void testCactusDisk_getUniqueID_UniqueIntervals(CuTest* testCase) { cactusDiskTestSetup(); stSortedSet *uniqueNames = stSortedSet_construct3(testCactusDisk_getUniqueID_UniqueP, free); for (int64_t i = 0; i < 10; i++) { //Gets a billion ids, checks we are good. int64_t intervalSize = st_randomInt(0, 100000); Name uniqueName = cactusDisk_getUniqueIDInterval(cactusDisk, intervalSize); for(int64_t j=0; j<intervalSize; j++) { CuAssertTrue(testCase, uniqueName > 0); CuAssertTrue(testCase, uniqueName < INT64_MAX); CuAssertTrue(testCase, uniqueName != NULL_NAME); char *cA = cactusMisc_nameToString(uniqueName); CuAssertTrue(testCase, stSortedSet_search(uniqueNames, cA) == NULL); CuAssertTrue(testCase, cactusMisc_stringToName(cA) == uniqueName); stSortedSet_insert(uniqueNames, cA); uniqueName++; } } stSortedSet_destruct(uniqueNames); cactusDiskTestTeardown(); }
Name cactusDisk_addString(CactusDisk *cactusDisk, const char *string) { /* * Adds a string to the database. */ if (cactusDisk->storeSequencesInAFile) { if (cactusDisk->sequencesWriteFileHandle == NULL) { //We do not allow the read file handle to be open at the same time. if (cactusDisk->sequencesReadFileHandle != NULL) { fclose(cactusDisk->sequencesReadFileHandle); cactusDisk->sequencesReadFileHandle = NULL; } cactusDisk->sequencesWriteFileHandle = fopen(cactusDisk->absSequencesFileName, "a"); assert(cactusDisk->sequencesWriteFileHandle != NULL); } else { //The read file handle should not be open at the same time. assert(cactusDisk->sequencesReadFileHandle == NULL); } Name name = ftell(cactusDisk->sequencesWriteFileHandle) + 1; //Extra temporary cheesy code to avoid potential overflow in fprintf int64_t chunkSize = 1000000000; //1 gig approx chunks, to avoid a possible overflow issue with fprintf int64_t length = strlen(string); if (length > chunkSize) { fprintf(cactusDisk->sequencesWriteFileHandle, ">"); for (int64_t i = 0; i < length;) { int64_t j = i + chunkSize <= length ? chunkSize : length - i; char *string2 = memcpy(st_malloc(sizeof(char) * (j + 1)), string + i, sizeof(char) * j); string2[j] = '\0'; int64_t k = fprintf(cactusDisk->sequencesWriteFileHandle, "%s", string2); (void) k; assert(k == j); free(string2); i += j; } } else { //Replacing this line int64_t k = fprintf(cactusDisk->sequencesWriteFileHandle, ">%s", string); (void) k; assert(k == length + 1); } #ifndef NDEBUG // Extra fsync may not be necessary. fsync(fileno(cactusDisk->sequencesWriteFileHandle)); fclose(cactusDisk->sequencesWriteFileHandle); cactusDisk->sequencesWriteFileHandle = NULL; cactusDisk->sequencesReadFileHandle = fopen(cactusDisk->absSequencesFileName, "r"); char *string2 = getStringFromDisk(cactusDisk->sequencesReadFileHandle, name, 0, length); for (int64_t i = 0; i < length; i++) { assert(string[i] == string2[i]); } free(string2); #endif return name; } else { int64_t stringSize = strlen(string); int64_t intervalSize = ceil((double) stringSize / CACTUS_DISK_SEQUENCE_CHUNK_SIZE); Name name = cactusDisk_getUniqueIDInterval(cactusDisk, intervalSize); stList *insertRequests = stList_construct3(0, (void (*)(void *)) stKVDatabaseBulkRequest_destruct); for (int64_t i = 0; i * CACTUS_DISK_SEQUENCE_CHUNK_SIZE < stringSize; i++) { int64_t j = (i + 1) * CACTUS_DISK_SEQUENCE_CHUNK_SIZE < stringSize ? CACTUS_DISK_SEQUENCE_CHUNK_SIZE : stringSize - i * CACTUS_DISK_SEQUENCE_CHUNK_SIZE; char *subString = stString_getSubString(string, i * CACTUS_DISK_SEQUENCE_CHUNK_SIZE, j); stList_append(insertRequests, stKVDatabaseBulkRequest_constructInsertRequest(name + i, subString, j + 1)); free(subString); } stTry { stKVDatabase_bulkSetRecords(cactusDisk->database, insertRequests); } stCatch(except) { stThrowNewCause(except, ST_KV_DATABASE_EXCEPTION_ID, "An unknown database error occurred when we tried to add a string to the cactus disk"); }stTryEnd ; stList_destruct(insertRequests); return name; } }