annotate common.cpp @ 249:1da9a9ed55a3

Slightly refactored the new trackSequenceQueryNNReporter so that it is a derived class of trackAveragingReporter. This reduces code duplication significantly. The reporter is still accessed via the nsequence QUERY directive from the command line.
author mas01mc
date Sun, 17 Feb 2008 16:39:57 +0000
parents 2cc06e5b05a5
children 4dcb09f5fe85
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@239 14 struct flock lock;
mas01cr@239 15 int status;
mas01cr@239 16
mas01cr@239 17 lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
mas01cr@239 18 lock.l_whence = SEEK_SET;
mas01cr@239 19 lock.l_start = 0;
mas01cr@239 20 lock.l_len = 0; /* "the whole file" */
mas01cr@239 21
mas01cr@239 22 retry:
mas01cr@239 23 do {
mas01cr@239 24 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@239 25 } while (status != 0 && errno == EINTR);
mas01cr@239 26
mas01cr@239 27 if (status) {
mas01cr@239 28 if (errno == EAGAIN) {
mas01cr@239 29 sleep(1);
mas01cr@239 30 goto retry;
mas01cr@239 31 } else {
mas01cr@239 32 error("fcntl lock error", "", "fcntl");
mas01cr@239 33 }
mas01cr@239 34 }
mas01cr@239 35 }
mas01cr@239 36
mas01cr@239 37 void audioDB::release_lock(int fd) {
mas01cr@239 38 struct flock lock;
mas01cr@239 39 int status;
mas01cr@239 40
mas01cr@239 41 lock.l_type = F_UNLCK;
mas01cr@239 42 lock.l_whence = SEEK_SET;
mas01cr@239 43 lock.l_start = 0;
mas01cr@239 44 lock.l_len = 0;
mas01cr@239 45
mas01cr@239 46 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@239 47
mas01cr@239 48 if (status)
mas01cr@239 49 error("fcntl unlock error", "", "fcntl");
mas01cr@239 50 }
mas01cr@239 51
mas01cr@239 52 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
mas01cr@239 53 if(isServer) {
mas01cr@239 54 /* FIXME: I think this is leaky -- we never delete err. actually
mas01cr@239 55 deleting it is tricky, though; it gets placed into some
mas01cr@239 56 soap-internal struct with uncertain extent... -- CSR,
mas01cr@239 57 2007-10-01 */
mas01cr@239 58 char *err = new char[256]; /* FIXME: overflows */
mas01cr@239 59 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
mas01cr@239 60 /* FIXME: actually we could usefully do with a properly structured
mas01cr@239 61 type, so that we can throw separate faultstring and details.
mas01cr@239 62 -- CSR, 2007-10-01 */
mas01cr@239 63 throw(err);
mas01cr@239 64 } else {
mas01cr@239 65 std::cerr << a << ": " << b << std::endl;
mas01cr@239 66 if (sysFunc) {
mas01cr@239 67 perror(sysFunc);
mas01cr@239 68 }
mas01cr@239 69 exit(1);
mas01cr@239 70 }
mas01cr@239 71 }
mas01cr@239 72
mas01cr@239 73 void audioDB::initDBHeader(const char* dbName) {
mas01cr@239 74 if ((dbfid = open(dbName, forWrite ? O_RDWR : O_RDONLY)) < 0) {
mas01cr@239 75 error("Can't open database file", dbName, "open");
mas01cr@239 76 }
mas01cr@239 77
mas01cr@239 78 get_lock(dbfid, forWrite);
mas01cr@239 79 // Get the database header info
mas01cr@239 80 dbH = new dbTableHeaderT();
mas01cr@239 81 assert(dbH);
mas01cr@239 82
mas01cr@239 83 if(read(dbfid, (char *) dbH, O2_HEADERSIZE) != O2_HEADERSIZE) {
mas01cr@239 84 error("error reading db header", dbName, "read");
mas01cr@239 85 }
mas01cr@239 86
mas01cr@239 87 if(dbH->magic == O2_OLD_MAGIC) {
mas01cr@239 88 // FIXME: if anyone ever complains, write the program to convert
mas01cr@239 89 // from the old audioDB format to the new...
mas01cr@239 90 error("database file has old O2 header", dbName);
mas01cr@239 91 }
mas01cr@239 92
mas01cr@239 93 if(dbH->magic != O2_MAGIC) {
mas01cr@239 94 std::cerr << "expected: " << O2_MAGIC << ", got: " << dbH->magic << std::endl;
mas01cr@239 95 error("database file has incorrect header", dbName);
mas01cr@239 96 }
mas01cr@239 97
mas01cr@239 98 if(dbH->version != O2_FORMAT_VERSION) {
mas01cr@239 99 error("database file has incorrect version", dbName);
mas01cr@239 100 }
mas01cr@239 101
mas01cr@239 102 if(dbH->headerSize != O2_HEADERSIZE) {
mas01cr@239 103 error("sizeof(dbTableHeader) unexpected: platform ABI mismatch?", dbName);
mas01cr@239 104 }
mas01cr@239 105
mas01cr@239 106 CHECKED_MMAP(char *, db, 0, getpagesize());
mas01cr@239 107
mas01cr@239 108 // Make some handy tables with correct types
mas01cr@239 109 if(forWrite || (dbH->length > 0)) {
mas01cr@239 110 if(forWrite) {
mas01cr@239 111 fileTableLength = dbH->trackTableOffset - dbH->fileTableOffset;
mas01cr@239 112 trackTableLength = dbH->dataOffset - dbH->trackTableOffset;
mas01cr@239 113 dataBufLength = dbH->timesTableOffset - dbH->dataOffset;
mas01cr@239 114 timesTableLength = dbH->powerTableOffset - dbH->timesTableOffset;
mas01cr@239 115 powerTableLength = dbH->l2normTableOffset - dbH->powerTableOffset;
mas01cr@239 116 l2normTableLength = dbH->dbSize - dbH->l2normTableOffset;
mas01cr@239 117 } else {
mas01cr@239 118 fileTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLESIZE);
mas01cr@239 119 trackTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_TRACKTABLESIZE);
mas01cr@239 120 dataBufLength = ALIGN_PAGE_UP(dbH->length);
mas01cr@239 121 timesTableLength = ALIGN_PAGE_UP(2*(dbH->length / dbH->dim));
mas01cr@239 122 powerTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01cr@239 123 l2normTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01cr@239 124 }
mas01cr@239 125 CHECKED_MMAP(char *, fileTable, dbH->fileTableOffset, fileTableLength);
mas01cr@239 126 CHECKED_MMAP(unsigned *, trackTable, dbH->trackTableOffset, trackTableLength);
mas01cr@239 127 /*
mas01cr@239 128 * No more mmap() for dataBuf
mas01cr@239 129 *
mas01cr@239 130 * FIXME: Actually we do do the mmap() in the two cases where it's
mas01cr@239 131 * still "needed": in pointQuery and in l2norm if dbH->length is
mas01cr@239 132 * non-zero. Removing those cases too (and deleting the dataBuf
mas01cr@239 133 * variable completely) would be cool. -- CSR, 2007-11-19
mas01cr@239 134 *
mas01cr@239 135 * CHECKED_MMAP(double *, dataBuf, dbH->dataOffset, dataBufLength);
mas01cr@239 136 */
mas01cr@239 137 CHECKED_MMAP(double *, timesTable, dbH->timesTableOffset, timesTableLength);
mas01cr@239 138 CHECKED_MMAP(double *, powerTable, dbH->powerTableOffset, powerTableLength);
mas01cr@239 139 CHECKED_MMAP(double *, l2normTable, dbH->l2normTableOffset, l2normTableLength);
mas01cr@239 140 }
mas01cr@239 141 }
mas01cr@239 142
mas01cr@239 143 void audioDB::initInputFile (const char *inFile) {
mas01cr@239 144 if (inFile) {
mas01cr@239 145 if ((infid = open(inFile, O_RDONLY)) < 0) {
mas01cr@239 146 error("can't open input file for reading", inFile, "open");
mas01cr@239 147 }
mas01cr@239 148
mas01cr@239 149 if (fstat(infid, &statbuf) < 0) {
mas01cr@239 150 error("fstat error finding size of input", inFile, "fstat");
mas01cr@239 151 }
mas01cr@239 152
mas01cr@239 153 if(dbH->dim == 0 && dbH->length == 0) { // empty database
mas01cr@239 154 // initialize with input dimensionality
mas01cr@239 155 if(read(infid, &dbH->dim, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 156 error("short read of input file", inFile);
mas01cr@239 157 }
mas01cr@239 158 if(dbH->dim == 0) {
mas01cr@239 159 error("dimensionality of zero in input file", inFile);
mas01cr@239 160 }
mas01cr@239 161 } else {
mas01cr@239 162 unsigned test;
mas01cr@239 163 if(read(infid, &test, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 164 error("short read of input file", inFile);
mas01cr@239 165 }
mas01cr@239 166 if(dbH->dim == 0) {
mas01cr@239 167 error("dimensionality of zero in input file", inFile);
mas01cr@239 168 }
mas01cr@239 169 if(dbH->dim != test) {
mas01cr@239 170 std::cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<std::endl;
mas01cr@239 171 error("feature dimensions do not match database table dimensions", inFile);
mas01cr@239 172 }
mas01cr@239 173 }
mas01cr@239 174
mas01cr@239 175 if ((indata = (char *) mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0)) == (caddr_t) -1) {
mas01cr@239 176 error("mmap error for input", inFile, "mmap");
mas01cr@239 177 }
mas01cr@239 178 }
mas01cr@239 179 }
mas01cr@239 180
mas01cr@239 181 void audioDB::initTables(const char* dbName, const char* inFile = 0) {
mas01cr@239 182 initDBHeader(dbName);
mas01cr@239 183 initInputFile(inFile);
mas01cr@239 184 }