annotate dump.cpp @ 601:82d23418d867

Fix some fd leaks in the command-line binary Strictly speaking, they're not really leaks, because the only codepath that suffers from these leaks exits immediately afterwards. On the other hand, this fix makes valgrind on e.g. tests/0025 happier, going from 5 errors to none.
author mas01cr
date Fri, 14 Aug 2009 16:39:32 +0000
parents 6ad0a6e67d4c
children
rev   line source
mas01cr@498 1 extern "C" {
mas01cr@498 2 #include "audioDB_API.h"
mas01cr@509 3 }
mas01cr@498 4 #include "audioDB-internals.h"
mas01cr@239 5
mas01cr@498 6 int audiodb_dump(adb_t *adb, const char *output) {
mas01cr@498 7 char *fileTable = 0; /* key_table */
mas01cr@498 8 double *timesTable = 0; /* timestamps_table */
mas01cr@498 9 double *powerTable = 0; /* power_table */
mas01cr@498 10
mas01cr@498 11 size_t fileTableLength = 0;
mas01cr@498 12 size_t timesTableLength = 0;
mas01cr@498 13 size_t powerTableLength = 0;
mas01cr@498 14
mas01cr@498 15 char *featureFileNameTable = 0;
mas01cr@498 16 char *powerFileNameTable = 0;
mas01cr@498 17 char *timesFileNameTable = 0;
mas01cr@498 18
mas01cr@498 19 char cwd[PATH_MAX];
mas01cr@498 20 int directory_changed = 0;
mas01cr@498 21
mas01cr@498 22 int fLfd = 0, tLfd = 0, pLfd = 0, kLfd = 0;
mas01cr@498 23 FILE *fLFile = 0, *tLFile = 0, *pLFile = 0, *kLFile = 0;
mas01cr@498 24
mas01cr@498 25 int times, power;
mas01cr@498 26
mas01cr@498 27 char fName[256];
mas01cr@498 28 int ffd, pfd;
mas01cr@498 29 FILE *tFile;
mas01cr@498 30 unsigned pos = 0;
mas01cr@498 31 double *data_buffer;
mas01cr@498 32 size_t data_buffer_size;
mas01cr@498 33 FILE *scriptFile = 0;
mas01cr@498 34
mas01cr@498 35 unsigned nfiles = adb->header->numFiles;
mas01cr@498 36
mas01cr@498 37 if(adb->header->length > 0) {
mas01cr@509 38 fileTableLength = align_page_up(nfiles * ADB_FILETABLE_ENTRY_SIZE);
mas01cr@509 39 if(!(adb->header->flags & ADB_HEADER_FLAG_REFERENCES)) {
mas01cr@498 40 off_t length = adb->header->length;
mas01cr@498 41 unsigned dim = adb->header->dim;
mas01cr@509 42 timesTableLength = align_page_up(2*length/dim);
mas01cr@509 43 powerTableLength = align_page_up(length/dim);
mas01cr@498 44 }
mas01cr@498 45
mas01cr@595 46 malloc_and_fill_or_goto_error(char *, fileTable, adb->header->fileTableOffset, fileTableLength);
mas01cr@509 47 if (adb->header->flags & ADB_HEADER_FLAG_REFERENCES) {
mas01cr@595 48 malloc_and_fill_or_goto_error(char *, featureFileNameTable, adb->header->dataOffset, fileTableLength);
mas01cr@595 49 malloc_and_fill_or_goto_error(char *, powerFileNameTable, adb->header->powerTableOffset, fileTableLength);
mas01cr@595 50 malloc_and_fill_or_goto_error(char *, timesFileNameTable, adb->header->timesTableOffset, fileTableLength);
mas01cr@498 51 } else {
mas01cr@595 52 malloc_and_fill_or_goto_error(double *, powerTable, adb->header->powerTableOffset, powerTableLength);
mas01cr@595 53 malloc_and_fill_or_goto_error(double *, timesTable, adb->header->timesTableOffset, timesTableLength);
mas01cr@498 54 }
mas01cr@239 55 }
mas01cr@239 56
mas01cr@595 57 mkdir_or_goto_error(output);
mas01cr@239 58
mas01cr@239 59 if ((getcwd(cwd, PATH_MAX)) == 0) {
mas01cr@498 60 goto error;
mas01cr@239 61 }
mas01cr@239 62
mas01cr@498 63 /* FIXME: Hrm. How does chdir(2) interact with threads? Does each
mas01cr@498 64 * thread have its own working directory? */
mas01cr@239 65 if((chdir(output)) < 0) {
mas01cr@498 66 goto error;
mas01cr@498 67 }
mas01cr@498 68 directory_changed = 1;
mas01cr@498 69
mas01cr@595 70 if ((fLfd = open("featureList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) {
mas01cr@498 71 goto error;
mas01cr@239 72 }
mas01cr@239 73
mas01cr@509 74 times = adb->header->flags & ADB_HEADER_FLAG_TIMES;
mas01cr@239 75 if (times) {
mas01cr@595 76 if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) {
mas01cr@498 77 goto error;
mas01cr@239 78 }
mas01cr@239 79 }
mas01cr@239 80
mas01cr@509 81 power = adb->header->flags & ADB_HEADER_FLAG_POWER;
mas01cr@239 82 if (power) {
mas01cr@595 83 if ((pLfd = open("powerList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) {
mas01cr@498 84 goto error;
mas01cr@239 85 }
mas01cr@239 86 }
mas01cr@239 87
mas01cr@595 88 if ((kLfd = open("keyList.txt", O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) {
mas01cr@498 89 goto error;
mas01cr@239 90 }
mas01cr@239 91
mas01cr@239 92 /* can these fail? I sincerely hope not. */
mas01cr@239 93 fLFile = fdopen(fLfd, "w");
mas01cr@239 94 if (times) {
mas01cr@239 95 tLFile = fdopen(tLfd, "w");
mas01cr@239 96 }
mas01cr@239 97 if (power) {
mas01cr@239 98 pLFile = fdopen(pLfd, "w");
mas01cr@239 99 }
mas01cr@239 100 kLFile = fdopen(kLfd, "w");
mas01cr@239 101
mas01cr@596 102 lseek_set_or_goto_error(adb->fd, adb->header->dataOffset);
mas01cr@498 103
mas01cr@498 104 for(unsigned k = 0; k < nfiles; k++) {
mas01cr@509 105 fprintf(kLFile, "%s\n", fileTable + k*ADB_FILETABLE_ENTRY_SIZE);
mas01cr@509 106 if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) {
mas01cr@509 107 char *featureFileName = featureFileNameTable+k*ADB_FILETABLE_ENTRY_SIZE;
mas01cr@498 108 if(*featureFileName != '/') {
mas01cr@498 109 goto error;
mas01cr@498 110 }
mas01cr@380 111 fprintf(fLFile, "%s\n", featureFileName);
mas01cr@380 112 if(times) {
mas01cr@509 113 char *timesFileName = timesFileNameTable + k*ADB_FILETABLE_ENTRY_SIZE;
mas01cr@498 114 if(*timesFileName != '/') {
mas01cr@498 115 goto error;
mas01cr@498 116 }
mas01cr@380 117 fprintf(tLFile, "%s\n", timesFileName);
mas01cr@239 118 }
mas01cr@380 119 if(power) {
mas01cr@509 120 char *powerFileName = powerFileNameTable + k*ADB_FILETABLE_ENTRY_SIZE;
mas01cr@498 121 if(*powerFileName != '/') {
mas01cr@498 122 goto error;
mas01cr@498 123 }
mas01cr@380 124 fprintf(pLFile, "%s\n", powerFileName);
mas01cr@239 125 }
mas01cr@380 126 } else {
mas01cr@380 127 snprintf(fName, 256, "%05d.features", k);
mas01cr@595 128 if ((ffd = open(fName, O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) {
mas01cr@498 129 goto error;
mas01cr@239 130 }
mas01cr@498 131 write_or_goto_error(ffd, &(adb->header->dim), sizeof(uint32_t));
mas01cr@380 132
mas01cr@380 133 /* FIXME: this repeated malloc()/free() of data buffers is
mas01cr@380 134 inefficient. */
mas01cr@498 135 data_buffer_size = (*adb->track_lengths)[k] * adb->header->dim * sizeof(double);
mas01cr@380 136
mas01cr@380 137 {
mas01cr@380 138 void *tmp = malloc(data_buffer_size);
mas01cr@380 139 if (tmp == NULL) {
mas01cr@498 140 goto error;
mas01cr@380 141 }
mas01cr@380 142 data_buffer = (double *) tmp;
mas01cr@380 143 }
mas01cr@380 144
mas01cr@498 145 if ((read(adb->fd, data_buffer, data_buffer_size)) != (ssize_t) data_buffer_size) {
mas01cr@498 146 goto error;
mas01cr@380 147 }
mas01cr@380 148
mas01cr@498 149 write_or_goto_error(ffd, data_buffer, data_buffer_size);
mas01cr@380 150
mas01cr@380 151 free(data_buffer);
mas01cr@380 152
mas01cr@380 153 fprintf(fLFile, "%s\n", fName);
mas01cr@380 154 close(ffd);
mas01cr@498 155 ffd = 0;
mas01cr@498 156
mas01cr@380 157 if (times) {
mas01cr@380 158 snprintf(fName, 256, "%05d.times", k);
mas01cr@380 159 tFile = fopen(fName, "w");
mas01cr@498 160 for(unsigned i = 0; i < (*adb->track_lengths)[k]; i++) {
mas01cr@380 161 // KLUDGE: specifying 16 digits of precision after the decimal
mas01cr@380 162 // point is (but check this!) sufficient to uniquely identify
mas01cr@380 163 // doubles; however, that will cause ugliness, as that's
mas01cr@380 164 // vastly too many for most values of interest. Moving to %a
mas01cr@380 165 // here and scanf() in the timesFile reading might fix this.
mas01cr@380 166 // -- CSR, 2007-10-19
mas01cr@380 167 fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*i));
mas01cr@380 168 }
mas01cr@498 169 fprintf(tFile, "%.16e\n", *(timesTable + 2*pos + 2*(*adb->track_lengths)[k]-1));
mas01cr@498 170 fclose(tFile);
mas01cr@380 171
mas01cr@380 172 fprintf(tLFile, "%s\n", fName);
mas01cr@380 173 }
mas01cr@380 174
mas01cr@380 175 if (power) {
mas01cr@380 176 uint32_t one = 1;
mas01cr@380 177 snprintf(fName, 256, "%05d.power", k);
mas01cr@595 178 if ((pfd = open(fName, O_CREAT|O_RDWR|O_EXCL, ADB_CREAT_PERMISSIONS)) < 0) {
mas01cr@498 179 goto error;
mas01cr@380 180 }
mas01cr@498 181 write_or_goto_error(pfd, &one, sizeof(uint32_t));
mas01cr@498 182 write_or_goto_error(pfd, powerTable + pos, (*adb->track_lengths)[k] * sizeof(double));
mas01cr@380 183 fprintf(pLFile, "%s\n", fName);
mas01cr@380 184 close(pfd);
mas01cr@498 185 pfd = 0;
mas01cr@380 186 }
mas01cr@380 187
mas01cr@498 188 pos += (*adb->track_lengths)[k];
mas01cr@509 189 std::cout << fileTable+k*ADB_FILETABLE_ENTRY_SIZE << " " << (*adb->track_lengths)[k] << std::endl;
mas01cr@380 190 }
mas01cr@239 191 }
mas01cr@239 192
mas01cr@239 193 scriptFile = fopen("restore.sh", "w");
mas01cr@239 194 fprintf(scriptFile, "\
mas01cr@239 195 #! /bin/sh\n\
mas01cr@239 196 #\n\
mas01cr@239 197 # usage: AUDIODB=/path/to/audioDB sh ./restore.sh <newdb>\n\
mas01cr@239 198 \n\
mas01cr@239 199 if [ -z \"${AUDIODB}\" ]; then echo set AUDIODB variable; exit 1; fi\n\
mas01cr@239 200 if [ -z \"$1\" ]; then echo usage: $0 newdb; exit 1; fi\n\n\
mas01cr@256 201 \"${AUDIODB}\" -d \"$1\" -N --datasize=%d --ntracks=%d --datadim=%d\n",
mas01cr@498 202 (int) ((adb->header->timesTableOffset - adb->header->dataOffset) / (1024*1024)),
mas01cr@256 203 // fileTable entries (char[256]) are bigger than trackTable
mas01cr@256 204 // (int), so the granularity of page aligning is finer.
mas01cr@509 205 (int) ((adb->header->trackTableOffset - adb->header->fileTableOffset) / ADB_FILETABLE_ENTRY_SIZE),
mas01cr@498 206 (int) ceil(((double) (adb->header->timesTableOffset - adb->header->dataOffset)) / ((double) (adb->header->dbSize - adb->header->l2normTableOffset))));
mas01cr@509 207 if(adb->header->flags & ADB_HEADER_FLAG_L2NORM) {
mas01cr@239 208 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n");
mas01cr@239 209 }
mas01cr@239 210 if(power) {
mas01cr@239 211 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -P\n");
mas01cr@239 212 }
mas01cr@239 213 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -B -F featureList.txt -K keyList.txt");
mas01cr@239 214 if(times) {
mas01cr@239 215 fprintf(scriptFile, " -T timesList.txt");
mas01cr@239 216 }
mas01cr@239 217 if(power) {
mas01cr@239 218 fprintf(scriptFile, " -W powerList.txt");
mas01cr@239 219 }
mas01cr@239 220 fprintf(scriptFile, "\n");
mas01cr@239 221 fclose(scriptFile);
mas01cr@239 222
mas01cr@239 223 fclose(fLFile);
mas01cr@239 224 if(times) {
mas01cr@239 225 fclose(tLFile);
mas01cr@239 226 }
mas01cr@239 227 if(power) {
mas01cr@239 228 fclose(pLFile);
mas01cr@239 229 }
mas01cr@239 230 fclose(kLFile);
mas01cr@239 231
mas01cr@595 232 maybe_free(fileTable);
mas01cr@595 233 maybe_free(timesTable);
mas01cr@595 234 maybe_free(powerTable);
mas01cr@595 235 maybe_free(featureFileNameTable);
mas01cr@595 236 maybe_free(timesFileNameTable);
mas01cr@595 237 maybe_free(powerFileNameTable);
mas01mc@334 238
mas01cr@498 239 if((chdir(cwd)) < 0) {
mas01cr@498 240 /* don't goto error because the error handling will try to
mas01cr@498 241 * chdir() */
mas01cr@498 242 return 1;
mas01mc@334 243 }
mas01mc@334 244
mas01cr@498 245 return 0;
mas01mc@334 246
mas01cr@498 247 error:
mas01cr@498 248 if(fLFile) {
mas01cr@498 249 fclose(fLFile);
mas01cr@498 250 } else if(fLfd) {
mas01cr@498 251 close(fLfd);
mas01cr@498 252 }
mas01cr@498 253 if(tLFile) {
mas01cr@498 254 fclose(tLFile);
mas01cr@498 255 } else if(tLfd) {
mas01cr@498 256 close(fLfd);
mas01cr@498 257 }
mas01cr@498 258 if(pLFile) {
mas01cr@498 259 fclose(pLFile);
mas01cr@498 260 } else if(pLfd) {
mas01cr@498 261 close(pLfd);
mas01cr@498 262 }
mas01cr@498 263 if(kLFile) {
mas01cr@498 264 fclose(kLFile);
mas01cr@498 265 } else if(kLfd) {
mas01cr@498 266 close(kLfd);
mas01cr@498 267 }
mas01cr@498 268 if(scriptFile) {
mas01cr@498 269 fclose(scriptFile);
mas01mc@334 270 }
mas01mc@334 271
mas01cr@595 272 maybe_free(fileTable);
mas01cr@595 273 maybe_free(timesTable);
mas01cr@595 274 maybe_free(powerTable);
mas01cr@595 275 maybe_free(featureFileNameTable);
mas01cr@595 276 maybe_free(timesFileNameTable);
mas01cr@595 277 maybe_free(powerFileNameTable);
mas01cr@498 278
mas01cr@498 279 if(directory_changed) {
mas01cr@498 280 int gcc_warning_workaround = chdir(cwd);
mas01cr@498 281 directory_changed = gcc_warning_workaround;
mas01mc@334 282 }
mas01cr@498 283 return 1;
mas01mc@334 284 }