Mercurial > hg > audiodb
comparison dump.cpp @ 399:a65b31660804 api-inversion
Invert audioDB::dump / audiodb_dump().
No real API/ABI breakages, modulo the disappearance of
audiodb_dump_withdir() (which really should have been audiodb_dump()
itself from the start). There were of course ABI breakages in the
previous commits.
The dodgy thing in this patch is the horribleness of audiodb_dump()
itself; there must be a better way of writing it, or at least
abstracting some of the body into individual functional pieces. The
declaration block at the top tells its own story.
We also need to alter the way that audioDB::status handles the adb;
rather than having a local variable, use the C++ audioDB object instance
field and only open the database if necessary -- then everything has a
consistent view.
author | mas01cr |
---|---|
date | Thu, 27 Nov 2008 15:19:49 +0000 |
parents | 4ded52b104e6 |
children | 8c7453fb5bd9 |
comparison
equal
deleted
inserted
replaced
398:443c2939e84b | 399:a65b31660804 |
---|---|
1 #include "audioDB.h" | 1 #include "audioDB.h" |
2 | 2 extern "C" { |
3 void audioDB::dump(const char* dbName){ | 3 #include "audioDB_API.h" |
4 if(!dbH) { | 4 } |
5 initTables(dbName, 0); | 5 |
6 /* We could go gcc-specific here and use typeof() instead of passing | |
7 * in an explicit type. Answers on a postcard as to whether that's a | |
8 * good plan or not. */ | |
9 #define mmap_or_goto_error(type, var, start, length) \ | |
10 { void *tmp = mmap(0, length, PROT_READ, MAP_SHARED, adb->fd, (start)); \ | |
11 if(tmp == (void *) -1) { \ | |
12 goto error; \ | |
13 } \ | |
14 var = (type) tmp; \ | |
15 } | |
16 | |
17 #define maybe_munmap(table, length) \ | |
18 { if(table) { \ | |
19 munmap(table, length); \ | |
20 } \ | |
21 } | |
22 | |
23 int audiodb_dump(adb_t *adb, const char *output) { | |
24 char *fileTable = 0; /* key_table */ | |
25 unsigned *trackTable = 0; /* track_size_table */ | |
26 double *timesTable = 0; /* timestamps_table */ | |
27 double *powerTable = 0; /* power_table */ | |
28 | |
29 size_t fileTableLength = 0; | |
30 size_t trackTableLength = 0; | |
31 size_t timesTableLength = 0; | |
32 size_t powerTableLength = 0; | |
33 | |
34 char *featureFileNameTable = 0; | |
35 char *powerFileNameTable = 0; | |
36 char *timesFileNameTable = 0; | |
37 | |
38 char cwd[PATH_MAX]; | |
39 int directory_changed = 0; | |
40 | |
41 int fLfd = 0, tLfd = 0, pLfd = 0, kLfd = 0; | |
42 FILE *fLFile = 0, *tLFile = 0, *pLFile = 0, *kLFile = 0; | |
43 | |
44 int times, power; | |
45 | |
46 char fName[256]; | |
47 int ffd, pfd; | |
48 FILE *tFile; | |
49 unsigned pos = 0; | |
50 double *data_buffer; | |
51 size_t data_buffer_size; | |
52 FILE *scriptFile = 0; | |
53 | |
54 unsigned nfiles = adb->header->numFiles; | |
55 | |
56 if(adb->header->length > 0) { | |
57 fileTableLength = ALIGN_PAGE_UP(nfiles * O2_FILETABLE_ENTRY_SIZE); | |
58 trackTableLength = ALIGN_PAGE_UP(nfiles * O2_TRACKTABLE_ENTRY_SIZE); | |
59 if(!(adb->header->flags & O2_FLAG_LARGE_ADB)) { | |
60 off_t length = adb->header->length; | |
61 unsigned dim = adb->header->dim; | |
62 timesTableLength = ALIGN_PAGE_UP(2*length/dim); | |
63 powerTableLength = ALIGN_PAGE_UP(length/dim); | |
64 } | |
65 | |
66 mmap_or_goto_error(char *, fileTable, adb->header->fileTableOffset, fileTableLength); | |
67 mmap_or_goto_error(unsigned *, trackTable, adb->header->trackTableOffset, trackTableLength); | |
68 if (adb->header->flags & O2_FLAG_LARGE_ADB) { | |
69 mmap_or_goto_error(char *, featureFileNameTable, adb->header->dataOffset, fileTableLength); | |
70 mmap_or_goto_error(char *, powerFileNameTable, adb->header->powerTableOffset, fileTableLength); | |
71 mmap_or_goto_error(char *, timesFileNameTable, adb->header->timesTableOffset, fileTableLength); | |
72 } else { | |
73 mmap_or_goto_error(double *, powerTable, adb->header->powerTableOffset, powerTableLength); | |
74 mmap_or_goto_error(double *, timesTable, adb->header->timesTableOffset, timesTableLength); | |
75 } | |
6 } | 76 } |
7 | 77 |
8 if((mkdir(output, S_IRWXU|S_IRWXG|S_IRWXO)) < 0) { | 78 if((mkdir(output, S_IRWXU|S_IRWXG|S_IRWXO)) < 0) { |
9 error("error making output directory", output, "mkdir"); | 79 goto error; |
10 } | 80 } |
11 | |
12 char *cwd = new char[PATH_MAX]; | |
13 | 81 |
14 if ((getcwd(cwd, PATH_MAX)) == 0) { | 82 if ((getcwd(cwd, PATH_MAX)) == 0) { |
15 error("error getting working directory", "", "getcwd"); | 83 goto error; |
16 } | 84 } |
17 | 85 |
86 /* FIXME: Hrm. How does chdir(2) interact with threads? Does each | |
87 * thread have its own working directory? */ | |
18 if((chdir(output)) < 0) { | 88 if((chdir(output)) < 0) { |
19 error("error changing working directory", output, "chdir"); | 89 goto error; |
20 } | 90 } |
21 | 91 directory_changed = 1; |
22 int fLfd, tLfd = 0, pLfd = 0, kLfd; | |
23 FILE *fLFile, *tLFile = 0, *pLFile = 0, *kLFile; | |
24 | 92 |
25 if ((fLfd = open("featureList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { | 93 if ((fLfd = open("featureList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { |
26 error("error creating featureList file", "featureList.txt", "open"); | 94 goto error; |
27 } | 95 } |
28 | 96 |
29 int times = dbH->flags & O2_FLAG_TIMES; | 97 times = adb->header->flags & O2_FLAG_TIMES; |
30 if (times) { | 98 if (times) { |
31 if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { | 99 if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { |
32 error("error creating timesList file", "timesList.txt", "open"); | 100 goto error; |
33 } | 101 } |
34 } | 102 } |
35 | 103 |
36 int power = dbH->flags & O2_FLAG_POWER; | 104 power = adb->header->flags & O2_FLAG_POWER; |
37 if (power) { | 105 if (power) { |
38 if ((pLfd = open("powerList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { | 106 if ((pLfd = open("powerList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { |
39 error("error creating powerList file", "powerList.txt", "open"); | 107 goto error; |
40 } | 108 } |
41 } | 109 } |
42 | 110 |
43 if ((kLfd = open("keyList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { | 111 if ((kLfd = open("keyList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { |
44 error("error creating keyList file", "keyList.txt", "open"); | 112 goto error; |
45 } | 113 } |
46 | 114 |
47 /* can these fail? I sincerely hope not. */ | 115 /* can these fail? I sincerely hope not. */ |
48 fLFile = fdopen(fLfd, "w"); | 116 fLFile = fdopen(fLfd, "w"); |
49 if (times) { | 117 if (times) { |
52 if (power) { | 120 if (power) { |
53 pLFile = fdopen(pLfd, "w"); | 121 pLFile = fdopen(pLfd, "w"); |
54 } | 122 } |
55 kLFile = fdopen(kLfd, "w"); | 123 kLFile = fdopen(kLfd, "w"); |
56 | 124 |
57 char *fName = new char[256]; | 125 lseek(adb->fd, adb->header->dataOffset, SEEK_SET); |
58 int ffd, pfd; | 126 |
59 FILE *tFile; | 127 for(unsigned k = 0; k < nfiles; k++) { |
60 unsigned pos = 0; | |
61 lseek(dbfid, dbH->dataOffset, SEEK_SET); | |
62 double *data_buffer; | |
63 size_t data_buffer_size; | |
64 for(unsigned k = 0; k < dbH->numFiles; k++) { | |
65 fprintf(kLFile, "%s\n", fileTable + k*O2_FILETABLE_ENTRY_SIZE); | 128 fprintf(kLFile, "%s\n", fileTable + k*O2_FILETABLE_ENTRY_SIZE); |
66 if(dbH->flags & O2_FLAG_LARGE_ADB) { | 129 if(adb->header->flags & O2_FLAG_LARGE_ADB) { |
67 char *featureFileName = featureFileNameTable+k*O2_FILETABLE_ENTRY_SIZE; | 130 char *featureFileName = featureFileNameTable+k*O2_FILETABLE_ENTRY_SIZE; |
131 if(*featureFileName != '/') { | |
132 goto error; | |
133 } | |
68 fprintf(fLFile, "%s\n", featureFileName); | 134 fprintf(fLFile, "%s\n", featureFileName); |
69 if(*featureFileName != '/') { | |
70 error("relative path in LARGE_ADB", featureFileName); | |
71 } | |
72 if(times) { | 135 if(times) { |
73 char *timesFileName = timesFileNameTable + k*O2_FILETABLE_ENTRY_SIZE; | 136 char *timesFileName = timesFileNameTable + k*O2_FILETABLE_ENTRY_SIZE; |
137 if(*timesFileName != '/') { | |
138 goto error; | |
139 } | |
74 fprintf(tLFile, "%s\n", timesFileName); | 140 fprintf(tLFile, "%s\n", timesFileName); |
75 if(*timesFileName != '/') { | |
76 error("relative path in LARGE_ADB", timesFileName); | |
77 } | |
78 } | 141 } |
79 if(power) { | 142 if(power) { |
80 char *powerFileName = powerFileNameTable + k*O2_FILETABLE_ENTRY_SIZE; | 143 char *powerFileName = powerFileNameTable + k*O2_FILETABLE_ENTRY_SIZE; |
144 if(*powerFileName != '/') { | |
145 goto error; | |
146 } | |
81 fprintf(pLFile, "%s\n", powerFileName); | 147 fprintf(pLFile, "%s\n", powerFileName); |
82 if(*powerFileName != '/') { | |
83 error("relative path in LARGE_ADB", powerFileName); | |
84 } | |
85 } | 148 } |
86 } else { | 149 } else { |
87 snprintf(fName, 256, "%05d.features", k); | 150 snprintf(fName, 256, "%05d.features", k); |
88 if ((ffd = open(fName, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { | 151 if ((ffd = open(fName, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { |
89 error("error creating feature file", fName, "open"); | 152 goto error; |
90 } | 153 } |
91 if ((write(ffd, &dbH->dim, sizeof(uint32_t))) < 0) { | 154 if ((write(ffd, &(adb->header->dim), sizeof(uint32_t))) < 0) { |
92 error("error writing dimensions", fName, "write"); | 155 goto error; |
93 } | 156 } |
94 | 157 |
95 /* FIXME: this repeated malloc()/free() of data buffers is | 158 /* FIXME: this repeated malloc()/free() of data buffers is |
96 inefficient. */ | 159 inefficient. */ |
97 data_buffer_size = trackTable[k] * dbH->dim * sizeof(double); | 160 data_buffer_size = trackTable[k] * adb->header->dim * sizeof(double); |
98 | 161 |
99 { | 162 { |
100 void *tmp = malloc(data_buffer_size); | 163 void *tmp = malloc(data_buffer_size); |
101 if (tmp == NULL) { | 164 if (tmp == NULL) { |
102 error("error allocating data buffer"); | 165 goto error; |
103 } | 166 } |
104 data_buffer = (double *) tmp; | 167 data_buffer = (double *) tmp; |
105 } | 168 } |
106 | 169 |
107 if ((read(dbfid, data_buffer, data_buffer_size)) != (ssize_t) data_buffer_size) { | 170 if ((read(adb->fd, data_buffer, data_buffer_size)) != (ssize_t) data_buffer_size) { |
108 error("error reading data", fName, "read"); | 171 goto error; |
109 } | 172 } |
110 | 173 |
111 if ((write(ffd, data_buffer, data_buffer_size)) < 0) { | 174 if ((write(ffd, data_buffer, data_buffer_size)) < 0) { |
112 error("error writing data", fName, "write"); | 175 goto error; |
113 } | 176 } |
114 | 177 |
115 free(data_buffer); | 178 free(data_buffer); |
116 | 179 |
117 fprintf(fLFile, "%s\n", fName); | 180 fprintf(fLFile, "%s\n", fName); |
118 close(ffd); | 181 close(ffd); |
119 | 182 ffd = 0; |
183 | |
120 if (times) { | 184 if (times) { |
121 snprintf(fName, 256, "%05d.times", k); | 185 snprintf(fName, 256, "%05d.times", k); |
122 tFile = fopen(fName, "w"); | 186 tFile = fopen(fName, "w"); |
123 for(unsigned i = 0; i < trackTable[k]; i++) { | 187 for(unsigned i = 0; i < trackTable[k]; i++) { |
124 // KLUDGE: specifying 16 digits of precision after the decimal | 188 // KLUDGE: specifying 16 digits of precision after the decimal |
128 // here and scanf() in the timesFile reading might fix this. | 192 // here and scanf() in the timesFile reading might fix this. |
129 // -- CSR, 2007-10-19 | 193 // -- CSR, 2007-10-19 |
130 fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*i)); | 194 fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*i)); |
131 } | 195 } |
132 fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*trackTable[k]-1)); | 196 fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*trackTable[k]-1)); |
197 fclose(tFile); | |
133 | 198 |
134 fprintf(tLFile, "%s\n", fName); | 199 fprintf(tLFile, "%s\n", fName); |
135 } | 200 } |
136 | 201 |
137 if (power) { | 202 if (power) { |
138 uint32_t one = 1; | 203 uint32_t one = 1; |
139 snprintf(fName, 256, "%05d.power", k); | 204 snprintf(fName, 256, "%05d.power", k); |
140 if ((pfd = open(fName, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { | 205 if ((pfd = open(fName, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { |
141 error("error creating power file", fName, "open"); | 206 goto error; |
142 } | 207 } |
143 if ((write(pfd, &one, sizeof(uint32_t))) < 0) { | 208 if ((write(pfd, &one, sizeof(uint32_t))) < 0) { |
144 error("error writing one", fName, "write"); | 209 goto error; |
145 } | 210 } |
146 if ((write(pfd, powerTable + pos, trackTable[k] * sizeof(double))) < 0) { | 211 if ((write(pfd, powerTable + pos, trackTable[k] * sizeof(double))) < 0) { |
147 error("error writing data", fName, "write"); | 212 goto error; |
148 } | 213 } |
149 fprintf(pLFile, "%s\n", fName); | 214 fprintf(pLFile, "%s\n", fName); |
150 close(pfd); | 215 close(pfd); |
216 pfd = 0; | |
151 } | 217 } |
152 | 218 |
153 pos += trackTable[k]; | 219 pos += trackTable[k]; |
154 std::cout << fileTable+k*O2_FILETABLE_ENTRY_SIZE << " " << trackTable[k] << std::endl; | 220 std::cout << fileTable+k*O2_FILETABLE_ENTRY_SIZE << " " << trackTable[k] << std::endl; |
155 } | 221 } |
156 } | 222 } |
157 | 223 |
158 FILE *scriptFile; | |
159 scriptFile = fopen("restore.sh", "w"); | 224 scriptFile = fopen("restore.sh", "w"); |
160 fprintf(scriptFile, "\ | 225 fprintf(scriptFile, "\ |
161 #! /bin/sh\n\ | 226 #! /bin/sh\n\ |
162 #\n\ | 227 #\n\ |
163 # usage: AUDIODB=/path/to/audioDB sh ./restore.sh <newdb>\n\ | 228 # usage: AUDIODB=/path/to/audioDB sh ./restore.sh <newdb>\n\ |
164 \n\ | 229 \n\ |
165 if [ -z \"${AUDIODB}\" ]; then echo set AUDIODB variable; exit 1; fi\n\ | 230 if [ -z \"${AUDIODB}\" ]; then echo set AUDIODB variable; exit 1; fi\n\ |
166 if [ -z \"$1\" ]; then echo usage: $0 newdb; exit 1; fi\n\n\ | 231 if [ -z \"$1\" ]; then echo usage: $0 newdb; exit 1; fi\n\n\ |
167 \"${AUDIODB}\" -d \"$1\" -N --datasize=%d --ntracks=%d --datadim=%d\n", | 232 \"${AUDIODB}\" -d \"$1\" -N --datasize=%d --ntracks=%d --datadim=%d\n", |
168 (int) ((dbH->timesTableOffset - dbH->dataOffset) / (1024*1024)), | 233 (int) ((adb->header->timesTableOffset - adb->header->dataOffset) / (1024*1024)), |
169 // fileTable entries (char[256]) are bigger than trackTable | 234 // fileTable entries (char[256]) are bigger than trackTable |
170 // (int), so the granularity of page aligning is finer. | 235 // (int), so the granularity of page aligning is finer. |
171 (int) ((dbH->trackTableOffset - dbH->fileTableOffset) / O2_FILETABLE_ENTRY_SIZE), | 236 (int) ((adb->header->trackTableOffset - adb->header->fileTableOffset) / O2_FILETABLE_ENTRY_SIZE), |
172 (int) ceil(((double) (dbH->timesTableOffset - dbH->dataOffset)) / ((double) (dbH->dbSize - dbH->l2normTableOffset)))); | 237 (int) ceil(((double) (adb->header->timesTableOffset - adb->header->dataOffset)) / ((double) (adb->header->dbSize - adb->header->l2normTableOffset)))); |
173 if(dbH->flags & O2_FLAG_L2NORM) { | 238 if(adb->header->flags & O2_FLAG_L2NORM) { |
174 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n"); | 239 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n"); |
175 } | 240 } |
176 if(power) { | 241 if(power) { |
177 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -P\n"); | 242 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -P\n"); |
178 } | 243 } |
184 fprintf(scriptFile, " -W powerList.txt"); | 249 fprintf(scriptFile, " -W powerList.txt"); |
185 } | 250 } |
186 fprintf(scriptFile, "\n"); | 251 fprintf(scriptFile, "\n"); |
187 fclose(scriptFile); | 252 fclose(scriptFile); |
188 | 253 |
189 if((chdir(cwd)) < 0) { | |
190 error("error changing working directory", cwd, "chdir"); | |
191 } | |
192 | |
193 fclose(fLFile); | 254 fclose(fLFile); |
194 if(times) { | 255 if(times) { |
195 fclose(tLFile); | 256 fclose(tLFile); |
196 } | 257 } |
197 if(power) { | 258 if(power) { |
198 fclose(pLFile); | 259 fclose(pLFile); |
199 } | 260 } |
200 fclose(kLFile); | 261 fclose(kLFile); |
201 delete[] fName; | |
202 | 262 |
203 status(dbName); | 263 maybe_munmap(fileTable, fileTableLength); |
264 maybe_munmap(trackTable, trackTableLength); | |
265 maybe_munmap(timesTable, timesTableLength); | |
266 maybe_munmap(powerTable, powerTableLength); | |
267 maybe_munmap(featureFileNameTable, fileTableLength); | |
268 maybe_munmap(timesFileNameTable, fileTableLength); | |
269 maybe_munmap(powerFileNameTable, fileTableLength); | |
270 | |
271 if((chdir(cwd)) < 0) { | |
272 /* don't goto error because the error handling will try to | |
273 * chdir() */ | |
274 return 1; | |
275 } | |
276 | |
277 return 0; | |
278 | |
279 error: | |
280 if(fLFile) { | |
281 fclose(fLFile); | |
282 } else if(fLfd) { | |
283 close(fLfd); | |
284 } | |
285 if(tLFile) { | |
286 fclose(tLFile); | |
287 } else if(tLfd) { | |
288 close(fLfd); | |
289 } | |
290 if(pLFile) { | |
291 fclose(pLFile); | |
292 } else if(pLfd) { | |
293 close(pLfd); | |
294 } | |
295 if(kLFile) { | |
296 fclose(kLFile); | |
297 } else if(kLfd) { | |
298 close(kLfd); | |
299 } | |
300 if(scriptFile) { | |
301 fclose(scriptFile); | |
302 } | |
303 | |
304 maybe_munmap(fileTable, fileTableLength); | |
305 maybe_munmap(trackTable, trackTableLength); | |
306 maybe_munmap(timesTable, timesTableLength); | |
307 maybe_munmap(powerTable, powerTableLength); | |
308 maybe_munmap(featureFileNameTable, fileTableLength); | |
309 maybe_munmap(timesFileNameTable, fileTableLength); | |
310 maybe_munmap(powerFileNameTable, fileTableLength); | |
311 | |
312 if(directory_changed) { | |
313 chdir(cwd); | |
314 } | |
315 return 1; | |
204 } | 316 } |