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