mas01cr@239: #include "audioDB.h" mas01cr@385: extern "C" { mas01cr@385: #include "audioDB_API.h" mas01cr@385: } mas01cr@410: #include "audioDB-internals.h" mas01cr@410: mas01cr@239: /* Make a new database. mas01cr@239: mas01cr@407: IF size(featuredata) < O2_LARGE_ADB_SIZE mas01cr@239: The database consists of: mas01cr@239: mas01cr@239: * a header (see dbTableHeader struct definition); mas01cr@239: * keyTable: list of keys of tracks; mas01cr@239: * trackTable: Maps implicit feature index to a feature vector mas01cr@239: matrix (sizes of tracks) mas01cr@239: * featureTable: Lots of doubles; mas01cr@239: * timesTable: (start,end) time points for each feature vector; mas01cr@239: * powerTable: associated power for each feature vector; mas01cr@239: * l2normTable: squared l2norms for each feature vector. mas01cr@407: mas01mc@324: ELSE the database consists of: mas01cr@407: mas01mc@324: * a header (see dbTableHeader struct definition); mas01mc@324: * keyTable: list of keys of tracks mas01mc@324: * trackTable: sizes of tracks mas01mc@324: * featureTable: list of feature file names mas01mc@324: * timesTable: list of times file names mas01mc@324: * powerTable: list of power file names mas01mc@324: mas01cr@239: */ mas01cr@239: mas01cr@407: adb_t *audiodb_create(const char *path, unsigned datasize, unsigned ntracks, unsigned datadim) { mas01cr@407: int fd; mas01cr@407: adb_header_t *header = 0; mas01cr@407: off_t databytes, auxbytes; mas01cr@407: if(datasize == 0) { mas01cr@407: datasize = O2_DEFAULT_DATASIZE; mas01cr@407: } mas01cr@407: if(ntracks == 0) { mas01cr@407: ntracks = O2_DEFAULT_NTRACKS; mas01cr@407: } mas01cr@407: if(datadim == 0) { mas01cr@407: datadim = O2_DEFAULT_DATADIM; mas01cr@407: } mas01cr@239: mas01cr@407: if ((fd = open(path, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { mas01cr@407: goto error; mas01cr@407: } mas01cr@407: if (acquire_lock(fd, true)) { mas01cr@407: goto error; mas01cr@407: } mas01cr@389: mas01cr@407: header = (adb_header_t *) malloc(sizeof(adb_header_t)); mas01cr@407: if(!header) { mas01cr@407: goto error; mas01cr@407: } mas01cr@389: mas01cr@407: // Initialize header mas01cr@407: header->magic = O2_MAGIC; mas01cr@407: header->version = O2_FORMAT_VERSION; mas01cr@407: header->numFiles = 0; mas01cr@407: header->dim = 0; mas01cr@407: header->flags = 0; mas01cr@407: header->headerSize = O2_HEADERSIZE; mas01cr@407: header->length = 0; mas01cr@407: header->fileTableOffset = ALIGN_PAGE_UP(O2_HEADERSIZE); mas01cr@407: header->trackTableOffset = ALIGN_PAGE_UP(header->fileTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); mas01cr@407: header->dataOffset = ALIGN_PAGE_UP(header->trackTableOffset + O2_TRACKTABLE_ENTRY_SIZE*ntracks); mas01cr@407: mas01cr@407: databytes = ((off_t) datasize) * 1024 * 1024; mas01cr@407: auxbytes = databytes / datadim; mas01cr@407: mas01cr@458: /* FIXME: what's going on here? There are two distinct preprocessor mas01cr@458: constants (O2_LSH_N_POINT_BITS, LSH_N_POINT_BITS); a third is mas01cr@458: presumably some default (O2_DEFAULT_LSH_N_POINT_BITS), and then mas01cr@458: there's this magic 28 bits [which needs to be the same as the 28 mas01cr@458: in audiodb_lsh_n_point_bits()]. Should this really be part of mas01cr@458: the flags structure at all? Putting it elsewhere will of course mas01cr@458: break backwards compatibility, unless 14 is the only value that's mas01cr@458: been used anywhere... */ mas01cr@407: mas01cr@407: // For backward-compatibility, Record the point-encoding parameter for LSH indexing in the adb header mas01cr@407: // If this value is 0 then it will be set to 14 mas01cr@407: mas01mc@324: #if O2_LSH_N_POINT_BITS > 15 mas01mc@324: #error "AudioDB Compile ERROR: consistency check of O2_LSH_POINT_BITS failed (>15)" mas01mc@324: #endif mas01cr@407: mas01cr@407: header->flags |= LSH_N_POINT_BITS << 28; mas01cr@407: mas01cr@407: // If database will fit in a single file the vectors are copied into the AudioDB instance mas01cr@407: // Else all the vectors are left on the FileSystem and we use the dataOffset as storage mas01cr@407: // for the location of the features, powers and times files (assuming that arbitrary keys are used for the fileTable) mas01cr@407: if(ntrackstimesTableOffset = ALIGN_PAGE_UP(header->dataOffset + databytes); mas01cr@407: header->powerTableOffset = ALIGN_PAGE_UP(header->timesTableOffset + 2*auxbytes); mas01cr@407: header->l2normTableOffset = ALIGN_PAGE_UP(header->powerTableOffset + auxbytes); mas01cr@407: header->dbSize = ALIGN_PAGE_UP(header->l2normTableOffset + auxbytes); mas01cr@407: } else { // Create LARGE_ADB, features and powers kept on filesystem mas01cr@407: header->flags |= O2_FLAG_LARGE_ADB; mas01cr@407: header->timesTableOffset = ALIGN_PAGE_UP(header->dataOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); mas01cr@407: header->powerTableOffset = ALIGN_PAGE_UP(header->timesTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); mas01cr@407: header->l2normTableOffset = ALIGN_PAGE_UP(header->powerTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); mas01cr@407: header->dbSize = header->l2normTableOffset; mas01cr@407: } mas01cr@407: mas01cr@410: write_or_goto_error(fd, header, O2_HEADERSIZE); mas01cr@407: mas01cr@407: // go to the location corresponding to the last byte mas01cr@407: if (lseek (fd, header->dbSize - 1, SEEK_SET) == -1) { mas01cr@407: goto error; mas01cr@407: } mas01cr@407: mas01cr@407: // write a dummy byte at the last location mas01cr@410: write_or_goto_error(fd, "", 1); mas01cr@389: mas01cr@407: free(header); mas01cr@407: return audiodb_open(path, O_RDWR); mas01cr@389: mas01cr@407: error: mas01cr@407: if(header) { mas01cr@390: free(header); mas01mc@324: } mas01cr@407: return NULL; mas01cr@239: }