📄 database.cpp
字号:
::remove(backupFileName); ::rename(newFileName, backupFileName); delete[] newFileName; } } else { return; } }} void dbDatabase::recovery(){ int curr = header->curr; header->size = file.getSize(); header->root[1-curr].indexUsed = header->root[curr].indexUsed; header->root[1-curr].freeList = header->root[curr].freeList; header->root[1-curr].index = header->root[curr].shadowIndex; header->root[1-curr].indexSize = header->root[curr].shadowIndexSize; header->root[1-curr].shadowIndex = header->root[curr].index; header->root[1-curr].shadowIndexSize = header->root[curr].indexSize; offs_t* dst = (offs_t*)(baseAddr+header->root[1-curr].index); offs_t* src = (offs_t*)(baseAddr+header->root[curr].index); currIndex = dst; for (int i = 0, n = header->root[curr].indexUsed; i < n; i++) { if (dst[i] != src[i]) { dst[i] = src[i]; file.markAsDirty(header->root[1-curr].index + i*sizeof(offs_t), sizeof(offs_t)); } } // // Restore consistency of table rows l2-list // restoreTablesConsistency(); file.markAsDirty(0, sizeof(dbHeader));}void dbDatabase::restoreTablesConsistency(){ dbTable* table = (dbTable*)getRow(dbMetaTableId); oid_t lastId = table->lastRow; if (lastId != 0) { dbRecord* record = getRow(lastId); if (record->next != 0) { record->next = 0; file.markAsDirty(currIndex[lastId], sizeof(dbTable)); } } oid_t tableId = table->firstRow; while (tableId != 0) { table = (dbTable*)getRow(tableId); lastId = table->lastRow; if (lastId != 0) { dbRecord* record = getRow(lastId); if (record->next != 0) { record->next = 0; file.markAsDirty(currIndex[lastId], sizeof(dbTable)); } } tableId = table->next; }}void dbDatabase::setConcurrency(unsigned nThreads){ if (nThreads == 0) { // autodetect number of processors nThreads = dbThread::numberOfProcessors(); } if (nThreads > dbMaxParallelSearchThreads) { nThreads = dbMaxParallelSearchThreads; } parThreads = nThreads;}bool dbDatabase::loadScheme(bool alter) { if (!beginTransaction(accessType != dbReadOnly && accessType != dbConcurrentRead ? dbExclusiveLock : dbSharedLock)) { return false; } dbTableDescriptor *desc, *next; dbTable* metaTable = (dbTable*)getRow(dbMetaTableId); oid_t first = metaTable->firstRow; oid_t last = metaTable->lastRow; int nTables = metaTable->nRows; oid_t tableId = first; for (desc = dbTableDescriptor::chain; desc != NULL; desc = next) { next = desc->next; if (desc->db != NULL && desc->db != DETACHED_TABLE && desc->db != this) { continue; } if (desc->db == DETACHED_TABLE) { desc = desc->clone(); } dbFieldDescriptor* fd; for (fd = desc->firstField; fd != NULL; fd = fd->nextField) { fd->tTree = 0; fd->hashTable = 0; fd->attr &= ~dbFieldDescriptor::Updated; } int n = nTables; while (--n >= 0) { dbTable* table = (dbTable*)getRow(tableId); oid_t next = table->next; if (strcmp(desc->name, (char*)table + table->name.offs) == 0) { if (!desc->equal(table)) { if (!alter) { handleError(DatabaseOpenError, "Incompatible class" " definition in application"); return false; } modified = true; if (table->nRows == 0) { TRACE_MSG(("Replace definition of table '%s'\n", desc->name)); updateTableDescriptor(desc, tableId); } else { reformatTable(tableId, desc); } } else { linkTable(desc, tableId); } desc->setFlags(); break; } if (tableId == last) { tableId = first; } else { tableId = next; } } if (n < 0) { // no match found if (accessType == dbReadOnly || accessType == dbConcurrentRead) { handleError(DatabaseOpenError, "New table definition can not " "be added to read only database"); return false; } else { TRACE_MSG(("Create new table '%s' in database\n", desc->name)); addNewTable(desc); modified = true; } } if (accessType != dbReadOnly && accessType != dbConcurrentRead) { if (!addIndices(alter, desc)) { handleError(DatabaseOpenError, "Failed to alter indices with" " active applications"); rollback(); return false; } } } for (desc = tables; desc != NULL; desc = desc->nextDbTable) { if (desc->cloneOf != NULL) { for (dbFieldDescriptor *fd = desc->firstField; fd != NULL; fd = fd->nextField) { if (fd->refTable != NULL) { fd->refTable = lookupTable(fd->refTable); } } } desc->checkRelationship(); } commit(); return true;} void dbDatabase::reformatTable(oid_t tableId, dbTableDescriptor* desc){ dbTable* table = (dbTable*)putRow(tableId); if (desc->match(table, confirmDeleteColumns)) { TRACE_MSG(("New version of table '%s' is compatible with old one\n", desc->name)); updateTableDescriptor(desc, tableId); } else { TRACE_MSG(("Reformat table '%s'\n", desc->name)); oid_t oid = table->firstRow; updateTableDescriptor(desc, tableId); while (oid != 0) { dbRecord* record = getRow(oid); size_t size = desc->columns->calculateNewRecordSize((byte*)record, desc->fixedSize); offs_t offs = currIndex[oid]; record = putRow(oid, size); byte* dst = (byte*)record; byte* src = baseAddr + offs; desc->columns->convertRecord(dst, src, desc->fixedSize); oid = record->next; } }} void dbDatabase::deleteTable(dbTableDescriptor* desc){ beginTransaction(dbExclusiveLock); modified = true; dbTable* table = (dbTable*)putRow(desc->tableId); oid_t rowId = table->firstRow; table->firstRow = table->lastRow = 0; table->nRows = 0; while (rowId != 0) { dbRecord* record = getRow(rowId); oid_t nextId = record->next; size_t size = record->size; removeInverseReferences(desc, rowId); if (rowId < committedIndexSize && index[0][rowId] == index[1][rowId]) { cloneBitmap(currIndex[rowId], size); } else { deallocate(currIndex[rowId], size); } freeId(rowId); rowId = nextId; } dbFieldDescriptor* fd; for (fd = desc->hashedFields; fd != NULL; fd = fd->nextHashedField) { dbHashTable::purge(this, fd->hashTable); } for (fd = desc->indexedFields; fd != NULL; fd = fd->nextIndexedField) { dbTtree::purge(this, fd->tTree); } } void dbDatabase::dropHashTable(dbFieldDescriptor* fd){ beginTransaction(dbExclusiveLock); modified = true; dbHashTable::drop(this, fd->hashTable); fd->hashTable = 0; fd->indexType &= ~HASHED; dbFieldDescriptor** fpp = &fd->defTable->hashedFields; while (*fpp != fd) { fpp = &(*fpp)->nextHashedField; } *fpp = fd->nextHashedField; dbTable* table = (dbTable*)putRow(fd->defTable->tableId); dbField* field = (dbField*)((char*)table + table->fields.offs); field[fd->fieldNo].hashTable = 0;}void dbDatabase::dropIndex(dbFieldDescriptor* fd){ beginTransaction(dbExclusiveLock); modified = true; dbTtree::drop(this, fd->tTree); fd->tTree = 0; fd->indexType &= ~INDEXED; dbFieldDescriptor** fpp = &fd->defTable->indexedFields; while (*fpp != fd) { fpp = &(*fpp)->nextIndexedField; } *fpp = fd->nextIndexedField; dbTable* table = (dbTable*)putRow(fd->defTable->tableId); dbField* field = (dbField*)((char*)table + table->fields.offs); field[fd->fieldNo].tTree = 0;}void dbDatabase::createHashTable(dbFieldDescriptor* fd){ beginTransaction(dbExclusiveLock); modified = true; dbTable* table = (dbTable*)getRow(fd->defTable->tableId); int nRows = table->nRows; fd->hashTable = dbHashTable::allocate(this, 2*nRows); fd->attr &= ~dbFieldDescriptor::Updated; fd->nextHashedField = fd->defTable->hashedFields; fd->defTable->hashedFields = fd; fd->indexType |= HASHED; table = (dbTable*)putRow(fd->defTable->tableId); dbField* field = (dbField*)((char*)table + table->fields.offs); field[fd->fieldNo].hashTable = fd->hashTable; for (oid_t oid = table->firstRow; oid != 0; oid = getRow(oid)->next) { dbHashTable::insert(this, fd->hashTable, oid, fd->type, fd->dbsSize, fd->dbsOffs, nRows); }}void dbDatabase::createIndex(dbFieldDescriptor* fd){ beginTransaction(dbExclusiveLock); modified = true; fd->tTree = dbTtree::allocate(this); fd->attr &= ~dbFieldDescriptor::Updated; fd->nextIndexedField = fd->defTable->indexedFields; fd->defTable->indexedFields = fd; fd->indexType |= INDEXED; dbTable* table = (dbTable*)putRow(fd->defTable->tableId); dbField* field = (dbField*)((char*)table + table->fields.offs); field[fd->fieldNo].tTree = fd->tTree; for (oid_t oid = table->firstRow; oid != 0; oid = getRow(oid)->next) { dbTtree::insert(this, fd->tTree, oid, fd->type, fd->dbsSize, fd->comparator, fd->dbsOffs); }}void dbDatabase::dropTable(dbTableDescriptor* desc){ deleteTable(desc); freeRow(dbMetaTableId, desc->tableId); dbFieldDescriptor* fd; for (fd = desc->hashedFields; fd != NULL; fd = fd->nextHashedField) { dbHashTable::drop(this, fd->hashTable); } for (fd = desc->indexedFields; fd != NULL; fd = fd->nextIndexedField) { dbTtree::drop(this, fd->tTree); } }bool dbDatabase::addIndices(bool alter, dbTableDescriptor* desc){ dbFieldDescriptor* fd; oid_t tableId = desc->tableId; dbTable* table = (dbTable*)getRow(tableId); int nRows = table->nRows; oid_t firstId = table->firstRow; int nNewIndices = 0; int nDelIndices = 0; for (fd = desc->firstField; fd != NULL; fd = fd->nextField) { if ((fd->indexType & HASHED) && fd->type != dbField::tpStructure) { if (fd->hashTable == 0) { if (!alter && tableId < committedIndexSize && index[0][tableId] == index[1][tableId]) { // If there are some other active applications which // can use this table, then they will not know // about newly created index, which leads to inconsistency return false; } fd->hashTable = dbHashTable::allocate(this, nRows); nNewIndices += 1; TRACE_MSG(("Create hash table for field '%s'\n", fd->name)); } } else if (fd->hashTable != 0) { if (alter) { TRACE_MSG(("Remove hash table for field '%s'\n", fd->name)); nDelIndices += 1; fd->hashTable = 0; } else { return false; } } if ((fd->indexType & INDEXED) && fd->type != dbField::tpStructure) { if (fd->tTree == 0) { if (!alter && tableId < committedIndexSize && index[0][tableId] == index[1][tableId]) { return false; } fd->tTree = dbTtree::allocate(this); nNewIndices += 1; TRACE_MSG(("Create index for field '%s'\n", fd->name)); } } else if (fd->tTree != 0) { if (alter) { nDelIndices += 1; TRACE_MSG(("Remove index for field '%s'\n", fd->name)); fd->tTree = 0; } else { return false; } } } if (nNewIndices > 0) { modified = true; for (oid_t rowId = firstId; rowId != 0; rowId = getRow(rowId)->next) { for (fd = desc->hashedFields; fd != NULL; fd=fd->nextHashedField) { if (fd->hashTable >= committedIndexSize || index[0][fd->hashTable] != index[1][fd->hashTable]) { dbHashTable::insert(this, fd->hashTable, rowId, fd->type, fd->dbsSize, fd->dbsOffs, 2*nRows); } } for (fd=desc->indexedFields; fd != NULL; fd=fd->nextIndexedField) { if (fd->tTree >= committedIndexSize || index[0][fd->tTree] != index[1][fd->tTree]) { dbTtree::insert(this, fd->tTree, rowId, fd->type, fd->dbsSize, fd->comparator, fd->dbsOffs); } } } } if (nNewIndices + nDelIndices != 0) { table = (dbTable*)putRow(tableId); offs_t fieldOffs = currIndex[tableId] + table->fields.offs; for (fd = desc->firstField; fd != NULL; fd = fd->nextField) { dbField* field = (dbField*)(baseAddr + fieldOffs); if (field->hashTable != fd->hashTable) { if (field->hashTable != 0) { assert(fd->hashTable == 0); modified = true; dbHashTable::drop(this, field->hashTable); field = (dbField*)(baseAddr + fieldOffs); } field->hashTable = fd->hashTable; } if (field->tTree != fd->tTree) { if (field->tTree != 0) { assert(fd->tTree == 0); modified = true; dbTtree::drop(this, field->tTree); field = (dbField*)(baseAddr + fieldOffs); } field->tTree = fd->tTree; } fieldOffs += sizeof(dbField); } } retur
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -