mas01cr@498: extern "C" { mas01cr@498: #include "audioDB_API.h" mas01cr@509: } mas01cr@498: #include "audioDB-internals.h" mas01cr@239: mas01cr@498: int audiodb_dump(adb_t *adb, const char *output) { mas01cr@498: char *fileTable = 0; /* key_table */ mas01cr@498: double *timesTable = 0; /* timestamps_table */ mas01cr@498: double *powerTable = 0; /* power_table */ mas01cr@498: mas01cr@498: size_t fileTableLength = 0; mas01cr@498: size_t timesTableLength = 0; mas01cr@498: size_t powerTableLength = 0; mas01cr@498: mas01cr@498: char *featureFileNameTable = 0; mas01cr@498: char *powerFileNameTable = 0; mas01cr@498: char *timesFileNameTable = 0; mas01cr@498: mas01cr@498: char cwd[PATH_MAX]; mas01cr@498: int directory_changed = 0; mas01cr@498: mas01cr@498: int fLfd = 0, tLfd = 0, pLfd = 0, kLfd = 0; mas01cr@498: FILE *fLFile = 0, *tLFile = 0, *pLFile = 0, *kLFile = 0; mas01cr@498: mas01cr@498: int times, power; mas01cr@498: mas01cr@498: char fName[256]; mas01cr@498: int ffd, pfd; mas01cr@498: FILE *tFile; mas01cr@498: unsigned pos = 0; mas01cr@498: double *data_buffer; mas01cr@498: size_t data_buffer_size; mas01cr@498: FILE *scriptFile = 0; mas01cr@498: mas01cr@498: unsigned nfiles = adb->header->numFiles; mas01cr@498: mas01cr@498: if(adb->header->length > 0) { mas01cr@509: fileTableLength = align_page_up(nfiles * ADB_FILETABLE_ENTRY_SIZE); mas01cr@509: if(!(adb->header->flags & ADB_HEADER_FLAG_REFERENCES)) { mas01cr@498: off_t length = adb->header->length; mas01cr@498: unsigned dim = adb->header->dim; mas01cr@509: timesTableLength = align_page_up(2*length/dim); mas01cr@509: powerTableLength = align_page_up(length/dim); mas01cr@498: } mas01cr@498: mas01cr@595: malloc_and_fill_or_goto_error(char *, fileTable, adb->header->fileTableOffset, fileTableLength); mas01cr@509: if (adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { mas01cr@595: malloc_and_fill_or_goto_error(char *, featureFileNameTable, adb->header->dataOffset, fileTableLength); mas01cr@595: malloc_and_fill_or_goto_error(char *, powerFileNameTable, adb->header->powerTableOffset, fileTableLength); mas01cr@595: malloc_and_fill_or_goto_error(char *, timesFileNameTable, adb->header->timesTableOffset, fileTableLength); mas01cr@498: } else { mas01cr@595: malloc_and_fill_or_goto_error(double *, powerTable, adb->header->powerTableOffset, powerTableLength); mas01cr@595: malloc_and_fill_or_goto_error(double *, timesTable, adb->header->timesTableOffset, timesTableLength); mas01cr@498: } mas01cr@239: } mas01cr@239: mas01cr@595: mkdir_or_goto_error(output); mas01cr@239: mas01cr@239: if ((getcwd(cwd, PATH_MAX)) == 0) { mas01cr@498: goto error; mas01cr@239: } mas01cr@239: mas01cr@498: /* FIXME: Hrm. How does chdir(2) interact with threads? Does each mas01cr@498: * thread have its own working directory? */ mas01cr@239: if((chdir(output)) < 0) { mas01cr@498: goto error; mas01cr@498: } mas01cr@498: directory_changed = 1; mas01cr@498: mas01cr@595: if ((fLfd = open("featureList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) { mas01cr@498: goto error; mas01cr@239: } mas01cr@239: mas01cr@509: times = adb->header->flags & ADB_HEADER_FLAG_TIMES; mas01cr@239: if (times) { mas01cr@595: if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) { mas01cr@498: goto error; mas01cr@239: } mas01cr@239: } mas01cr@239: mas01cr@509: power = adb->header->flags & ADB_HEADER_FLAG_POWER; mas01cr@239: if (power) { mas01cr@595: if ((pLfd = open("powerList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) { mas01cr@498: goto error; mas01cr@239: } mas01cr@239: } mas01cr@239: mas01cr@595: if ((kLfd = open("keyList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) { mas01cr@498: goto error; mas01cr@239: } mas01cr@239: mas01cr@239: /* can these fail? I sincerely hope not. */ mas01cr@239: fLFile = fdopen(fLfd, "w"); mas01cr@239: if (times) { mas01cr@239: tLFile = fdopen(tLfd, "w"); mas01cr@239: } mas01cr@239: if (power) { mas01cr@239: pLFile = fdopen(pLfd, "w"); mas01cr@239: } mas01cr@239: kLFile = fdopen(kLfd, "w"); mas01cr@239: mas01cr@596: lseek_set_or_goto_error(adb->fd, adb->header->dataOffset); mas01cr@498: mas01cr@498: for(unsigned k = 0; k < nfiles; k++) { mas01cr@509: fprintf(kLFile, "%s\n", fileTable + k*ADB_FILETABLE_ENTRY_SIZE); mas01cr@509: if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { mas01cr@509: char *featureFileName = featureFileNameTable+k*ADB_FILETABLE_ENTRY_SIZE; mas01cr@498: if(*featureFileName != '/') { mas01cr@498: goto error; mas01cr@498: } mas01cr@380: fprintf(fLFile, "%s\n", featureFileName); mas01cr@380: if(times) { mas01cr@509: char *timesFileName = timesFileNameTable + k*ADB_FILETABLE_ENTRY_SIZE; mas01cr@498: if(*timesFileName != '/') { mas01cr@498: goto error; mas01cr@498: } mas01cr@380: fprintf(tLFile, "%s\n", timesFileName); mas01cr@239: } mas01cr@380: if(power) { mas01cr@509: char *powerFileName = powerFileNameTable + k*ADB_FILETABLE_ENTRY_SIZE; mas01cr@498: if(*powerFileName != '/') { mas01cr@498: goto error; mas01cr@498: } mas01cr@380: fprintf(pLFile, "%s\n", powerFileName); mas01cr@239: } mas01cr@380: } else { mas01cr@380: snprintf(fName, 256, "%05d.features", k); mas01cr@595: if ((ffd = open(fName, O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) { mas01cr@498: goto error; mas01cr@239: } mas01cr@498: write_or_goto_error(ffd, &(adb->header->dim), sizeof(uint32_t)); mas01cr@380: mas01cr@380: /* FIXME: this repeated malloc()/free() of data buffers is mas01cr@380: inefficient. */ mas01cr@498: data_buffer_size = (*adb->track_lengths)[k] * adb->header->dim * sizeof(double); mas01cr@380: mas01cr@380: { mas01cr@380: void *tmp = malloc(data_buffer_size); mas01cr@380: if (tmp == NULL) { mas01cr@498: goto error; mas01cr@380: } mas01cr@380: data_buffer = (double *) tmp; mas01cr@380: } mas01cr@380: mas01cr@498: if ((read(adb->fd, data_buffer, data_buffer_size)) != (ssize_t) data_buffer_size) { mas01cr@498: goto error; mas01cr@380: } mas01cr@380: mas01cr@498: write_or_goto_error(ffd, data_buffer, data_buffer_size); mas01cr@380: mas01cr@380: free(data_buffer); mas01cr@380: mas01cr@380: fprintf(fLFile, "%s\n", fName); mas01cr@380: close(ffd); mas01cr@498: ffd = 0; mas01cr@498: mas01cr@380: if (times) { mas01cr@380: snprintf(fName, 256, "%05d.times", k); mas01cr@380: tFile = fopen(fName, "w"); mas01cr@498: for(unsigned i = 0; i < (*adb->track_lengths)[k]; i++) { mas01cr@380: // KLUDGE: specifying 16 digits of precision after the decimal mas01cr@380: // point is (but check this!) sufficient to uniquely identify mas01cr@380: // doubles; however, that will cause ugliness, as that's mas01cr@380: // vastly too many for most values of interest. Moving to %a mas01cr@380: // here and scanf() in the timesFile reading might fix this. mas01cr@380: // -- CSR, 2007-10-19 mas01cr@380: fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*i)); mas01cr@380: } mas01cr@498: fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*(*adb->track_lengths)[k]-1)); mas01cr@498: fclose(tFile); mas01cr@380: mas01cr@380: fprintf(tLFile, "%s\n", fName); mas01cr@380: } mas01cr@380: mas01cr@380: if (power) { mas01cr@380: uint32_t one = 1; mas01cr@380: snprintf(fName, 256, "%05d.power", k); mas01cr@595: if ((pfd = open(fName, O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) { mas01cr@498: goto error; mas01cr@380: } mas01cr@498: write_or_goto_error(pfd, &one, sizeof(uint32_t)); mas01cr@498: write_or_goto_error(pfd, powerTable + pos, (*adb->track_lengths)[k] * sizeof(double)); mas01cr@380: fprintf(pLFile, "%s\n", fName); mas01cr@380: close(pfd); mas01cr@498: pfd = 0; mas01cr@380: } mas01cr@380: mas01cr@498: pos += (*adb->track_lengths)[k]; mas01cr@509: std::cout << fileTable+k*ADB_FILETABLE_ENTRY_SIZE << " " << (*adb->track_lengths)[k] << std::endl; mas01cr@380: } mas01cr@239: } mas01cr@239: mas01cr@239: scriptFile = fopen("restore.sh", "w"); mas01cr@239: fprintf(scriptFile, "\ mas01cr@239: #! /bin/sh\n\ mas01cr@239: #\n\ mas01cr@239: # usage: AUDIODB=/path/to/audioDB sh ./restore.sh \n\ mas01cr@239: \n\ mas01cr@239: if [ -z \"${AUDIODB}\" ]; then echo set AUDIODB variable; exit 1; fi\n\ mas01cr@239: if [ -z \"$1\" ]; then echo usage: $0 newdb; exit 1; fi\n\n\ mas01cr@256: \"${AUDIODB}\" -d \"$1\" -N --datasize=%d --ntracks=%d --datadim=%d\n", mas01cr@498: (int) ((adb->header->timesTableOffset - adb->header->dataOffset) / (1024*1024)), mas01cr@256: // fileTable entries (char[256]) are bigger than trackTable mas01cr@256: // (int), so the granularity of page aligning is finer. mas01cr@509: (int) ((adb->header->trackTableOffset - adb->header->fileTableOffset) / ADB_FILETABLE_ENTRY_SIZE), mas01cr@498: (int) ceil(((double) (adb->header->timesTableOffset - adb->header->dataOffset)) / ((double) (adb->header->dbSize - adb->header->l2normTableOffset)))); mas01cr@509: if(adb->header->flags & ADB_HEADER_FLAG_L2NORM) { mas01cr@239: fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n"); mas01cr@239: } mas01cr@239: if(power) { mas01cr@239: fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -P\n"); mas01cr@239: } mas01cr@239: fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -B -F featureList.txt -K keyList.txt"); mas01cr@239: if(times) { mas01cr@239: fprintf(scriptFile, " -T timesList.txt"); mas01cr@239: } mas01cr@239: if(power) { mas01cr@239: fprintf(scriptFile, " -W powerList.txt"); mas01cr@239: } mas01cr@239: fprintf(scriptFile, "\n"); mas01cr@239: fclose(scriptFile); mas01cr@239: mas01cr@239: fclose(fLFile); mas01cr@239: if(times) { mas01cr@239: fclose(tLFile); mas01cr@239: } mas01cr@239: if(power) { mas01cr@239: fclose(pLFile); mas01cr@239: } mas01cr@239: fclose(kLFile); mas01cr@239: mas01cr@595: maybe_free(fileTable); mas01cr@595: maybe_free(timesTable); mas01cr@595: maybe_free(powerTable); mas01cr@595: maybe_free(featureFileNameTable); mas01cr@595: maybe_free(timesFileNameTable); mas01cr@595: maybe_free(powerFileNameTable); mas01mc@334: mas01cr@498: if((chdir(cwd)) < 0) { mas01cr@498: /* don't goto error because the error handling will try to mas01cr@498: * chdir() */ mas01cr@498: return 1; mas01mc@334: } mas01mc@334: mas01cr@498: return 0; mas01mc@334: mas01cr@498: error: mas01cr@498: if(fLFile) { mas01cr@498: fclose(fLFile); mas01cr@498: } else if(fLfd) { mas01cr@498: close(fLfd); mas01cr@498: } mas01cr@498: if(tLFile) { mas01cr@498: fclose(tLFile); mas01cr@498: } else if(tLfd) { mas01cr@498: close(fLfd); mas01cr@498: } mas01cr@498: if(pLFile) { mas01cr@498: fclose(pLFile); mas01cr@498: } else if(pLfd) { mas01cr@498: close(pLfd); mas01cr@498: } mas01cr@498: if(kLFile) { mas01cr@498: fclose(kLFile); mas01cr@498: } else if(kLfd) { mas01cr@498: close(kLfd); mas01cr@498: } mas01cr@498: if(scriptFile) { mas01cr@498: fclose(scriptFile); mas01mc@334: } mas01mc@334: mas01cr@595: maybe_free(fileTable); mas01cr@595: maybe_free(timesTable); mas01cr@595: maybe_free(powerTable); mas01cr@595: maybe_free(featureFileNameTable); mas01cr@595: maybe_free(timesFileNameTable); mas01cr@595: maybe_free(powerFileNameTable); mas01cr@498: mas01cr@498: if(directory_changed) { mas01cr@498: int gcc_warning_workaround = chdir(cwd); mas01cr@498: directory_changed = gcc_warning_workaround; mas01mc@334: } mas01cr@498: return 1; mas01mc@334: }