comparison 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
comparison
equal deleted inserted replaced
224:3a81da6fb1d7 239:2cc06e5b05a5
1 #include "audioDB.h"
2
3 #if defined(O2_DEBUG)
4 void sigterm_action(int signal, siginfo_t *info, void *context) {
5 exit(128+signal);
6 }
7
8 void sighup_action(int signal, siginfo_t *info, void *context) {
9 // FIXME: reread any configuration files
10 }
11 #endif
12
13 void audioDB::get_lock(int fd, bool exclusive) {
14 struct flock lock;
15 int status;
16
17 lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
18 lock.l_whence = SEEK_SET;
19 lock.l_start = 0;
20 lock.l_len = 0; /* "the whole file" */
21
22 retry:
23 do {
24 status = fcntl(fd, F_SETLKW, &lock);
25 } while (status != 0 && errno == EINTR);
26
27 if (status) {
28 if (errno == EAGAIN) {
29 sleep(1);
30 goto retry;
31 } else {
32 error("fcntl lock error", "", "fcntl");
33 }
34 }
35 }
36
37 void audioDB::release_lock(int fd) {
38 struct flock lock;
39 int status;
40
41 lock.l_type = F_UNLCK;
42 lock.l_whence = SEEK_SET;
43 lock.l_start = 0;
44 lock.l_len = 0;
45
46 status = fcntl(fd, F_SETLKW, &lock);
47
48 if (status)
49 error("fcntl unlock error", "", "fcntl");
50 }
51
52 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
53 if(isServer) {
54 /* FIXME: I think this is leaky -- we never delete err. actually
55 deleting it is tricky, though; it gets placed into some
56 soap-internal struct with uncertain extent... -- CSR,
57 2007-10-01 */
58 char *err = new char[256]; /* FIXME: overflows */
59 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
60 /* FIXME: actually we could usefully do with a properly structured
61 type, so that we can throw separate faultstring and details.
62 -- CSR, 2007-10-01 */
63 throw(err);
64 } else {
65 std::cerr << a << ": " << b << std::endl;
66 if (sysFunc) {
67 perror(sysFunc);
68 }
69 exit(1);
70 }
71 }
72
73 void audioDB::initDBHeader(const char* dbName) {
74 if ((dbfid = open(dbName, forWrite ? O_RDWR : O_RDONLY)) < 0) {
75 error("Can't open database file", dbName, "open");
76 }
77
78 get_lock(dbfid, forWrite);
79 // Get the database header info
80 dbH = new dbTableHeaderT();
81 assert(dbH);
82
83 if(read(dbfid, (char *) dbH, O2_HEADERSIZE) != O2_HEADERSIZE) {
84 error("error reading db header", dbName, "read");
85 }
86
87 if(dbH->magic == O2_OLD_MAGIC) {
88 // FIXME: if anyone ever complains, write the program to convert
89 // from the old audioDB format to the new...
90 error("database file has old O2 header", dbName);
91 }
92
93 if(dbH->magic != O2_MAGIC) {
94 std::cerr << "expected: " << O2_MAGIC << ", got: " << dbH->magic << std::endl;
95 error("database file has incorrect header", dbName);
96 }
97
98 if(dbH->version != O2_FORMAT_VERSION) {
99 error("database file has incorrect version", dbName);
100 }
101
102 if(dbH->headerSize != O2_HEADERSIZE) {
103 error("sizeof(dbTableHeader) unexpected: platform ABI mismatch?", dbName);
104 }
105
106 CHECKED_MMAP(char *, db, 0, getpagesize());
107
108 // Make some handy tables with correct types
109 if(forWrite || (dbH->length > 0)) {
110 if(forWrite) {
111 fileTableLength = dbH->trackTableOffset - dbH->fileTableOffset;
112 trackTableLength = dbH->dataOffset - dbH->trackTableOffset;
113 dataBufLength = dbH->timesTableOffset - dbH->dataOffset;
114 timesTableLength = dbH->powerTableOffset - dbH->timesTableOffset;
115 powerTableLength = dbH->l2normTableOffset - dbH->powerTableOffset;
116 l2normTableLength = dbH->dbSize - dbH->l2normTableOffset;
117 } else {
118 fileTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_FILETABLESIZE);
119 trackTableLength = ALIGN_PAGE_UP(dbH->numFiles * O2_TRACKTABLESIZE);
120 dataBufLength = ALIGN_PAGE_UP(dbH->length);
121 timesTableLength = ALIGN_PAGE_UP(2*(dbH->length / dbH->dim));
122 powerTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
123 l2normTableLength = ALIGN_PAGE_UP(dbH->length / dbH->dim);
124 }
125 CHECKED_MMAP(char *, fileTable, dbH->fileTableOffset, fileTableLength);
126 CHECKED_MMAP(unsigned *, trackTable, dbH->trackTableOffset, trackTableLength);
127 /*
128 * No more mmap() for dataBuf
129 *
130 * FIXME: Actually we do do the mmap() in the two cases where it's
131 * still "needed": in pointQuery and in l2norm if dbH->length is
132 * non-zero. Removing those cases too (and deleting the dataBuf
133 * variable completely) would be cool. -- CSR, 2007-11-19
134 *
135 * CHECKED_MMAP(double *, dataBuf, dbH->dataOffset, dataBufLength);
136 */
137 CHECKED_MMAP(double *, timesTable, dbH->timesTableOffset, timesTableLength);
138 CHECKED_MMAP(double *, powerTable, dbH->powerTableOffset, powerTableLength);
139 CHECKED_MMAP(double *, l2normTable, dbH->l2normTableOffset, l2normTableLength);
140 }
141 }
142
143 void audioDB::initInputFile (const char *inFile) {
144 if (inFile) {
145 if ((infid = open(inFile, O_RDONLY)) < 0) {
146 error("can't open input file for reading", inFile, "open");
147 }
148
149 if (fstat(infid, &statbuf) < 0) {
150 error("fstat error finding size of input", inFile, "fstat");
151 }
152
153 if(dbH->dim == 0 && dbH->length == 0) { // empty database
154 // initialize with input dimensionality
155 if(read(infid, &dbH->dim, sizeof(unsigned)) != sizeof(unsigned)) {
156 error("short read of input file", inFile);
157 }
158 if(dbH->dim == 0) {
159 error("dimensionality of zero in input file", inFile);
160 }
161 } else {
162 unsigned test;
163 if(read(infid, &test, sizeof(unsigned)) != sizeof(unsigned)) {
164 error("short read of input file", inFile);
165 }
166 if(dbH->dim == 0) {
167 error("dimensionality of zero in input file", inFile);
168 }
169 if(dbH->dim != test) {
170 std::cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<std::endl;
171 error("feature dimensions do not match database table dimensions", inFile);
172 }
173 }
174
175 if ((indata = (char *) mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0)) == (caddr_t) -1) {
176 error("mmap error for input", inFile, "mmap");
177 }
178 }
179 }
180
181 void audioDB::initTables(const char* dbName, const char* inFile = 0) {
182 initDBHeader(dbName);
183 initInputFile(inFile);
184 }