Mercurial > hg > audiodb
diff common.cpp @ 239:2cc06e5b05a5
Merge refactoring branch.
Bug fixes:
* 64-bit powertable bug;
* -inf - -inf bug;
* use new times information;
* plus short track, O2_MAXFILES and structure padding ABI fixes (already
backported)
Major code changes:
* split source into functional units, known as 'files';
* Reporter class for accumulating and reporting on query results;
* much OAOOization, mostly from above: net 800 LOC (25%) shorter.
author | mas01cr |
---|---|
date | Thu, 13 Dec 2007 14:23:32 +0000 |
parents | |
children | 4dcb09f5fe85 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common.cpp Thu Dec 13 14:23:32 2007 +0000 @@ -0,0 +1,184 @@ +#include "audioDB.h" + +#if defined(O2_DEBUG) +void sigterm_action(int signal, siginfo_t *info, void *context) { + exit(128+signal); +} + +void sighup_action(int signal, siginfo_t *info, void *context) { + // FIXME: reread any configuration files +} +#endif + +void audioDB::get_lock(int fd, bool exclusive) { + struct flock lock; + int status; + + lock.l_type = exclusive ? F_WRLCK : F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; /* "the whole file" */ + + retry: + do { + status = fcntl(fd, F_SETLKW, &lock); + } while (status != 0 && errno == EINTR); + + if (status) { + if (errno == EAGAIN) { + sleep(1); + goto retry; + } else { + error("fcntl lock error", "", "fcntl"); + } + } +} + +void audioDB::release_lock(int fd) { + struct flock lock; + int status; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + status = fcntl(fd, F_SETLKW, &lock); + + if (status) + error("fcntl unlock error", "", "fcntl"); +} + +void audioDB::error(const char* a, const char* b, const char *sysFunc) { + if(isServer) { + /* FIXME: I think this is leaky -- we never delete err. actually + deleting it is tricky, though; it gets placed into some + soap-internal struct with uncertain extent... -- CSR, + 2007-10-01 */ + char *err = new char[256]; /* FIXME: overflows */ + snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : ""); + /* FIXME: actually we could usefully do with a properly structured + type, so that we can throw separate faultstring and details. + -- CSR, 2007-10-01 */ + throw(err); + } else { + std::cerr << a << ": " << b << std::endl; + if (sysFunc) { + perror(sysFunc); + } + exit(1); + } +} + +void audioDB::initDBHeader(const char* dbName) { + if ((dbfid = open(dbName, forWrite ? O_RDWR : O_RDONLY)) < 0) { + error("Can't open database file", dbName, "open"); + } + + get_lock(dbfid, forWrite); + // Get the database header info + dbH = new dbTableHeaderT(); + assert(dbH); + + if(read(dbfid, (char *) dbH, O2_HEADERSIZE) != O2_HEADERSIZE) { + error("error reading db header", dbName, "read"); + } + + if(dbH->magic == O2_OLD_MAGIC) { + // FIXME: if anyone ever complains, write the program to convert + // from the old audioDB format to the new... + error("database file has old O2 header", dbName); + } + + if(dbH->magic != O2_MAGIC) { + std::cerr << "expected: " << O2_MAGIC << ", got: " << dbH->magic << std::endl; + error("database file has incorrect header", dbName); + } + + if(dbH->version != O2_FORMAT_VERSION) { + error("database file has incorrect version", dbName); + } + + if(dbH->headerSize != O2_HEADERSIZE) { + error("sizeof(dbTableHeader) unexpected: platform ABI mismatch?", dbName); + } + + CHECKED_MMAP(char *, db, 0, getpagesize()); + + // Make some handy tables with correct types + if(forWrite || (dbH->length > 0)) { + if(forWrite) { + fileTableLength = dbH->trackTableOffset - dbH->fileTableOffset; + trackTableLength = dbH->dataOffset - dbH->trackTableOffset; + dataBufLength = dbH->timesTableOffset - dbH->dataOffset; + timesTableLength = dbH->powerTableOffset - dbH->timesTableOffset; + powerTableLength = dbH->l2normTableOffset - dbH->powerTableOffset; + l2normTableLength = dbH->dbSize - dbH->l2normTableOffset; + } else { + fileTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLESIZE); + trackTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_TRACKTABLESIZE); + dataBufLength = ALIGN_PAGE_UP(dbH->length); + timesTableLength = ALIGN_PAGE_UP(2*(dbH->length / dbH->dim)); + powerTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim); + l2normTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim); + } + CHECKED_MMAP(char *, fileTable, dbH->fileTableOffset, fileTableLength); + CHECKED_MMAP(unsigned *, trackTable, dbH->trackTableOffset, trackTableLength); + /* + * No more mmap() for dataBuf + * + * FIXME: Actually we do do the mmap() in the two cases where it's + * still "needed": in pointQuery and in l2norm if dbH->length is + * non-zero. Removing those cases too (and deleting the dataBuf + * variable completely) would be cool. -- CSR, 2007-11-19 + * + * CHECKED_MMAP(double *, dataBuf, dbH->dataOffset, dataBufLength); + */ + CHECKED_MMAP(double *, timesTable, dbH->timesTableOffset, timesTableLength); + CHECKED_MMAP(double *, powerTable, dbH->powerTableOffset, powerTableLength); + CHECKED_MMAP(double *, l2normTable, dbH->l2normTableOffset, l2normTableLength); + } +} + +void audioDB::initInputFile (const char *inFile) { + if (inFile) { + if ((infid = open(inFile, O_RDONLY)) < 0) { + error("can't open input file for reading", inFile, "open"); + } + + if (fstat(infid, &statbuf) < 0) { + error("fstat error finding size of input", inFile, "fstat"); + } + + if(dbH->dim == 0 && dbH->length == 0) { // empty database + // initialize with input dimensionality + if(read(infid, &dbH->dim, sizeof(unsigned)) != sizeof(unsigned)) { + error("short read of input file", inFile); + } + if(dbH->dim == 0) { + error("dimensionality of zero in input file", inFile); + } + } else { + unsigned test; + if(read(infid, &test, sizeof(unsigned)) != sizeof(unsigned)) { + error("short read of input file", inFile); + } + if(dbH->dim == 0) { + error("dimensionality of zero in input file", inFile); + } + if(dbH->dim != test) { + std::cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<std::endl; + error("feature dimensions do not match database table dimensions", inFile); + } + } + + if ((indata = (char *) mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0)) == (caddr_t) -1) { + error("mmap error for input", inFile, "mmap"); + } + } +} + +void audioDB::initTables(const char* dbName, const char* inFile = 0) { + initDBHeader(dbName); + initInputFile(inFile); +}