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