annotate common.cpp @ 277:abfb26e08d9c audiodb-debian

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