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