annotate insert.cpp @ 498:342822c2d49a

Merge api-inversion branch (-r656:771, but I don't expect to return to that branch) into the trunk. I expect there to be minor performance regressions (e.g. in the SOAP server index cacheing, which I have forcibly removed) and minor unplugged memory leaks (e.g. in audioDB::query(), where I don't free up the datum). I hope that these leaks and performance regressions can be plugged in short order. I also expect that some (but maybe not all) of the issues currently addressed in the memory-leaks branch are superseded or fixed by this merge. There remains much work to be done; go forth and do it.
author mas01cr
date Sat, 10 Jan 2009 16:47:57 +0000
parents 7d6dd067d12e
children cc2b97d020b1
rev   line source
mas01cr@239 1 #include "audioDB.h"
mas01cr@498 2 extern "C" {
mas01cr@498 3 #include "audioDB_API.h"
mas01cr@498 4 }
mas01cr@498 5 #include "audioDB-internals.h"
mas01cr@239 6
mas01cr@498 7 static bool audiodb_enough_data_space_free(adb_t *adb, off_t size) {
mas01cr@498 8 adb_header_t *header = adb->header;
mas01cr@498 9 if(header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@498 10 return true;
mas01cr@498 11 } else {
mas01cr@498 12 /* FIXME: timesTableOffset isn't necessarily the next biggest
mas01cr@498 13 * offset after dataOffset. Maybe make the offsets into an array
mas01cr@498 14 * that we can iterate over... */
mas01cr@498 15 return (header->timesTableOffset >
mas01cr@498 16 (header->dataOffset + header->length + size));
mas01cr@239 17 }
mas01cr@239 18 }
mas01cr@239 19
mas01cr@498 20 static bool audiodb_enough_per_file_space_free(adb_t *adb) {
mas01cr@498 21 /* FIXME: the comment above about the ordering of the tables applies
mas01cr@498 22 here too. */
mas01cr@498 23 adb_header_t *header = adb->header;
mas01cr@498 24 off_t file_table_length = header->trackTableOffset - header->fileTableOffset;
mas01cr@498 25 off_t track_table_length = header->dataOffset - header->trackTableOffset;
mas01cr@498 26 int fmaxfiles = file_table_length / O2_FILETABLE_ENTRY_SIZE;
mas01cr@498 27 int tmaxfiles = track_table_length / O2_TRACKTABLE_ENTRY_SIZE;
mas01cr@498 28 /* maxfiles is the _minimum_ of the two. Do not be confused... */
mas01cr@498 29 int maxfiles = fmaxfiles > tmaxfiles ? tmaxfiles : fmaxfiles;
mas01cr@498 30 if(header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@498 31 /* by default, these tables are created with the same size as the
mas01cr@498 32 * fileTable (which should be called key_table); relying on that
mas01cr@498 33 * always being the case, though, smacks of optimism, so instead
mas01cr@498 34 * we code defensively... */
mas01cr@498 35 off_t data_table_length = header->timesTableOffset - header->dataOffset;
mas01cr@498 36 off_t times_table_length = header->powerTableOffset - header->timesTableOffset;
mas01cr@498 37 off_t power_table_length = header->dbSize - header->powerTableOffset;
mas01cr@498 38 int dmaxfiles = data_table_length / O2_FILETABLE_ENTRY_SIZE;
mas01cr@498 39 int timaxfiles = times_table_length / O2_FILETABLE_ENTRY_SIZE;
mas01cr@498 40 int pmaxfiles = power_table_length / O2_FILETABLE_ENTRY_SIZE;
mas01cr@498 41 /* ... even though it means a certain amount of tedium. */
mas01cr@498 42 maxfiles = maxfiles > dmaxfiles ? dmaxfiles : maxfiles;
mas01cr@498 43 maxfiles = maxfiles > timaxfiles ? timaxfiles : maxfiles;
mas01cr@498 44 maxfiles = maxfiles > pmaxfiles ? pmaxfiles : maxfiles;
mas01cr@498 45 }
mas01cr@498 46 return (header->numFiles < (unsigned int) maxfiles);
mas01cr@498 47 }
mas01cr@498 48
mas01cr@498 49 /*
mas01cr@498 50 * Hey, look, a comment. Normally I wouldn't bother, as the code
mas01cr@498 51 * should be self-documenting, but a lot of logic is concentrated in
mas01cr@498 52 * this one place, so let's give an overview beforehand. To insert a
mas01cr@498 53 * datum into the database, we:
mas01cr@498 54 *
mas01cr@498 55 * 1. check write permission;
mas01cr@498 56 * 2. check for enough space;
mas01cr@498 57 * 3. check that datum->dim and adb->header->dim agree (or that the
mas01cr@498 58 * header dimension is zero, in which case write datum->dim to
mas01cr@498 59 * adb->header->dim).
mas01cr@498 60 * 4. check for presence of datum->key in adb->keymap;
mas01cr@498 61 * 5. check for consistency between power and O2_FLAG_POWER, and
mas01cr@498 62 * times and O2_FLAG_TIMES;
mas01cr@498 63 * 6. write in data, power, times as appropriate; add to track
mas01cr@498 64 * and key tables too;
mas01cr@498 65 * 7. if O2_FLAG_L2NORM and !O2_FLAG_LARGE_ADB, compute norms and fill
mas01cr@498 66 * in table;
mas01cr@498 67 * 8. update adb->keys, adb->keymap, adb->track_lengths,
mas01cr@498 68 * adb->track_offsets and adb->header;
mas01cr@498 69 * 9. sync adb->header with disk.
mas01cr@498 70 *
mas01cr@498 71 * Step 9 essentially commits the transaction; until we update
mas01cr@498 72 * header->length, nothing will recognize the newly-written data. In
mas01cr@498 73 * principle, if it fails, we should roll back, which we can in fact
mas01cr@498 74 * do on the assumption that nothing in step 8 can ever fail; on the
mas01cr@498 75 * other hand, if it's failed, then it's unlikely that rolling back by
mas01cr@498 76 * syncing the original header back to disk is going to work
mas01cr@498 77 * desperately well. We should perhaps take an operating-system lock
mas01cr@498 78 * around step 9, so that we can't be interrupted part-way through
mas01cr@498 79 * (except of course for SIGKILL, but if we're hit with that we will
mas01cr@498 80 * always lose).
mas01cr@498 81 */
mas01cr@498 82 static int audiodb_insert_datum_internal(adb_t *adb, adb_datum_internal_t *datum) {
mas01cr@498 83
mas01cr@498 84 off_t size, offset, nfiles;
mas01cr@498 85 double *l2norm_buffer = NULL;
mas01cr@498 86
mas01cr@498 87 /* 1. check write permission; */
mas01cr@498 88 if(!(adb->flags & O_RDWR)) {
mas01cr@498 89 return 1;
mas01cr@498 90 }
mas01cr@498 91 /* 2. check for enough space; */
mas01cr@498 92 size = sizeof(double) * datum->nvectors * datum->dim;
mas01cr@498 93 if(!audiodb_enough_data_space_free(adb, size)) {
mas01cr@498 94 return 1;
mas01cr@498 95 }
mas01cr@498 96 if(!audiodb_enough_per_file_space_free(adb)) {
mas01cr@498 97 return 1;
mas01cr@498 98 }
mas01cr@498 99 /* 3. check that datum->dim and adb->header->dim agree (or that the
mas01cr@498 100 * header dimension is zero, in which case write datum->dim to
mas01cr@498 101 * adb->header->dim).
mas01cr@498 102 */
mas01cr@498 103 if(adb->header->dim == 0) {
mas01cr@498 104 adb->header->dim = datum->dim;
mas01cr@498 105 } else if (adb->header->dim != datum->dim) {
mas01cr@498 106 return 1;
mas01cr@498 107 }
mas01cr@498 108 /* 4. check for presence of datum->key in adb->keymap; */
mas01cr@498 109 if(adb->keymap->count(datum->key)) {
mas01cr@498 110 /* not part of an explicit API/ABI, but we need a distinguished
mas01cr@498 111 value in this circumstance to preserve somewhat wonky behaviour
mas01cr@498 112 of audioDB::batchinsert. */
mas01cr@498 113 return 2;
mas01cr@498 114 }
mas01cr@498 115 /* 5. check for consistency between power and O2_FLAG_POWER, and
mas01cr@498 116 * times and O2_FLAG_TIMES;
mas01cr@498 117 */
mas01cr@498 118 if((datum->power && !(adb->header->flags & O2_FLAG_POWER)) ||
mas01cr@498 119 ((adb->header->flags & O2_FLAG_POWER) && !datum->power)) {
mas01cr@498 120 return 1;
mas01cr@498 121 }
mas01cr@498 122 if(datum->times && !(adb->header->flags & O2_FLAG_TIMES)) {
mas01cr@498 123 if(adb->header->numFiles == 0) {
mas01cr@498 124 adb->header->flags |= O2_FLAG_TIMES;
mas01cr@498 125 } else {
mas01cr@498 126 return 1;
mas01cr@239 127 }
mas01cr@498 128 } else if ((adb->header->flags & O2_FLAG_TIMES) && !datum->times) {
mas01cr@498 129 return 1;
mas01cr@498 130 }
mas01cr@498 131 /* 6. write in data, power, times as appropriate; add to track
mas01cr@498 132 * and key tables too;
mas01cr@498 133 */
mas01cr@498 134 offset = adb->header->length;
mas01cr@498 135 nfiles = adb->header->numFiles;
mas01cr@498 136
mas01cr@498 137 /* FIXME: checking for all these lseek()s */
mas01cr@498 138 lseek(adb->fd, adb->header->fileTableOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@498 139 write_or_goto_error(adb->fd, datum->key, strlen(datum->key)+1);
mas01cr@498 140 lseek(adb->fd, adb->header->trackTableOffset + nfiles * O2_TRACKTABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@498 141 write_or_goto_error(adb->fd, &datum->nvectors, O2_TRACKTABLE_ENTRY_SIZE);
mas01cr@498 142 if(adb->header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@498 143 char cwd[PATH_MAX];
mas01cr@498 144 char slash = '/';
mas01cr@498 145
mas01cr@498 146 if(!getcwd(cwd, PATH_MAX)) {
mas01cr@498 147 goto error;
mas01cr@498 148 }
mas01cr@498 149 lseek(adb->fd, adb->header->dataOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@498 150 if(*((char *) datum->data) != '/') {
mas01cr@498 151 write_or_goto_error(adb->fd, cwd, strlen(cwd));
mas01cr@498 152 write_or_goto_error(adb->fd, &slash, 1);
mas01cr@498 153 }
mas01cr@498 154 write_or_goto_error(adb->fd, datum->data, strlen((const char *) datum->data)+1);
mas01cr@498 155 if(datum->power) {
mas01cr@498 156 lseek(adb->fd, adb->header->powerTableOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@498 157 if(*((char *) datum->power) != '/') {
mas01cr@498 158 write_or_goto_error(adb->fd, cwd, strlen(cwd));
mas01cr@498 159 write_or_goto_error(adb->fd, &slash, 1);
mas01cr@498 160 }
mas01cr@498 161 write_or_goto_error(adb->fd, datum->power, strlen((const char *) datum->power)+1);
mas01cr@498 162 }
mas01cr@498 163 if(datum->times) {
mas01cr@498 164 lseek(adb->fd, adb->header->timesTableOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@498 165 if(*((char *) datum->times) != '/') {
mas01cr@498 166 write_or_goto_error(adb->fd, cwd, strlen(cwd));
mas01cr@498 167 write_or_goto_error(adb->fd, &slash, 1);
mas01cr@498 168 }
mas01cr@498 169 write_or_goto_error(adb->fd, datum->times, strlen((const char *) datum->times)+1);
mas01cr@498 170 }
mas01cr@498 171 } else {
mas01cr@498 172 lseek(adb->fd, adb->header->dataOffset + offset, SEEK_SET);
mas01cr@498 173 write_or_goto_error(adb->fd, datum->data, sizeof(double) * datum->nvectors * datum->dim);
mas01cr@498 174 if(datum->power) {
mas01cr@498 175 lseek(adb->fd, adb->header->powerTableOffset + offset / datum->dim, SEEK_SET);
mas01cr@498 176 write_or_goto_error(adb->fd, datum->power, sizeof(double) * datum->nvectors);
mas01cr@498 177 }
mas01cr@498 178 if(datum->times) {
mas01cr@498 179 lseek(adb->fd, adb->header->timesTableOffset + offset / datum->dim * 2, SEEK_SET);
mas01cr@498 180 write_or_goto_error(adb->fd, datum->times, sizeof(double) * datum->nvectors * 2);
mas01cr@498 181 }
mas01cr@498 182 }
mas01cr@498 183
mas01cr@498 184 /* 7. if O2_FLAG_L2NORM and !O2_FLAG_LARGE_ADB, compute norms and fill
mas01cr@498 185 * in table;
mas01cr@498 186 */
mas01cr@498 187 if((adb->header->flags & O2_FLAG_L2NORM) &&
mas01cr@498 188 !(adb->header->flags & O2_FLAG_LARGE_ADB)) {
mas01cr@498 189 l2norm_buffer = (double *) malloc(datum->nvectors * sizeof(double));
mas01mc@324 190
mas01cr@498 191 audiodb_l2norm_buffer((double *) datum->data, datum->dim, datum->nvectors, l2norm_buffer);
mas01cr@498 192 lseek(adb->fd, adb->header->l2normTableOffset + offset / datum->dim, SEEK_SET);
mas01cr@498 193 write_or_goto_error(adb->fd, l2norm_buffer, sizeof(double) * datum->nvectors);
mas01cr@498 194 free(l2norm_buffer);
mas01cr@498 195 l2norm_buffer = NULL;
mas01cr@498 196 }
mas01cr@498 197
mas01cr@498 198 /* 8. update adb->keys, adb->keymap, adb->track_lengths,
mas01cr@498 199 * adb->track_offsets and adb->header;
mas01cr@498 200 */
mas01cr@498 201 adb->keys->push_back(datum->key);
mas01cr@498 202 (*adb->keymap)[datum->key] = adb->header->numFiles;
mas01cr@498 203 adb->track_lengths->push_back(datum->nvectors);
mas01cr@498 204 adb->track_offsets->push_back(offset);
mas01cr@498 205 adb->header->numFiles += 1;
mas01cr@498 206 adb->header->length += sizeof(double) * datum->nvectors * datum->dim;
mas01cr@498 207
mas01cr@498 208 /* 9. sync adb->header with disk. */
mas01cr@498 209 return audiodb_sync_header(adb);
mas01cr@498 210
mas01cr@498 211 error:
mas01cr@498 212 if(l2norm_buffer) {
mas01cr@498 213 free(l2norm_buffer);
mas01cr@498 214 }
mas01cr@498 215 return 1;
mas01cr@498 216 }
mas01cr@498 217
mas01cr@498 218 int audiodb_insert_datum(adb_t *adb, const adb_datum_t *datum) {
mas01cr@498 219 if(adb->header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@498 220 return 1;
mas01cr@498 221 } else {
mas01cr@498 222 adb_datum_internal_t d;
mas01cr@498 223 d.nvectors = datum->nvectors;
mas01cr@498 224 d.dim = datum->dim;
mas01cr@498 225 d.key = datum->key;
mas01cr@498 226 d.data = datum->data;
mas01cr@498 227 d.times = datum->times;
mas01cr@498 228 d.power = datum->power;
mas01cr@498 229 return audiodb_insert_datum_internal(adb, &d);
mas01cr@498 230 }
mas01cr@498 231 }
mas01cr@498 232
mas01cr@498 233 int audiodb_insert_reference(adb_t *adb, const adb_reference_t *reference) {
mas01cr@498 234 if(!(adb->header->flags & O2_FLAG_LARGE_ADB)) {
mas01cr@498 235 return 1;
mas01cr@498 236 } else {
mas01cr@498 237 adb_datum_internal_t d;
mas01cr@498 238 struct stat st;
mas01cr@498 239 int fd;
mas01cr@498 240 off_t size;
mas01mc@324 241
mas01cr@498 242 if((fd = open(reference->features, O_RDONLY)) == -1) {
mas01cr@498 243 return 1;
mas01cr@239 244 }
mas01cr@498 245 if(fstat(fd, &st)) {
mas01cr@498 246 goto error;
mas01cr@239 247 }
mas01cr@498 248 read_or_goto_error(fd, &(d.dim), sizeof(uint32_t));
mas01cr@498 249 close(fd);
mas01cr@498 250 fd = 0;
mas01cr@498 251 size = st.st_size - sizeof(uint32_t);
mas01cr@498 252 d.nvectors = size / (sizeof(double) * d.dim);
mas01cr@498 253 d.data = (void *) reference->features;
mas01cr@498 254 if(reference->power) {
mas01cr@498 255 if(stat(reference->power, &st)) {
mas01cr@498 256 return 1;
mas01cr@498 257 }
mas01cr@498 258 }
mas01cr@498 259 d.power = (void *) reference->power;
mas01cr@498 260 if(reference->times) {
mas01cr@498 261 if(stat(reference->times, &st)) {
mas01cr@498 262 return 1;
mas01cr@498 263 }
mas01cr@498 264 }
mas01cr@498 265 d.times = (void *) reference->times;
mas01cr@498 266 d.key = reference->key ? reference->key : reference->features;
mas01cr@498 267 return audiodb_insert_datum_internal(adb, &d);
mas01cr@498 268 error:
mas01cr@498 269 if(fd) {
mas01cr@498 270 close(fd);
mas01cr@498 271 }
mas01cr@498 272 return 1;
mas01cr@498 273 }
mas01cr@498 274 }
mas01cr@498 275
mas01cr@498 276 int audiodb_free_datum(adb_datum_t *datum) {
mas01cr@498 277 if(datum->data) {
mas01cr@498 278 free(datum->data);
mas01cr@498 279 datum->data = NULL;
mas01cr@498 280 }
mas01cr@498 281 if(datum->power) {
mas01cr@498 282 free(datum->power);
mas01cr@498 283 datum->power = NULL;
mas01cr@498 284 }
mas01cr@498 285 if(datum->times) {
mas01cr@498 286 free(datum->times);
mas01cr@498 287 datum->times = NULL;
mas01cr@498 288 }
mas01cr@498 289 return 0;
mas01cr@498 290 }
mas01cr@498 291
mas01cr@498 292 int audiodb_insert_create_datum(adb_insert_t *insert, adb_datum_t *datum) {
mas01cr@498 293 int fd = 0;
mas01cr@498 294 FILE *file = NULL;
mas01cr@498 295 struct stat st;
mas01cr@498 296 off_t size;
mas01cr@498 297
mas01cr@498 298 datum->data = NULL;
mas01cr@498 299 datum->power = NULL;
mas01cr@498 300 datum->times = NULL;
mas01cr@498 301 if((fd = open(insert->features, O_RDONLY)) == -1) {
mas01cr@498 302 goto error;
mas01cr@498 303 }
mas01cr@498 304 if(fstat(fd, &st)) {
mas01cr@498 305 goto error;
mas01cr@498 306 }
mas01cr@498 307 read_or_goto_error(fd, &(datum->dim), sizeof(uint32_t));
mas01cr@498 308 size = st.st_size - sizeof(uint32_t);
mas01cr@498 309 datum->nvectors = size / (sizeof(double) * datum->dim);
mas01cr@498 310 datum->data = (double *) malloc(size);
mas01cr@498 311 if(!datum->data) {
mas01cr@498 312 goto error;
mas01cr@498 313 }
mas01cr@498 314 read_or_goto_error(fd, datum->data, size);
mas01cr@498 315 close(fd);
mas01cr@498 316 fd = 0;
mas01cr@498 317 if(insert->power) {
mas01cr@498 318 int dim;
mas01cr@498 319 if((fd = open(insert->power, O_RDONLY)) == -1) {
mas01cr@498 320 goto error;
mas01cr@498 321 }
mas01cr@498 322 if(fstat(fd, &st)) {
mas01cr@498 323 goto error;
mas01cr@498 324 }
mas01cr@498 325 /* This cast is so non-trivial that it deserves a comment.
mas01cr@498 326 *
mas01cr@498 327 * The data types in this expression, left to right, are: off_t,
mas01cr@498 328 * size_t, off_t, uint32_t. The rules for conversions in
mas01cr@498 329 * arithmetic expressions with mixtures of integral types are
mas01cr@498 330 * essentially that the widest type wins, with unsigned types
mas01cr@498 331 * winning on a tie-break.
mas01cr@498 332 *
mas01cr@498 333 * Because we are enforcing (through the use of sufficient
mas01cr@498 334 * compiler flags, if necessary) that off_t be a (signed) 64-bit
mas01cr@498 335 * type, the only variability in this set of types is in fact the
mas01cr@498 336 * size_t. On 32-bit machines, size_t is uint32_t and so the
mas01cr@498 337 * coercions on both sides of the equality end up promoting
mas01cr@498 338 * everything to int64_t, which is fine. On 64-bit machines,
mas01cr@498 339 * however, the left hand side is promoted to a uint64_t, while
mas01cr@498 340 * the right hand side remains int64_t.
mas01cr@498 341 *
mas01cr@498 342 * The mixture of signed and unsigned types in comparisons is Evil
mas01cr@498 343 * Bad and Wrong, and gcc complains about it. (It's right to do
mas01cr@498 344 * so, actually). Of course in this case it will never matter
mas01cr@498 345 * because of the particular relationships between all of these
mas01cr@498 346 * numbers, so we just cast the left hand side to off_t, which
mas01cr@498 347 * will do the right thing for us on all platforms.
mas01cr@498 348 *
mas01cr@498 349 * I hate C.
mas01cr@498 350 */
mas01cr@498 351 if(((off_t) (st.st_size - sizeof(uint32_t))) != (size / datum->dim)) {
mas01cr@498 352 goto error;
mas01cr@498 353 }
mas01cr@498 354 read_or_goto_error(fd, &dim, sizeof(uint32_t));
mas01cr@498 355 if(dim != 1) {
mas01cr@498 356 goto error;
mas01cr@498 357 }
mas01cr@498 358 datum->power = (double *) malloc(size / datum->dim);
mas01cr@498 359 if(!datum->power) {
mas01cr@498 360 goto error;
mas01cr@498 361 }
mas01cr@498 362 read_or_goto_error(fd, datum->power, size / datum->dim);
mas01cr@498 363 close(fd);
mas01cr@498 364 }
mas01cr@498 365 if(insert->times) {
mas01cr@498 366 double t, *tp;
mas01cr@498 367 if(!(file = fopen(insert->times, "r"))) {
mas01cr@498 368 goto error;
mas01cr@498 369 }
mas01cr@498 370 datum->times = (double *) malloc(2 * size / datum->dim);
mas01cr@498 371 if(!datum->times) {
mas01cr@498 372 goto error;
mas01cr@498 373 }
mas01cr@498 374 if(fscanf(file, " %lf", &t) != 1) {
mas01cr@498 375 goto error;
mas01cr@498 376 }
mas01cr@498 377 tp = datum->times;
mas01cr@498 378 *tp++ = t;
mas01cr@498 379 for(unsigned int n = 0; n < datum->nvectors - 1; n++) {
mas01cr@498 380 if(fscanf(file, " %lf", &t) != 1) {
mas01cr@498 381 goto error;
mas01cr@498 382 }
mas01cr@498 383 *tp++ = t;
mas01cr@498 384 *tp++ = t;
mas01cr@498 385 }
mas01cr@498 386 if(fscanf(file, " %lf", &t) != 1) {
mas01cr@498 387 goto error;
mas01cr@498 388 }
mas01cr@498 389 *tp = t;
mas01cr@498 390 fclose(file);
mas01cr@498 391 }
mas01cr@498 392 datum->key = insert->key ? insert->key : insert->features;
mas01cr@498 393 return 0;
mas01cr@498 394
mas01cr@498 395 error:
mas01cr@498 396 if(fd > 0) {
mas01cr@498 397 close(fd);
mas01cr@498 398 }
mas01cr@498 399 if(file) {
mas01cr@498 400 fclose(file);
mas01cr@498 401 }
mas01cr@498 402 audiodb_free_datum(datum);
mas01cr@498 403 return 1;
mas01cr@498 404 }
mas01cr@498 405
mas01cr@498 406 int audiodb_insert(adb_t *adb, adb_insert_t *insert) {
mas01cr@498 407 if(adb->header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@498 408 adb_reference_t *reference = insert;
mas01cr@498 409 int err;
mas01cr@498 410 err = audiodb_insert_reference(adb, reference);
mas01cr@498 411
mas01cr@498 412 if(err == 2) {
mas01cr@498 413 return 0;
mas01cr@498 414 } else {
mas01cr@498 415 return err;
mas01cr@498 416 }
mas01cr@498 417 } else {
mas01cr@498 418 adb_datum_t datum;
mas01cr@498 419 int err;
mas01cr@498 420
mas01cr@498 421 if(audiodb_insert_create_datum(insert, &datum)) {
mas01cr@498 422 return 1;
mas01cr@498 423 }
mas01cr@498 424 err = audiodb_insert_datum(adb, &datum);
mas01cr@498 425 audiodb_free_datum(&datum);
mas01cr@498 426
mas01cr@498 427 if(err == 2) {
mas01cr@498 428 return 0;
mas01cr@498 429 } else {
mas01cr@498 430 return err;
mas01cr@239 431 }
mas01cr@239 432 }
mas01cr@239 433 }
mas01cr@239 434
mas01cr@498 435 int audiodb_batchinsert(adb_t *adb, adb_insert_t *insert, unsigned int size) {
mas01cr@498 436 int err;
mas01cr@498 437 for(unsigned int n = 0; n < size; n++) {
mas01cr@498 438 if((err = audiodb_insert(adb, &(insert[n])))) {
mas01cr@498 439 return err;
mas01cr@498 440 }
mas01mc@324 441 }
mas01cr@498 442 return 0;
mas01cr@239 443 }