diff open.cpp @ 498:342822c2d49a

Merge api-inversion branch (-r656:771, but I don't expect to return to that branch) into the trunk. I expect there to be minor performance regressions (e.g. in the SOAP server index cacheing, which I have forcibly removed) and minor unplugged memory leaks (e.g. in audioDB::query(), where I don't free up the datum). I hope that these leaks and performance regressions can be plugged in short order. I also expect that some (but maybe not all) of the issues currently addressed in the memory-leaks branch are superseded or fixed by this merge. There remains much work to be done; go forth and do it.
author mas01cr
date Sat, 10 Jan 2009 16:47:57 +0000
parents
children cc2b97d020b1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open.cpp	Sat Jan 10 16:47:57 2009 +0000
@@ -0,0 +1,157 @@
+#include "audioDB.h"
+extern "C" {
+#include "audioDB_API.h"
+#include "audioDB-internals.h"
+}
+
+static bool audiodb_check_header(adb_header_t *header) {
+  /* FIXME: use syslog() or write to stderr or something to give the
+     poor user some diagnostics. */
+  if(header->magic == O2_OLD_MAGIC) {
+    return false;
+  }
+  if(header->magic != O2_MAGIC) {
+    return false;
+  }
+  if(header->version != O2_FORMAT_VERSION) {
+    return false;
+  }
+  if(header->headerSize != O2_HEADERSIZE) {
+    return false;
+  }
+  return true;
+}
+
+static int audiodb_collect_keys(adb_t *adb) {
+  char *key_table = 0;
+  size_t key_table_length = 0;
+
+  if(adb->header->length > 0) {
+    unsigned nfiles = adb->header->numFiles;
+    key_table_length = ALIGN_PAGE_UP(nfiles * O2_FILETABLE_ENTRY_SIZE);
+    mmap_or_goto_error(char *, key_table, adb->header->fileTableOffset, key_table_length);
+    for (unsigned int k = 0; k < nfiles; k++) {
+      adb->keys->push_back(key_table + k*O2_FILETABLE_ENTRY_SIZE);
+      (*adb->keymap)[(key_table + k*O2_FILETABLE_ENTRY_SIZE)] = k;
+    }
+    munmap(key_table, key_table_length);
+  }
+
+  return 0;
+
+ error:
+  maybe_munmap(key_table, key_table_length);
+  return 1;
+}
+
+static int audiodb_collect_track_lengths(adb_t *adb) {
+  uint32_t *track_table = 0;
+  size_t track_table_length = 0;
+  if(adb->header->length > 0) {
+    unsigned nfiles = adb->header->numFiles;
+    track_table_length = ALIGN_PAGE_UP(nfiles * O2_TRACKTABLE_ENTRY_SIZE);
+    mmap_or_goto_error(uint32_t *, track_table, adb->header->trackTableOffset, track_table_length);
+    off_t offset = 0;
+    for (unsigned int k = 0; k < nfiles; k++) {
+      uint32_t track_length = track_table[k];
+      adb->track_lengths->push_back(track_length);
+      adb->track_offsets->push_back(offset);
+      offset += track_length * adb->header->dim * sizeof(double);
+    }
+    munmap(track_table, track_table_length);
+  }
+
+  return 0;
+
+ error:
+  maybe_munmap(track_table, track_table_length);
+  return 1;
+}
+
+adb_t *audiodb_open(const char *path, int flags) {
+  adb_t *adb = 0;
+  int fd = -1;
+
+  flags &= (O_RDONLY|O_RDWR);
+  fd = open(path, flags);
+  if(fd == -1) {
+    goto error;
+  }
+  if(acquire_lock(fd, flags == O_RDWR)) {
+    goto error;
+  }
+
+  adb = (adb_t *) calloc(1, sizeof(adb_t));
+  if(!adb) {
+    goto error;
+  }
+  adb->fd = fd;
+  adb->flags = flags;
+  adb->path = (char *) malloc(1+strlen(path));
+  if(!(adb->path)) {
+    goto error;
+  }
+  strcpy(adb->path, path);
+
+  adb->header = (adb_header_t *) malloc(sizeof(adb_header_t));
+  if(!(adb->header)) {
+    goto error;
+  }
+  if(read(fd, (char *) adb->header, O2_HEADERSIZE) != O2_HEADERSIZE) {
+    goto error;
+  }
+  if(!audiodb_check_header(adb->header)) {
+    goto error;
+  }
+
+  adb->keys = new std::vector<std::string>;
+  if(!adb->keys) {
+    goto error;
+  }
+  adb->keymap = new std::map<std::string,uint32_t>;
+  if(!adb->keymap) {
+    goto error;
+  }
+  if(audiodb_collect_keys(adb)) {
+    goto error;
+  }
+  adb->track_lengths = new std::vector<uint32_t>;
+  if(!adb->track_lengths) {
+    goto error;
+  }
+  adb->track_lengths->reserve(adb->header->numFiles);
+  adb->track_offsets = new std::vector<off_t>;
+  if(!adb->track_offsets) {
+    goto error;
+  }
+  adb->track_offsets->reserve(adb->header->numFiles);
+  if(audiodb_collect_track_lengths(adb)) {
+    goto error;
+  }
+  adb->cached_lsh = 0;
+  return adb;
+
+ error:
+  if(adb) {
+    if(adb->header) {
+      free(adb->header);
+    }
+    if(adb->path) {
+      free(adb->path);
+    }
+    if(adb->keys) {
+      delete adb->keys;
+    }
+    if(adb->keymap) {
+      delete adb->keymap;
+    }
+    if(adb->track_lengths) {
+      delete adb->track_lengths;
+    }
+    free(adb);
+  }
+  if(fd != -1) {
+    close(fd);
+  }
+  return NULL;
+}