annotate common.cpp @ 469:d3afc91d205d api-inversion

Move audioDB::query over to audioDB.cpp At the same time, remove all the abstraction violations in audioDB::query, which came in two flavours: use of dbH->numFiles, which is dealt with by getting the database status instead (and is eventually unnecessary, being only needed now because reporters are implemented in terms of vectors indexed by ID), and use of fileTable in reporter's report functions (dealt with by passing in the adb instead). To actually implement reporting as of now, we continue to use stuff from audioDB-internals.h; maybe someday we will be clean and shiny.
author mas01cr
date Wed, 31 Dec 2008 15:44:16 +0000
parents 913a95f06998
children 8fb85fbcaba6
rev   line source
mas01cr@239 1 #include "audioDB.h"
mas01cr@392 2 extern "C" {
mas01cr@392 3 #include "audioDB_API.h"
mas01cr@402 4 #include "audioDB-internals.h"
mas01cr@392 5 }
mas01cr@239 6
mas01cr@239 7 #if defined(O2_DEBUG)
mas01cr@239 8 void sigterm_action(int signal, siginfo_t *info, void *context) {
mas01cr@239 9 exit(128+signal);
mas01cr@239 10 }
mas01cr@239 11
mas01cr@239 12 void sighup_action(int signal, siginfo_t *info, void *context) {
mas01cr@239 13 // FIXME: reread any configuration files
mas01cr@239 14 }
mas01cr@239 15 #endif
mas01cr@239 16
mas01cr@385 17 int acquire_lock(int fd, bool exclusive) {
mas01cr@239 18 struct flock lock;
mas01cr@239 19 int status;
mas01cr@239 20
mas01cr@239 21 lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
mas01cr@239 22 lock.l_whence = SEEK_SET;
mas01cr@239 23 lock.l_start = 0;
mas01cr@239 24 lock.l_len = 0; /* "the whole file" */
mas01cr@239 25
mas01cr@239 26 retry:
mas01cr@239 27 do {
mas01cr@239 28 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@239 29 } while (status != 0 && errno == EINTR);
mas01cr@239 30
mas01cr@239 31 if (status) {
mas01cr@239 32 if (errno == EAGAIN) {
mas01cr@239 33 sleep(1);
mas01cr@239 34 goto retry;
mas01cr@239 35 } else {
mas01cr@385 36 return status;
mas01cr@239 37 }
mas01cr@239 38 }
mas01cr@385 39 return 0;
mas01cr@239 40 }
mas01cr@239 41
mas01cr@385 42 int divest_lock(int fd) {
mas01cr@239 43 struct flock lock;
mas01cr@239 44
mas01cr@239 45 lock.l_type = F_UNLCK;
mas01cr@239 46 lock.l_whence = SEEK_SET;
mas01cr@239 47 lock.l_start = 0;
mas01cr@239 48 lock.l_len = 0;
mas01cr@239 49
mas01cr@385 50 return fcntl(fd, F_SETLKW, &lock);
mas01cr@385 51 }
mas01cr@239 52
mas01cr@385 53 void audioDB::get_lock(int fd, bool exclusive) {
mas01cr@385 54 if(acquire_lock(fd, exclusive)) {
mas01cr@385 55 error("fcntl lock error", "", "fcntl");
mas01cr@385 56 }
mas01cr@385 57 }
mas01cr@385 58
mas01cr@385 59 void audioDB::release_lock(int fd) {
mas01cr@385 60 if (divest_lock(fd)) {
mas01cr@239 61 error("fcntl unlock error", "", "fcntl");
mas01cr@385 62 }
mas01cr@239 63 }
mas01cr@239 64
mas01cr@239 65 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
mas01ik@355 66
mas01ik@355 67
mas01ik@355 68 if(isServer) {
mas01cr@370 69 /* FIXME: I think this is leaky -- we never delete err.
mas01cr@370 70 actually deleting it is tricky, though; it gets placed into
mas01cr@370 71 some soap-internal struct with uncertain extent... -- CSR,
mas01cr@370 72 2007-10-01 */
mas01cr@370 73 char *err = new char[256]; /* FIXME: overflows */
mas01cr@370 74 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
mas01cr@370 75 /* FIXME: actually we could usefully do with a properly
mas01cr@370 76 structured type, so that we can throw separate faultstring
mas01cr@370 77 and details. -- CSR, 2007-10-01 */
mas01ik@355 78 throw(err);
mas01ik@355 79 } else if (UseApiError){
mas01ik@355 80 apierrortemp=-1;
mas01ik@355 81 throw(apierrortemp);
mas01ik@355 82 } else {
mas01ik@355 83 std::cerr << a << ": " << b << std::endl;
mas01ik@355 84 if (sysFunc) {
mas01ik@355 85 perror(sysFunc);
mas01ik@355 86 }
mas01ik@355 87 exit(1);
mas01cr@239 88 }
mas01ik@355 89
mas01cr@239 90 }
mas01cr@239 91
mas01cr@284 92 void audioDB::initRNG() {
mas01cr@284 93 rng = gsl_rng_alloc(gsl_rng_mt19937);
mas01cr@284 94 if(!rng) {
mas01cr@284 95 error("could not allocate Random Number Generator");
mas01cr@284 96 }
mas01cr@284 97 /* FIXME: maybe we should use a real source of entropy? */
mas01cr@284 98 gsl_rng_set(rng, time(NULL));
mas01cr@284 99 }
mas01cr@284 100
mas01cr@239 101 void audioDB::initDBHeader(const char* dbName) {
mas01cr@392 102 if(!adb) {
mas01cr@395 103 adb = audiodb_open(dbName, forWrite ? O_RDWR : O_RDONLY);
mas01cr@395 104 if(!adb) {
mas01cr@395 105 error("Failed to open database", dbName);
mas01cr@395 106 }
mas01cr@239 107 }
mas01cr@392 108 dbfid = adb->fd;
mas01cr@392 109 dbH = adb->header;
mas01cr@239 110
mas01cr@239 111 // Make some handy tables with correct types
mas01cr@239 112 if(forWrite || (dbH->length > 0)) {
mas01cr@239 113 if(forWrite) {
mas01cr@239 114 fileTableLength = dbH->trackTableOffset - dbH->fileTableOffset;
mas01cr@239 115 trackTableLength = dbH->dataOffset - dbH->trackTableOffset;
mas01cr@239 116 timesTableLength = dbH->powerTableOffset - dbH->timesTableOffset;
mas01cr@239 117 powerTableLength = dbH->l2normTableOffset - dbH->powerTableOffset;
mas01cr@239 118 l2normTableLength = dbH->dbSize - dbH->l2normTableOffset;
mas01cr@239 119 } else {
mas01cr@256 120 fileTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01cr@256 121 trackTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_TRACKTABLE_ENTRY_SIZE);
mas01mc@324 122 if( dbH->flags & O2_FLAG_LARGE_ADB ){
mas01mc@324 123 timesTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01mc@324 124 powerTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01mc@324 125 l2normTableLength = 0;
mas01mc@324 126 }
mas01mc@324 127 else{
mas01mc@324 128 timesTableLength = ALIGN_PAGE_UP(2*(dbH->length / dbH->dim));
mas01mc@324 129 powerTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01mc@324 130 l2normTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01mc@324 131 }
mas01cr@239 132 }
mas01cr@239 133 CHECKED_MMAP(char *, fileTable, dbH->fileTableOffset, fileTableLength);
mas01cr@239 134 CHECKED_MMAP(unsigned *, trackTable, dbH->trackTableOffset, trackTableLength);
mas01mc@324 135 if( dbH->flags & O2_FLAG_LARGE_ADB ){
mas01mc@324 136 CHECKED_MMAP(char *, featureFileNameTable, dbH->dataOffset, fileTableLength);
mas01mc@324 137 if( dbH->flags & O2_FLAG_TIMES )
mas01mc@324 138 CHECKED_MMAP(char *, timesFileNameTable, dbH->timesTableOffset, fileTableLength);
mas01mc@324 139 if( dbH->flags & O2_FLAG_POWER )
mas01mc@324 140 CHECKED_MMAP(char *, powerFileNameTable, dbH->powerTableOffset, fileTableLength);
mas01mc@324 141 }
mas01mc@324 142 else{
mas01mc@324 143 CHECKED_MMAP(double *, timesTable, dbH->timesTableOffset, timesTableLength);
mas01mc@324 144 CHECKED_MMAP(double *, powerTable, dbH->powerTableOffset, powerTableLength);
mas01mc@324 145 CHECKED_MMAP(double *, l2normTable, dbH->l2normTableOffset, l2normTableLength);
mas01mc@324 146 }
mas01cr@239 147 }
mas01cr@239 148 }
mas01cr@239 149
mas01cr@454 150 void audioDB::initInputFile (const char *inFile) {
mas01cr@239 151 if (inFile) {
mas01cr@239 152 if ((infid = open(inFile, O_RDONLY)) < 0) {
mas01cr@239 153 error("can't open input file for reading", inFile, "open");
mas01cr@239 154 }
mas01cr@239 155
mas01cr@239 156 if (fstat(infid, &statbuf) < 0) {
mas01cr@239 157 error("fstat error finding size of input", inFile, "fstat");
mas01cr@239 158 }
mas01cr@239 159
mas01cr@239 160 if(dbH->dim == 0 && dbH->length == 0) { // empty database
mas01cr@239 161 // initialize with input dimensionality
mas01cr@239 162 if(read(infid, &dbH->dim, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 163 error("short read of input file", inFile);
mas01cr@239 164 }
mas01cr@239 165 if(dbH->dim == 0) {
mas01cr@239 166 error("dimensionality of zero in input file", inFile);
mas01cr@239 167 }
mas01cr@239 168 } else {
mas01cr@239 169 unsigned test;
mas01cr@239 170 if(read(infid, &test, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 171 error("short read of input file", inFile);
mas01cr@239 172 }
mas01cr@239 173 if(dbH->dim == 0) {
mas01cr@239 174 error("dimensionality of zero in input file", inFile);
mas01cr@239 175 }
mas01cr@239 176 if(dbH->dim != test) {
mas01cr@239 177 std::cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<std::endl;
mas01cr@239 178 error("feature dimensions do not match database table dimensions", inFile);
mas01cr@239 179 }
mas01cr@239 180 }
mas01cr@239 181 }
mas01cr@239 182 }
mas01cr@239 183
mas01mc@292 184 void audioDB::initTables(const char* dbName, const char* inFile) {
mas01cr@284 185 /* FIXME: initRNG() really logically belongs in the audioDB
mas01cr@284 186 contructor. However, there are of the order of four constructors
mas01cr@284 187 at the moment, and more to come from API implementation. Given
mas01cr@284 188 that duplication, I think this is the least worst place to put
mas01cr@284 189 it; the assumption is that nothing which doesn't look at a
mas01cr@284 190 database will need an RNG. -- CSR, 2008-07-02 */
mas01cr@284 191 initRNG();
mas01cr@239 192 initDBHeader(dbName);
mas01mc@292 193 if(inFile)
mas01mc@292 194 initInputFile(inFile);
mas01cr@239 195 }
mas01mc@292 196
mas01mc@324 197 // If name is relative path, side effect name with prefix/name
mas01mc@324 198 // Do not free original pointer
mas01mc@324 199 void audioDB::prefix_name(char** const name, const char* prefix){
mas01mc@324 200 // No prefix if prefix is empty
mas01mc@324 201 if(!prefix)
mas01mc@324 202 return;
mas01mc@324 203 // Allocate new memory, keep old memory
mas01mc@324 204 assert(name && *name);
mas01mc@324 205 if (strlen(*name) + strlen(prefix) + 1 > O2_MAXFILESTR)
mas01mc@324 206 error("error: path prefix + filename too long",prefix);
mas01mc@324 207 // Do not prefix absolute path+filename
mas01mc@324 208 if(**name=='/')
mas01mc@324 209 return;
mas01mc@324 210 // OK to prefix relative path+filename
mas01mc@324 211 char* prefixedName = (char*) malloc(O2_MAXFILESTR);
mas01mc@324 212 sprintf(prefixedName, "%s/%s", prefix, *name);
mas01mc@324 213 *name = prefixedName; // side effect new name to old name
mas01mc@324 214 }
mas01cr@469 215
mas01cr@469 216 void audioDB::insertTimeStamps(unsigned numVectors, std::ifstream *timesFile, double *timesdata) {
mas01cr@469 217 assert(usingTimes);
mas01cr@469 218
mas01cr@469 219 unsigned numtimes = 0;
mas01cr@469 220
mas01cr@469 221 if(!timesFile->is_open()) {
mas01cr@469 222 error("problem opening times file on timestamped database", timesFileName);
mas01cr@469 223 }
mas01cr@469 224
mas01cr@469 225 double timepoint, next;
mas01cr@469 226 *timesFile >> timepoint;
mas01cr@469 227 if (timesFile->eof()) {
mas01cr@469 228 error("no entries in times file", timesFileName);
mas01cr@469 229 }
mas01cr@469 230 numtimes++;
mas01cr@469 231 do {
mas01cr@469 232 *timesFile >> next;
mas01cr@469 233 if (timesFile->eof()) {
mas01cr@469 234 break;
mas01cr@469 235 }
mas01cr@469 236 numtimes++;
mas01cr@469 237 timesdata[0] = timepoint;
mas01cr@469 238 timepoint = (timesdata[1] = next);
mas01cr@469 239 timesdata += 2;
mas01cr@469 240 } while (numtimes < numVectors + 1);
mas01cr@469 241
mas01cr@469 242 if (numtimes < numVectors + 1) {
mas01cr@469 243 error("too few timepoints in times file", timesFileName);
mas01cr@469 244 }
mas01cr@469 245
mas01cr@469 246 *timesFile >> next;
mas01cr@469 247 if (!timesFile->eof()) {
mas01cr@469 248 error("too many timepoints in times file", timesFileName);
mas01cr@469 249 }
mas01cr@469 250 }