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 }
|