annotate open.cpp @ 770:c54bc2ffbf92 tip

update tags
author convert-repo
date Fri, 16 Dec 2011 11:34:01 +0000
parents b1723ae7675e
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@498 5
mas01cr@498 6 static bool audiodb_check_header(adb_header_t *header) {
mas01cr@498 7 /* FIXME: use syslog() or write to stderr or something to give the
mas01cr@498 8 poor user some diagnostics. */
mas01cr@509 9 if(header->magic == ADB_OLD_MAGIC) {
mas01cr@498 10 return false;
mas01cr@498 11 }
mas01cr@509 12 if(header->magic != ADB_MAGIC) {
mas01cr@498 13 return false;
mas01cr@498 14 }
mas01cr@509 15 if(header->version != ADB_FORMAT_VERSION) {
mas01cr@498 16 return false;
mas01cr@498 17 }
mas01cr@509 18 if(header->headerSize != ADB_HEADER_SIZE) {
mas01cr@498 19 return false;
mas01cr@498 20 }
mas01cr@498 21 return true;
mas01cr@498 22 }
mas01cr@498 23
mas01cr@498 24 static int audiodb_collect_keys(adb_t *adb) {
mas01cr@498 25 char *key_table = 0;
mas01cr@498 26 size_t key_table_length = 0;
mas01cr@498 27
mas01cr@498 28 if(adb->header->length > 0) {
mas01cr@498 29 unsigned nfiles = adb->header->numFiles;
mas01cr@509 30 key_table_length = align_page_up(nfiles * ADB_FILETABLE_ENTRY_SIZE);
mas01cr@596 31 malloc_and_fill_or_goto_error(char *, key_table, adb->header->fileTableOffset, key_table_length);
mas01cr@498 32 for (unsigned int k = 0; k < nfiles; k++) {
mas01cr@509 33 adb->keys->push_back(key_table + k*ADB_FILETABLE_ENTRY_SIZE);
mas01cr@509 34 (*adb->keymap)[(key_table + k*ADB_FILETABLE_ENTRY_SIZE)] = k;
mas01cr@498 35 }
mas01cr@592 36 free(key_table);
mas01cr@498 37 }
mas01cr@498 38
mas01cr@498 39 return 0;
mas01cr@498 40
mas01cr@498 41 error:
mas01cr@596 42 maybe_free(key_table);
mas01cr@498 43 return 1;
mas01cr@498 44 }
mas01cr@498 45
mas01cr@498 46 static int audiodb_collect_track_lengths(adb_t *adb) {
mas01cr@498 47 uint32_t *track_table = 0;
mas01cr@498 48 size_t track_table_length = 0;
mas01cr@498 49 if(adb->header->length > 0) {
mas01cr@498 50 unsigned nfiles = adb->header->numFiles;
mas01cr@509 51 track_table_length = align_page_up(nfiles * ADB_TRACKTABLE_ENTRY_SIZE);
mas01cr@596 52 malloc_and_fill_or_goto_error(uint32_t *, track_table, adb->header->trackTableOffset, track_table_length);
mas01cr@498 53 off_t offset = 0;
mas01cr@498 54 for (unsigned int k = 0; k < nfiles; k++) {
mas01cr@498 55 uint32_t track_length = track_table[k];
mas01cr@498 56 adb->track_lengths->push_back(track_length);
mas01cr@498 57 adb->track_offsets->push_back(offset);
mas01cr@498 58 offset += track_length * adb->header->dim * sizeof(double);
mas01cr@498 59 }
mas01cr@592 60 free(track_table);
mas01cr@498 61 }
mas01cr@498 62
mas01cr@498 63 return 0;
mas01cr@498 64
mas01cr@498 65 error:
mas01cr@596 66 maybe_free(track_table);
mas01cr@498 67 return 1;
mas01cr@498 68 }
mas01cr@498 69
mas01cr@693 70 static int audiodb_init_rng(adb_t *adb) {
mas01cr@693 71 gsl_rng *rng = gsl_rng_alloc(gsl_rng_mt19937);
mas01cr@693 72 if(!rng) {
mas01cr@693 73 return 1;
mas01cr@693 74 }
mas01cr@693 75 /* FIXME: maybe we should use a real source of entropy? */
mas01cr@693 76 uint32_t seed = 0;
mas01cr@693 77 #ifdef WIN32
mas01cr@693 78 seed = time(NULL);
mas01cr@693 79 #else
mas01cr@693 80 struct timeval tv;
mas01cr@693 81 if(gettimeofday(&tv, NULL) == -1) {
mas01cr@693 82 return 1;
mas01cr@693 83 }
mas01cr@693 84 /* usec field should be less than than 2^20. We want to mix the
mas01cr@693 85 usec field, highly-variable, into the high bits of the seconds
mas01cr@693 86 field, which will be static between closely-spaced runs. -- CSR,
mas01cr@693 87 2010-01-05 */
mas01cr@693 88 seed = tv.tv_sec ^ (tv.tv_usec << 12);
mas01cr@693 89 #endif
mas01cr@693 90 gsl_rng_set(rng, seed);
mas01cr@693 91 adb->rng = rng;
mas01cr@693 92 return 0;
mas01cr@693 93 }
mas01cr@693 94
mas01cr@498 95 adb_t *audiodb_open(const char *path, int flags) {
mas01cr@498 96 adb_t *adb = 0;
mas01cr@498 97 int fd = -1;
mas01cr@498 98
mas01cr@498 99 flags &= (O_RDONLY|O_RDWR);
mas01cr@498 100 fd = open(path, flags);
mas01cr@498 101 if(fd == -1) {
mas01cr@498 102 goto error;
mas01cr@498 103 }
mas01cr@498 104 if(acquire_lock(fd, flags == O_RDWR)) {
mas01cr@498 105 goto error;
mas01cr@498 106 }
mas01cr@498 107
mas01cr@498 108 adb = (adb_t *) calloc(1, sizeof(adb_t));
mas01cr@498 109 if(!adb) {
mas01cr@498 110 goto error;
mas01cr@498 111 }
mas01cr@498 112 adb->fd = fd;
mas01cr@498 113 adb->flags = flags;
mas01cr@498 114 adb->path = (char *) malloc(1+strlen(path));
mas01cr@498 115 if(!(adb->path)) {
mas01cr@498 116 goto error;
mas01cr@498 117 }
mas01cr@498 118 strcpy(adb->path, path);
mas01cr@498 119
mas01cr@498 120 adb->header = (adb_header_t *) malloc(sizeof(adb_header_t));
mas01cr@498 121 if(!(adb->header)) {
mas01cr@498 122 goto error;
mas01cr@498 123 }
mas01cr@509 124 if(read(fd, (char *) adb->header, ADB_HEADER_SIZE) != ADB_HEADER_SIZE) {
mas01cr@498 125 goto error;
mas01cr@498 126 }
mas01cr@498 127 if(!audiodb_check_header(adb->header)) {
mas01cr@498 128 goto error;
mas01cr@498 129 }
mas01cr@498 130
mas01cr@498 131 adb->keys = new std::vector<std::string>;
mas01cr@498 132 if(!adb->keys) {
mas01cr@498 133 goto error;
mas01cr@498 134 }
mas01cr@498 135 adb->keymap = new std::map<std::string,uint32_t>;
mas01cr@498 136 if(!adb->keymap) {
mas01cr@498 137 goto error;
mas01cr@498 138 }
mas01cr@498 139 if(audiodb_collect_keys(adb)) {
mas01cr@498 140 goto error;
mas01cr@498 141 }
mas01cr@498 142 adb->track_lengths = new std::vector<uint32_t>;
mas01cr@498 143 if(!adb->track_lengths) {
mas01cr@498 144 goto error;
mas01cr@498 145 }
mas01cr@498 146 adb->track_lengths->reserve(adb->header->numFiles);
mas01cr@498 147 adb->track_offsets = new std::vector<off_t>;
mas01cr@498 148 if(!adb->track_offsets) {
mas01cr@498 149 goto error;
mas01cr@498 150 }
mas01cr@498 151 adb->track_offsets->reserve(adb->header->numFiles);
mas01cr@498 152 if(audiodb_collect_track_lengths(adb)) {
mas01cr@498 153 goto error;
mas01cr@498 154 }
mas01cr@498 155 adb->cached_lsh = 0;
mas01cr@693 156 if(audiodb_init_rng(adb)) {
mas01cr@693 157 goto error;
mas01cr@693 158 }
mas01cr@498 159 return adb;
mas01cr@498 160
mas01cr@498 161 error:
mas01cr@498 162 if(adb) {
mas01cr@596 163 maybe_free(adb->header);
mas01cr@596 164 maybe_free(adb->path);
mas01cr@498 165 if(adb->keys) {
mas01cr@498 166 delete adb->keys;
mas01cr@498 167 }
mas01cr@498 168 if(adb->keymap) {
mas01cr@498 169 delete adb->keymap;
mas01cr@498 170 }
mas01cr@498 171 if(adb->track_lengths) {
mas01cr@498 172 delete adb->track_lengths;
mas01cr@498 173 }
mas01cr@693 174 if(adb->rng) {
mas01cr@693 175 gsl_rng_free(adb->rng);
mas01cr@693 176 }
mas01cr@498 177 free(adb);
mas01cr@498 178 }
mas01cr@498 179 if(fd != -1) {
mas01cr@498 180 close(fd);
mas01cr@498 181 }
mas01cr@498 182 return NULL;
mas01cr@498 183 }