void UDBIndex_finishOpening(UDBIndex *self) { JFile_begin(self->file); UDBIndex_setPos_forPid_(self, 0, 0); UDBIndex_preCommit(self); UDBIndex_findHoles(self); }
void UDB_append_withPid_(UDB *self, Datum d, PID_TYPE pid) { UDBRecord *record = UDBRecords_newRecord(self->records); UDBRecord_pid_(record, pid); UDBRecord_saveWithDatum_(record, d); UDBIndex_setPos_forPid_(self->index, UDBRecord_pos(record), pid); }
void UDB_removeAt_(UDB *self, PID_TYPE pid) { if (UDB_isInTransaction(self)) { UDBRecord *record = UDB_recordAtPid_(self, pid); if (!record) { printf("UDB error: missing record with pid %" PID_FORMAT " for remove\n", pid); record = UDB_recordAtPid_(self, pid); return; } UDBRecords_removeRecord_(self->records, record); UDBIndex_setPos_forPid_(self->index, 0, pid); } }
int UDB_compactStepFor_(UDB *self, double maxSeconds) { UDBRecord *firstEmptyRecord = UDBRecords_firstEmptyRecord(self->records); if (!firstEmptyRecord) { return 0; } if (!UDBRecord_isEmpty(firstEmptyRecord)) { printf("firstEmptyRecord not empty!\n"); firstEmptyRecord = UDBRecords_firstEmptyRecord(self->records); UDBRecord_isEmpty(firstEmptyRecord); exit(1); } #ifdef DEBUG printf("empty record pid: %i pos: %i size: %i isEmpty: %i\n", UDBRecord_pid(firstEmptyRecord), UDBRecord_pos(firstEmptyRecord), UDBRecord_totalSize(firstEmptyRecord), UDBRecord_isEmpty(firstEmptyRecord)); #endif if (firstEmptyRecord) { UDBRecord *record = UDBRecords_recordAfter_(self->records, firstEmptyRecord); if (!record) { // reached end of file PID_TYPE size = UDBRecord_pos(firstEmptyRecord); UDBRecords_truncate_(self->records, size); return 0; } #ifdef DEBUG printf("next record pid: %i pos: %i size: %i isEmpty: %i\n\n", UDBRecord_pid(record), UDBRecord_pos(record), UDBRecord_totalSize(record), UDBRecord_isEmpty(record)); #endif UDB_beginTransaction(self); if (UDBRecord_isEmpty(record)) { // coalese this empty record into the first empty record PID_TYPE newSize = UDBRecord_totalSize(firstEmptyRecord) - sizeof(UDBRecordHeader) + UDBRecord_totalSize(record); UDBRecord_size_(firstEmptyRecord, newSize); UDBRecord_saveHeader(firstEmptyRecord); #ifdef DEBUG printf("merge\n"); #endif UDBIndex_setPos_forPid_(self->index, 0, UDBRecord_pid(record)); } else { // swap places with the first empty record PID_TYPE oldEmptyPos = UDBRecord_pos(firstEmptyRecord); PID_TYPE newEmptyPos = oldEmptyPos + UDBRecord_totalSize(record); UDBRecords_firstEmptyRecordPos_(self->records, newEmptyPos); UDBRecord_moveToPos_(record, UDBRecord_pos(firstEmptyRecord)); UDBRecord_setPos_(firstEmptyRecord, newEmptyPos); UDBRecord_saveHeader(firstEmptyRecord); #ifdef DEBUG printf("move\n"); #endif UDBIndex_setPos_forPid_(self->index, newEmptyPos, UDBRecord_pid(firstEmptyRecord)); UDBIndex_setPos_forPid_(self->index, oldEmptyPos, UDBRecord_pid(record)); } UDB_commitTransaction(self); return 1; } return 0; }