annotate common.cpp @ 524:469b50a3dd84 multiprobeLSH

Fixed a bug in LSH hashtable writing to disk that doesn't always sort the t2 entries into strict weak ordering. Now it does. Lots of debugging informational code inserted.
author mas01mc
date Wed, 28 Jan 2009 16:02:17 +0000
parents cc2b97d020b1
children 4eedc18634f5
rev   line source
mas01cr@239 1 #include "audioDB.h"
mas01cr@239 2
mas01cr@239 3 #if defined(O2_DEBUG)
mas01cr@239 4 void sigterm_action(int signal, siginfo_t *info, void *context) {
mas01cr@239 5 exit(128+signal);
mas01cr@239 6 }
mas01cr@239 7
mas01cr@239 8 void sighup_action(int signal, siginfo_t *info, void *context) {
mas01cr@239 9 // FIXME: reread any configuration files
mas01cr@239 10 }
mas01cr@239 11 #endif
mas01cr@239 12
mas01cr@239 13 void audioDB::get_lock(int fd, bool exclusive) {
mas01cr@498 14 if(acquire_lock(fd, exclusive)) {
mas01cr@498 15 error("fcntl lock error", "", "fcntl");
mas01cr@239 16 }
mas01cr@239 17 }
mas01cr@239 18
mas01cr@239 19 void audioDB::release_lock(int fd) {
mas01cr@498 20 if (divest_lock(fd)) {
mas01cr@239 21 error("fcntl unlock error", "", "fcntl");
mas01cr@498 22 }
mas01cr@239 23 }
mas01cr@239 24
mas01cr@239 25 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
mas01ik@355 26
mas01ik@355 27
mas01ik@355 28 if(isServer) {
mas01cr@370 29 /* FIXME: I think this is leaky -- we never delete err.
mas01cr@370 30 actually deleting it is tricky, though; it gets placed into
mas01cr@370 31 some soap-internal struct with uncertain extent... -- CSR,
mas01cr@370 32 2007-10-01 */
mas01cr@370 33 char *err = new char[256]; /* FIXME: overflows */
mas01cr@370 34 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
mas01cr@370 35 /* FIXME: actually we could usefully do with a properly
mas01cr@370 36 structured type, so that we can throw separate faultstring
mas01cr@370 37 and details. -- CSR, 2007-10-01 */
mas01ik@355 38 throw(err);
mas01ik@355 39 } else {
mas01ik@355 40 std::cerr << a << ": " << b << std::endl;
mas01ik@355 41 if (sysFunc) {
mas01ik@355 42 perror(sysFunc);
mas01ik@355 43 }
mas01ik@355 44 exit(1);
mas01cr@239 45 }
mas01cr@239 46 }
mas01cr@239 47
mas01cr@284 48 void audioDB::initRNG() {
mas01cr@284 49 rng = gsl_rng_alloc(gsl_rng_mt19937);
mas01cr@284 50 if(!rng) {
mas01cr@284 51 error("could not allocate Random Number Generator");
mas01cr@284 52 }
mas01cr@284 53 /* FIXME: maybe we should use a real source of entropy? */
mas01cr@284 54 gsl_rng_set(rng, time(NULL));
mas01cr@284 55 }
mas01cr@284 56
mas01cr@239 57 void audioDB::initDBHeader(const char* dbName) {
mas01cr@498 58 if(!adb) {
mas01cr@498 59 adb = audiodb_open(dbName, forWrite ? O_RDWR : O_RDONLY);
mas01cr@498 60 if(!adb) {
mas01cr@498 61 error("Failed to open database", dbName);
mas01cr@498 62 }
mas01cr@239 63 }
mas01cr@498 64 dbfid = adb->fd;
mas01cr@498 65 dbH = adb->header;
mas01cr@239 66
mas01cr@239 67 // Make some handy tables with correct types
mas01cr@239 68 if(forWrite || (dbH->length > 0)) {
mas01cr@239 69 if(forWrite) {
mas01cr@239 70 fileTableLength = dbH->trackTableOffset - dbH->fileTableOffset;
mas01cr@239 71 trackTableLength = dbH->dataOffset - dbH->trackTableOffset;
mas01cr@239 72 timesTableLength = dbH->powerTableOffset - dbH->timesTableOffset;
mas01cr@239 73 powerTableLength = dbH->l2normTableOffset - dbH->powerTableOffset;
mas01cr@239 74 l2normTableLength = dbH->dbSize - dbH->l2normTableOffset;
mas01cr@239 75 } else {
mas01cr@256 76 fileTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01cr@256 77 trackTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_TRACKTABLE_ENTRY_SIZE);
mas01mc@324 78 if( dbH->flags & O2_FLAG_LARGE_ADB ){
mas01mc@324 79 timesTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01mc@324 80 powerTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01mc@324 81 l2normTableLength = 0;
mas01mc@324 82 }
mas01mc@324 83 else{
mas01mc@324 84 timesTableLength = ALIGN_PAGE_UP(2*(dbH->length / dbH->dim));
mas01mc@324 85 powerTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01mc@324 86 l2normTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01mc@324 87 }
mas01cr@239 88 }
mas01cr@239 89 CHECKED_MMAP(char *, fileTable, dbH->fileTableOffset, fileTableLength);
mas01cr@239 90 CHECKED_MMAP(unsigned *, trackTable, dbH->trackTableOffset, trackTableLength);
mas01mc@324 91 if( dbH->flags & O2_FLAG_LARGE_ADB ){
mas01mc@324 92 CHECKED_MMAP(char *, featureFileNameTable, dbH->dataOffset, fileTableLength);
mas01mc@324 93 if( dbH->flags & O2_FLAG_TIMES )
mas01mc@324 94 CHECKED_MMAP(char *, timesFileNameTable, dbH->timesTableOffset, fileTableLength);
mas01mc@324 95 if( dbH->flags & O2_FLAG_POWER )
mas01mc@324 96 CHECKED_MMAP(char *, powerFileNameTable, dbH->powerTableOffset, fileTableLength);
mas01mc@324 97 }
mas01mc@324 98 else{
mas01mc@324 99 CHECKED_MMAP(double *, timesTable, dbH->timesTableOffset, timesTableLength);
mas01mc@324 100 CHECKED_MMAP(double *, powerTable, dbH->powerTableOffset, powerTableLength);
mas01mc@324 101 CHECKED_MMAP(double *, l2normTable, dbH->l2normTableOffset, l2normTableLength);
mas01mc@324 102 }
mas01cr@239 103 }
mas01cr@239 104 }
mas01cr@239 105
mas01cr@498 106 void audioDB::initInputFile (const char *inFile) {
mas01cr@239 107 if (inFile) {
mas01cr@239 108 if ((infid = open(inFile, O_RDONLY)) < 0) {
mas01cr@239 109 error("can't open input file for reading", inFile, "open");
mas01cr@239 110 }
mas01cr@239 111
mas01cr@239 112 if (fstat(infid, &statbuf) < 0) {
mas01cr@239 113 error("fstat error finding size of input", inFile, "fstat");
mas01cr@239 114 }
mas01cr@239 115
mas01cr@239 116 if(dbH->dim == 0 && dbH->length == 0) { // empty database
mas01cr@239 117 // initialize with input dimensionality
mas01cr@239 118 if(read(infid, &dbH->dim, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 119 error("short read of input file", inFile);
mas01cr@239 120 }
mas01cr@239 121 if(dbH->dim == 0) {
mas01cr@239 122 error("dimensionality of zero in input file", inFile);
mas01cr@239 123 }
mas01cr@239 124 } else {
mas01cr@239 125 unsigned test;
mas01cr@239 126 if(read(infid, &test, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 127 error("short read of input file", inFile);
mas01cr@239 128 }
mas01cr@239 129 if(dbH->dim == 0) {
mas01cr@239 130 error("dimensionality of zero in input file", inFile);
mas01cr@239 131 }
mas01cr@239 132 if(dbH->dim != test) {
mas01cr@239 133 std::cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<std::endl;
mas01cr@239 134 error("feature dimensions do not match database table dimensions", inFile);
mas01cr@239 135 }
mas01cr@239 136 }
mas01cr@239 137 }
mas01cr@239 138 }
mas01cr@239 139
mas01mc@292 140 void audioDB::initTables(const char* dbName, const char* inFile) {
mas01cr@284 141 /* FIXME: initRNG() really logically belongs in the audioDB
mas01cr@284 142 contructor. However, there are of the order of four constructors
mas01cr@284 143 at the moment, and more to come from API implementation. Given
mas01cr@284 144 that duplication, I think this is the least worst place to put
mas01cr@284 145 it; the assumption is that nothing which doesn't look at a
mas01cr@284 146 database will need an RNG. -- CSR, 2008-07-02 */
mas01cr@284 147 initRNG();
mas01cr@239 148 initDBHeader(dbName);
mas01mc@292 149 if(inFile)
mas01mc@292 150 initInputFile(inFile);
mas01cr@239 151 }
mas01mc@292 152
mas01mc@324 153 // If name is relative path, side effect name with prefix/name
mas01mc@324 154 // Do not free original pointer
mas01mc@324 155 void audioDB::prefix_name(char** const name, const char* prefix){
mas01mc@324 156 // No prefix if prefix is empty
mas01mc@324 157 if(!prefix)
mas01mc@324 158 return;
mas01mc@324 159 // Allocate new memory, keep old memory
mas01mc@324 160 assert(name && *name);
mas01mc@324 161 if (strlen(*name) + strlen(prefix) + 1 > O2_MAXFILESTR)
mas01mc@324 162 error("error: path prefix + filename too long",prefix);
mas01mc@324 163 // Do not prefix absolute path+filename
mas01mc@324 164 if(**name=='/')
mas01mc@324 165 return;
mas01mc@324 166 // OK to prefix relative path+filename
mas01mc@324 167 char* prefixedName = (char*) malloc(O2_MAXFILESTR);
mas01mc@324 168 sprintf(prefixedName, "%s/%s", prefix, *name);
mas01mc@324 169 *name = prefixedName; // side effect new name to old name
mas01mc@324 170 }
mas01cr@498 171
mas01cr@498 172 void audioDB::insertTimeStamps(unsigned numVectors, std::ifstream *timesFile, double *timesdata) {
mas01cr@498 173 assert(usingTimes);
mas01cr@498 174
mas01cr@498 175 unsigned numtimes = 0;
mas01cr@498 176
mas01cr@498 177 if(!timesFile->is_open()) {
mas01cr@498 178 error("problem opening times file on timestamped database", timesFileName);
mas01cr@498 179 }
mas01cr@498 180
mas01cr@498 181 double timepoint, next;
mas01cr@498 182 *timesFile >> timepoint;
mas01cr@498 183 if (timesFile->eof()) {
mas01cr@498 184 error("no entries in times file", timesFileName);
mas01cr@498 185 }
mas01cr@498 186 numtimes++;
mas01cr@498 187 do {
mas01cr@498 188 *timesFile >> next;
mas01cr@498 189 if (timesFile->eof()) {
mas01cr@498 190 break;
mas01cr@498 191 }
mas01cr@498 192 numtimes++;
mas01cr@498 193 timesdata[0] = timepoint;
mas01cr@498 194 timepoint = (timesdata[1] = next);
mas01cr@498 195 timesdata += 2;
mas01cr@498 196 } while (numtimes < numVectors + 1);
mas01cr@498 197
mas01cr@498 198 if (numtimes < numVectors + 1) {
mas01cr@498 199 error("too few timepoints in times file", timesFileName);
mas01cr@498 200 }
mas01cr@498 201
mas01cr@498 202 *timesFile >> next;
mas01cr@498 203 if (!timesFile->eof()) {
mas01cr@498 204 error("too many timepoints in times file", timesFileName);
mas01cr@498 205 }
mas01cr@498 206 }