Mercurial > hg > audiodb
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 } |