# HG changeset patch # User mas01cr # Date 1206964379 0 # Node ID a6c9a1c686468c5d54133320c380deb3bd0b94cb # Parent a6ee49f10296f24ae48223d07afa0798fa0bfce3 Detect when we've run out of per-file space on insert() and batchinsert(). Exposed by Lute Music/frames1 dataset, we previously corrupted the trackTable and then got a segfault. This happened because the fileTable and trackTable were mmap()ed next to each other, by coincidence, and the lack of overflow checking on the fileTable meant that continued insertion scribbled over the trackTable, which was twice as big (because it has to be at least one memory page in size). The root cause of all this is the --size creation argument, which needs to be split into --nfiles, --datasize and --dimensions, so that the size of all the tables can be computed accurately. No test case yet, because my /bin/sh is currently pointing to dash, which gets about as far as line 6 of run-tests.sh before giving up. (We need either to fix bashisms or to run /bin/bash explicitly.) diff -r a6ee49f10296 -r a6c9a1c68646 audioDB.h --- a/audioDB.h Mon Feb 18 10:47:03 2008 +0000 +++ b/audioDB.h Mon Mar 31 11:52:59 2008 +0000 @@ -230,6 +230,7 @@ void release_lock(int fd); void create(const char* dbName); void drop(); + bool enough_per_file_space_free(); bool enough_data_space_free(off_t size); void insert_data_vectors(off_t offset, void *buffer, size_t size); void insert(const char* dbName, const char* inFile); diff -r a6ee49f10296 -r a6c9a1c68646 insert.cpp --- a/insert.cpp Mon Feb 18 10:47:03 2008 +0000 +++ b/insert.cpp Mon Mar 31 11:52:59 2008 +0000 @@ -1,5 +1,15 @@ #include "audioDB.h" +bool audioDB::enough_per_file_space_free() { + unsigned int fmaxfiles, tmaxfiles; + unsigned int maxfiles; + + fmaxfiles = fileTableLength / O2_FILETABLESIZE; + tmaxfiles = trackTableLength / O2_TRACKTABLESIZE; + maxfiles = fmaxfiles > tmaxfiles ? tmaxfiles : fmaxfiles; + return(dbH->numFiles < maxfiles); +} + bool audioDB::enough_data_space_free(off_t size) { return(dbH->timesTableOffset > dbH->dataOffset + dbH->length + size); } @@ -19,6 +29,10 @@ if(!usingPower && (dbH->flags & O2_FLAG_POWER)) error("Must use power with power-enabled database", dbName); + if(!enough_per_file_space_free()) { + error("Insert failed: no more room for metadata", inFile); + } + if(!enough_data_space_free(statbuf.st_size - sizeof(int))) { error("Insert failed: no more room in database", inFile); } @@ -210,6 +224,10 @@ initInputFile(thisFile); + if(!enough_per_file_space_free()) { + error("batchinsert failed: no more room for metadata", thisFile); + } + if(!enough_data_space_free(statbuf.st_size - sizeof(int))) { error("batchinsert failed: no more room in database", thisFile); }