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 }