annotate common.cpp @ 497:9d8aee621afb api-inversion

More libtests fixups. Include audiodb_close() calls everywhere (whoops). Add the facility to run tests under valgrind. Unfortunately the error-exitcode flag doesn't actually cause an error exit if the only thing wrong is memory leaks, but it will if there are actual memory errors, which is a start.
author mas01cr
date Sat, 10 Jan 2009 16:07:43 +0000
parents 8fb85fbcaba6
children
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 void audioDB::get_lock(int fd, bool exclusive) {
mas01cr@385 18 if(acquire_lock(fd, exclusive)) {
mas01cr@385 19 error("fcntl lock error", "", "fcntl");
mas01cr@385 20 }
mas01cr@385 21 }
mas01cr@385 22
mas01cr@385 23 void audioDB::release_lock(int fd) {
mas01cr@385 24 if (divest_lock(fd)) {
mas01cr@239 25 error("fcntl unlock error", "", "fcntl");
mas01cr@385 26 }
mas01cr@239 27 }
mas01cr@239 28
mas01cr@239 29 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
mas01ik@355 30
mas01ik@355 31
mas01ik@355 32 if(isServer) {
mas01cr@370 33 /* FIXME: I think this is leaky -- we never delete err.
mas01cr@370 34 actually deleting it is tricky, though; it gets placed into
mas01cr@370 35 some soap-internal struct with uncertain extent... -- CSR,
mas01cr@370 36 2007-10-01 */
mas01cr@370 37 char *err = new char[256]; /* FIXME: overflows */
mas01cr@370 38 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
mas01cr@370 39 /* FIXME: actually we could usefully do with a properly
mas01cr@370 40 structured type, so that we can throw separate faultstring
mas01cr@370 41 and details. -- CSR, 2007-10-01 */
mas01ik@355 42 throw(err);
mas01ik@355 43 } else {
mas01ik@355 44 std::cerr << a << ": " << b << std::endl;
mas01ik@355 45 if (sysFunc) {
mas01ik@355 46 perror(sysFunc);
mas01ik@355 47 }
mas01ik@355 48 exit(1);
mas01cr@239 49 }
mas01cr@239 50 }
mas01cr@239 51
mas01cr@284 52 void audioDB::initRNG() {
mas01cr@284 53 rng = gsl_rng_alloc(gsl_rng_mt19937);
mas01cr@284 54 if(!rng) {
mas01cr@284 55 error("could not allocate Random Number Generator");
mas01cr@284 56 }
mas01cr@284 57 /* FIXME: maybe we should use a real source of entropy? */
mas01cr@284 58 gsl_rng_set(rng, time(NULL));
mas01cr@284 59 }
mas01cr@284 60
mas01cr@239 61 void audioDB::initDBHeader(const char* dbName) {
mas01cr@392 62 if(!adb) {
mas01cr@395 63 adb = audiodb_open(dbName, forWrite ? O_RDWR : O_RDONLY);
mas01cr@395 64 if(!adb) {
mas01cr@395 65 error("Failed to open database", dbName);
mas01cr@395 66 }
mas01cr@239 67 }
mas01cr@392 68 dbfid = adb->fd;
mas01cr@392 69 dbH = adb->header;
mas01cr@239 70
mas01cr@239 71 // Make some handy tables with correct types
mas01cr@239 72 if(forWrite || (dbH->length > 0)) {
mas01cr@239 73 if(forWrite) {
mas01cr@239 74 fileTableLength = dbH->trackTableOffset - dbH->fileTableOffset;
mas01cr@239 75 trackTableLength = dbH->dataOffset - dbH->trackTableOffset;
mas01cr@239 76 timesTableLength = dbH->powerTableOffset - dbH->timesTableOffset;
mas01cr@239 77 powerTableLength = dbH->l2normTableOffset - dbH->powerTableOffset;
mas01cr@239 78 l2normTableLength = dbH->dbSize - dbH->l2normTableOffset;
mas01cr@239 79 } else {
mas01cr@256 80 fileTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01cr@256 81 trackTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_TRACKTABLE_ENTRY_SIZE);
mas01mc@324 82 if( dbH->flags & O2_FLAG_LARGE_ADB ){
mas01mc@324 83 timesTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01mc@324 84 powerTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLE_ENTRY_SIZE);
mas01mc@324 85 l2normTableLength = 0;
mas01mc@324 86 }
mas01mc@324 87 else{
mas01mc@324 88 timesTableLength = ALIGN_PAGE_UP(2*(dbH->length / dbH->dim));
mas01mc@324 89 powerTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01mc@324 90 l2normTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
mas01mc@324 91 }
mas01cr@239 92 }
mas01cr@239 93 CHECKED_MMAP(char *, fileTable, dbH->fileTableOffset, fileTableLength);
mas01cr@239 94 CHECKED_MMAP(unsigned *, trackTable, dbH->trackTableOffset, trackTableLength);
mas01mc@324 95 if( dbH->flags & O2_FLAG_LARGE_ADB ){
mas01mc@324 96 CHECKED_MMAP(char *, featureFileNameTable, dbH->dataOffset, fileTableLength);
mas01mc@324 97 if( dbH->flags & O2_FLAG_TIMES )
mas01mc@324 98 CHECKED_MMAP(char *, timesFileNameTable, dbH->timesTableOffset, fileTableLength);
mas01mc@324 99 if( dbH->flags & O2_FLAG_POWER )
mas01mc@324 100 CHECKED_MMAP(char *, powerFileNameTable, dbH->powerTableOffset, fileTableLength);
mas01mc@324 101 }
mas01mc@324 102 else{
mas01mc@324 103 CHECKED_MMAP(double *, timesTable, dbH->timesTableOffset, timesTableLength);
mas01mc@324 104 CHECKED_MMAP(double *, powerTable, dbH->powerTableOffset, powerTableLength);
mas01mc@324 105 CHECKED_MMAP(double *, l2normTable, dbH->l2normTableOffset, l2normTableLength);
mas01mc@324 106 }
mas01cr@239 107 }
mas01cr@239 108 }
mas01cr@239 109
mas01cr@454 110 void audioDB::initInputFile (const char *inFile) {
mas01cr@239 111 if (inFile) {
mas01cr@239 112 if ((infid = open(inFile, O_RDONLY)) < 0) {
mas01cr@239 113 error("can't open input file for reading", inFile, "open");
mas01cr@239 114 }
mas01cr@239 115
mas01cr@239 116 if (fstat(infid, &statbuf) < 0) {
mas01cr@239 117 error("fstat error finding size of input", inFile, "fstat");
mas01cr@239 118 }
mas01cr@239 119
mas01cr@239 120 if(dbH->dim == 0 && dbH->length == 0) { // empty database
mas01cr@239 121 // initialize with input dimensionality
mas01cr@239 122 if(read(infid, &dbH->dim, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 123 error("short read of input file", inFile);
mas01cr@239 124 }
mas01cr@239 125 if(dbH->dim == 0) {
mas01cr@239 126 error("dimensionality of zero in input file", inFile);
mas01cr@239 127 }
mas01cr@239 128 } else {
mas01cr@239 129 unsigned test;
mas01cr@239 130 if(read(infid, &test, sizeof(unsigned)) != sizeof(unsigned)) {
mas01cr@239 131 error("short read of input file", inFile);
mas01cr@239 132 }
mas01cr@239 133 if(dbH->dim == 0) {
mas01cr@239 134 error("dimensionality of zero in input file", inFile);
mas01cr@239 135 }
mas01cr@239 136 if(dbH->dim != test) {
mas01cr@239 137 std::cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<std::endl;
mas01cr@239 138 error("feature dimensions do not match database table dimensions", inFile);
mas01cr@239 139 }
mas01cr@239 140 }
mas01cr@239 141 }
mas01cr@239 142 }
mas01cr@239 143
mas01mc@292 144 void audioDB::initTables(const char* dbName, const char* inFile) {
mas01cr@284 145 /* FIXME: initRNG() really logically belongs in the audioDB
mas01cr@284 146 contructor. However, there are of the order of four constructors
mas01cr@284 147 at the moment, and more to come from API implementation. Given
mas01cr@284 148 that duplication, I think this is the least worst place to put
mas01cr@284 149 it; the assumption is that nothing which doesn't look at a
mas01cr@284 150 database will need an RNG. -- CSR, 2008-07-02 */
mas01cr@284 151 initRNG();
mas01cr@239 152 initDBHeader(dbName);
mas01mc@292 153 if(inFile)
mas01mc@292 154 initInputFile(inFile);
mas01cr@239 155 }
mas01mc@292 156
mas01mc@324 157 // If name is relative path, side effect name with prefix/name
mas01mc@324 158 // Do not free original pointer
mas01mc@324 159 void audioDB::prefix_name(char** const name, const char* prefix){
mas01mc@324 160 // No prefix if prefix is empty
mas01mc@324 161 if(!prefix)
mas01mc@324 162 return;
mas01mc@324 163 // Allocate new memory, keep old memory
mas01mc@324 164 assert(name && *name);
mas01mc@324 165 if (strlen(*name) + strlen(prefix) + 1 > O2_MAXFILESTR)
mas01mc@324 166 error("error: path prefix + filename too long",prefix);
mas01mc@324 167 // Do not prefix absolute path+filename
mas01mc@324 168 if(**name=='/')
mas01mc@324 169 return;
mas01mc@324 170 // OK to prefix relative path+filename
mas01mc@324 171 char* prefixedName = (char*) malloc(O2_MAXFILESTR);
mas01mc@324 172 sprintf(prefixedName, "%s/%s", prefix, *name);
mas01mc@324 173 *name = prefixedName; // side effect new name to old name
mas01mc@324 174 }
mas01cr@469 175
mas01cr@469 176 void audioDB::insertTimeStamps(unsigned numVectors, std::ifstream *timesFile, double *timesdata) {
mas01cr@469 177 assert(usingTimes);
mas01cr@469 178
mas01cr@469 179 unsigned numtimes = 0;
mas01cr@469 180
mas01cr@469 181 if(!timesFile->is_open()) {
mas01cr@469 182 error("problem opening times file on timestamped database", timesFileName);
mas01cr@469 183 }
mas01cr@469 184
mas01cr@469 185 double timepoint, next;
mas01cr@469 186 *timesFile >> timepoint;
mas01cr@469 187 if (timesFile->eof()) {
mas01cr@469 188 error("no entries in times file", timesFileName);
mas01cr@469 189 }
mas01cr@469 190 numtimes++;
mas01cr@469 191 do {
mas01cr@469 192 *timesFile >> next;
mas01cr@469 193 if (timesFile->eof()) {
mas01cr@469 194 break;
mas01cr@469 195 }
mas01cr@469 196 numtimes++;
mas01cr@469 197 timesdata[0] = timepoint;
mas01cr@469 198 timepoint = (timesdata[1] = next);
mas01cr@469 199 timesdata += 2;
mas01cr@469 200 } while (numtimes < numVectors + 1);
mas01cr@469 201
mas01cr@469 202 if (numtimes < numVectors + 1) {
mas01cr@469 203 error("too few timepoints in times file", timesFileName);
mas01cr@469 204 }
mas01cr@469 205
mas01cr@469 206 *timesFile >> next;
mas01cr@469 207 if (!timesFile->eof()) {
mas01cr@469 208 error("too many timepoints in times file", timesFileName);
mas01cr@469 209 }
mas01cr@469 210 }