📄 database.cpp
字号:
{ return false;}void dbDatabase::initializeMetaTable(){ static struct { char const* name; int type; int size; int offs; } metaTableFields[] = { { "name", dbField::tpString, sizeof(dbVarying), offsetof(dbTable, name)}, { "fields", dbField::tpArray, sizeof(dbVarying), offsetof(dbTable, fields)}, { "fields[]", dbField::tpStructure, sizeof(dbField), 0}, { "fields[].name", dbField::tpString, sizeof(dbVarying), offsetof(dbField, name)}, { "fields[].tableName",dbField::tpString,sizeof(dbVarying), offsetof(dbField, tableName)}, { "fields[].inverse", dbField::tpString, sizeof(dbVarying), offsetof(dbField, inverse)},// { "fields[].type", dbField::tpInt4, 4, offsetof(dbField, type)}, { "fields[].type", dbField::tpInt4, 4, offsetof(dbField, offset)-4}, { "fields[].offset", dbField::tpInt4, 4, offsetof(dbField, offset)}, { "fields[].size", dbField::tpInt4, 4, offsetof(dbField, size)}, { "fields[].hashTable", dbField::tpReference, sizeof(oid_t), offsetof(dbField, hashTable)}, { "fields[].tTree", dbField::tpReference, sizeof(oid_t), offsetof(dbField, tTree)}, { "fixedSize", dbField::tpInt4, 4, offsetof(dbTable, fixedSize)}, { "nRows", dbField::tpInt4, 4, offsetof(dbTable, nRows)}, { "nColumns", dbField::tpInt4, 4, offsetof(dbTable, nColumns)}, { "firstRow", dbField::tpReference, sizeof(oid_t), offsetof(dbTable, firstRow)}, { "lastRow", dbField::tpReference, sizeof(oid_t), offsetof(dbTable, lastRow)} #ifdef AUTOINCREMENT_SUPPORT ,{ "count", dbField::tpInt4, 4, offsetof(dbTable, count)} #endif }; unsigned i; size_t varyingSize = strlen(dbMetaTableName)+1; for (i = 0; i < itemsof(metaTableFields); i++) { varyingSize += strlen(metaTableFields[i].name) + 3; } offs_t metaTableOffs = allocate(sizeof(dbTable) + sizeof(dbField)*itemsof(metaTableFields) + varyingSize); index[0][dbMetaTableId] = metaTableOffs; dbTable* table = (dbTable*)(baseAddr + metaTableOffs); table->size = sizeof(dbTable) + sizeof(dbField)*itemsof(metaTableFields) + varyingSize; table->next = table->prev = 0; int offs = sizeof(dbTable) + sizeof(dbField)*itemsof(metaTableFields); table->name.offs = offs; table->name.size = strlen(dbMetaTableName)+1; strcpy((char*)table + offs, dbMetaTableName); offs += table->name.size; table->fields.offs = sizeof(dbTable); table->fields.size = itemsof(metaTableFields); table->fixedSize = sizeof(dbTable); table->nRows = 0; table->nColumns = 5; table->firstRow = 0; table->lastRow = 0;#ifdef AUTOINCREMENT_SUPPORT table->count = 0;#endif dbField* field = (dbField*)((char*)table + table->fields.offs); offs -= sizeof(dbTable); for (i = 0; i < itemsof(metaTableFields); i++) { field->name.offs = offs; field->name.size = strlen(metaTableFields[i].name) + 1; strcpy((char*)field + offs, metaTableFields[i].name); offs += field->name.size; field->tableName.offs = offs; field->tableName.size = 1; *((char*)field + offs++) = '\0'; field->inverse.offs = offs; field->inverse.size = 1; *((char*)field + offs++) = '\0'; field->flags = 0; field->type = metaTableFields[i].type; field->size = metaTableFields[i].size; field->offset = metaTableFields[i].offs; field->hashTable = 0; field->tTree = 0; field += 1; offs -= sizeof(dbField); }}void dbDatabase::cleanup(dbInitializationMutex::initializationStatus status, int step) { switch (step) { case 9: if (status == dbInitializationMutex::NotYetInitialized) { file.close(); } // no break case 8: if (accessType == dbConcurrentUpdate || accessType == dbConcurrentRead) { mutatorCS.close(); } // no break case 7: if (delayedCommitEventsOpened) { delayedCommitStopTimerEvent.close(); delayedCommitStartTimerEvent.close(); commitThreadSyncEvent.close(); delayedCommitEventsOpened = false; } // no break case 6: cs.close(); // no break case 5: backupCompletedEvent.close(); // no break case 4: upgradeSem.close(); // no break case 3: readSem.close(); // no break case 2: writeSem.close(); // no break case 1: shm.close(); // no break default: if (status == dbInitializationMutex::NotYetInitialized) { initMutex.done(); } initMutex.close(); }}bool dbDatabase::open(char const* dbName, char const* fiName, time_t waitLockTimeoutMsec, time_t commitDelaySec){ dbWaitLockTimeout = waitLockTimeoutMsec; delete[] databaseName; delete[] fileName; commitDelay = 0; commitTimeout = 0; commitTimerStarted = 0; delayedCommitEventsOpened = false; backupFileName = NULL; backupPeriod = 0; opened = false; stopDelayedCommitThread = false; databaseNameLen = strlen(dbName); char* name = new char[databaseNameLen+16]; sprintf(name, "%s.in", dbName); databaseName = name; if (fiName == NULL) { fileName = new char[databaseNameLen + 5]; sprintf(fileName, "%s.fdb", dbName); } else { fileName = new char[strlen(fiName)+1]; strcpy(fileName, fiName); } dbInitializationMutex::initializationStatus status = initMutex.initialize(name); if (status == dbInitializationMutex::InitializationError) { handleError(DatabaseOpenError, "Failed to start database initialization"); return false; } sprintf(name, "%s.dm", dbName); if (!shm.open(name)) { handleError(DatabaseOpenError, "Failed to open database monitor"); cleanup(status, 0); return false; } monitor = shm.get(); sprintf(name, "%s.ws", dbName); if (!writeSem.open(name)) { handleError(DatabaseOpenError, "Failed to initialize database writers semaphore"); cleanup(status, 1); return false; } sprintf(name, "%s.rs", dbName); if (!readSem.open(name)) { handleError(DatabaseOpenError, "Failed to initialize database readers semaphore"); cleanup(status, 2); return false; } sprintf(name, "%s.us", dbName); if (!upgradeSem.open(name)) { handleError(DatabaseOpenError, "Failed to initialize database upgrade semaphore"); cleanup(status, 3); return false; } sprintf(name, "%s.bce", dbName); if (!backupCompletedEvent.open(name)) { handleError(DatabaseOpenError, "Failed to initialize database backup completed event"); cleanup(status, 4); return false; } if (commitDelaySec != 0) { sprintf(name, "%s.dce", dbName); delayedCommitEventsOpened = true; if (!delayedCommitStopTimerEvent.open(name)) { handleError(DatabaseOpenError, "Failed to initialize delayed commit event"); cleanup(status, 5); return false; } delayedCommitStartTimerEvent.open(); commitThreadSyncEvent.open(); } backupInitEvent.open(); backupFileName = NULL; allocatedSize = 0; size_t indexSize = initIndexSize < dbFirstUserId ? size_t(dbFirstUserId) : initIndexSize; indexSize = DOALIGN(indexSize, dbHandlesPerPage); size_t fileSize = initSize ? initSize : dbDefaultInitDatabaseSize; if (fileSize < indexSize*sizeof(offs_t)*4) { fileSize = indexSize*sizeof(offs_t)*4; } fileSize = DOALIGN(fileSize, dbBitmapSegmentSize);#ifdef DISKLESS_CONFIGURATION mmapSize = fileSize;#else mmapSize = 0;#endif for (int i = dbBitmapId + dbBitmapPages; --i >= 0;) { bitmapPageAvailableSpace[i] = INT_MAX; } currRBitmapPage = currPBitmapPage = dbBitmapId; currRBitmapOffs = currPBitmapOffs = 0; reservedChain = NULL; tables = NULL; modified = false; selfId = 0; maxClientId = 0; threadContextList.reset(); attach(); if (status == dbInitializationMutex::NotYetInitialized) { sprintf(name, "%s.cs", dbName); if (!cs.create(name, &monitor->sem)) { handleError(DatabaseOpenError, "Failed to initialize database monitor"); cleanup(status, 6); return false; } if (accessType == dbConcurrentUpdate || accessType == dbConcurrentRead) { sprintf(name, "%s.mcs", dbName); if (!mutatorCS.create(name, &monitor->mutatorSem)) { handleError(DatabaseOpenError, "Failed to initialize database monitor"); cleanup(status, 7); return false; } } readSem.reset(); writeSem.reset(); upgradeSem.reset(); monitor->nReaders = 0; monitor->nWriters = 0; monitor->nWaitReaders = 0; monitor->nWaitWriters = 0; monitor->waitForUpgrade = false; monitor->version = version = 1; monitor->users = 0; monitor->backupInProgress = 0; monitor->forceCommitCount = 0; monitor->lastDeadlockRecoveryTime = 0; monitor->delayedCommitContext = NULL; monitor->concurrentTransId = 1; monitor->commitInProgress = false; monitor->uncommittedChanges = false; monitor->clientId = 0; monitor->upgradeId = 0; monitor->modified = false; monitor->exclusiveLockOwner = 0; memset(monitor->dirtyPagesMap, 0, dbDirtyPageBitmapSize); memset(monitor->sharedLockOwner, 0, sizeof(monitor->sharedLockOwner)); sprintf(databaseName, "%s.%d", dbName, version); int rc = file.open(fileName, databaseName, accessType == dbReadOnly || accessType == dbConcurrentRead, fileSize, false); if (rc != dbFile::ok) { char msgbuf[64]; file.errorText(rc, msgbuf, sizeof msgbuf); TRACE_MSG(("File open error: %s\n", msgbuf)); handleError(DatabaseOpenError, "Failed to create database file"); cleanup(status, 8); return false; } baseAddr = (byte*)file.getAddr(); fileSize = file.getSize(); header = (dbHeader*)baseAddr; updatedRecordId = 0; if ((unsigned)header->curr > 1) { handleError(DatabaseOpenError, "Database file was corrupted: " "invalid root index"); cleanup(status, 9); return false; } if (header->initialized != 1) { if (accessType == dbReadOnly || accessType == dbConcurrentRead) { handleError(DatabaseOpenError, "Can not open uninitialized " "file in read only mode"); cleanup(status, 9); return false; } monitor->curr = header->curr = 0; header->size = fileSize; size_t used = dbPageSize; header->root[0].index = used; header->root[0].indexSize = indexSize; header->root[0].indexUsed = dbFirstUserId; header->root[0].freeList = 0; used += indexSize*sizeof(offs_t); header->root[1].index = used; header->root[1].indexSize = indexSize; header->root[1].indexUsed = dbFirstUserId; header->root[1].freeList = 0; used += indexSize*sizeof(offs_t); header->root[0].shadowIndex = header->root[1].index; header->root[1].shadowIndex = header->root[0].index; header->root[0].shadowIndexSize = indexSize; header->root[1].shadowIndexSize = indexSize; header->majorVersion= FASTDB_MAJOR_VERSION; header->minorVersion = FASTDB_MINOR_VERSION; header->mode = dbHeader::getCurrentMode(); index[0] = (offs_t*)(baseAddr + header->root[0].index); index[1] = (offs_t*)(baseAddr + header->root[1].index); index[0][dbInvalidId] = dbFreeHandleMarker; size_t bitmapPages = (used + dbPageSize*(dbAllocationQuantum*8-1) - 1) / (dbPageSize*(dbAllocationQuantum*8-1)); memset(baseAddr+used, 0xFF, (used + bitmapPages*dbPageSize) / (dbAllocationQuantum*8)); size_t i; for (i = 0; i < bitmapPages; i++) { index[0][dbBitmapId + i] = used + dbPageObjectMarker; used += dbPageSize; } while (i < dbBitmapPages) { index[0][dbBitmapId+i] = dbFreeHandleMarker; i += 1; } currIndex = index[0]; currIndexSize = dbFirstUserId; committedIndexSize = 0; initializeMetaTable(); header->dirty = true; memcpy(index[1], index[0], currIndexSize*sizeof(offs_t)); file.markAsDirty(0, used); file.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -