annotate common.cpp @ 491:29d28cfe0222 api-inversion

More removal of audiodb_query() There's still a certain amount of code duplication between these test files (for example, almost all of 0011/ and 0012/ are exactly the same), but it's all improvement.
author mas01cr
date Sat, 10 Jan 2009 15:33:02 +0000
parents d3afc91d205d
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 }