database.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 2,469 行 · 第 1/5 页
CPP
2,469 行
case dbvmFuncInt2Bool:
execute(expr->func.arg[0], iattr, sattr);
sattr.bvalue = (*(bool(*)(db_int8))expr->func.fptr)(sattr.ivalue);
return;
case dbvmFuncReal2Bool:
execute(expr->func.arg[0], iattr, sattr);
sattr.bvalue = (*(bool(*)(real8))expr->func.fptr)(sattr.fvalue);
return;
case dbvmFuncStr2Bool:
execute(expr->func.arg[0], iattr, sattr);
sattr.bvalue =
(*(bool(*)(char const*))expr->func.fptr)(sattr.array.base);
return;
case dbvmFuncInt2Int:
execute(expr->func.arg[0], iattr, sattr);
sattr.ivalue = (*(db_int8(*)(db_int8))expr->func.fptr)(sattr.ivalue);
return;
case dbvmFuncReal2Int:
execute(expr->func.arg[0], iattr, sattr);
sattr.ivalue = (*(db_int8(*)(real8))expr->func.fptr)(sattr.fvalue);
return;
case dbvmFuncStr2Int:
execute(expr->func.arg[0], iattr, sattr);
sattr.ivalue =
(*(db_int8(*)(char const*))expr->func.fptr)(sattr.array.base);
return;
case dbvmFuncInt2Real:
execute(expr->func.arg[0], iattr, sattr);
sattr.fvalue = (*(real8(*)(db_int8))expr->func.fptr)(sattr.ivalue);
return;
case dbvmFuncReal2Real:
execute(expr->func.arg[0], iattr, sattr);
sattr.fvalue = (*(real8(*)(real8))expr->func.fptr)(sattr.fvalue);
return;
case dbvmFuncStr2Real:
execute(expr->func.arg[0], iattr, sattr);
sattr.fvalue =
(*(real8(*)(char const*))expr->func.fptr)(sattr.array.base);
return;
case dbvmFuncInt2Str:
execute(expr->func.arg[0], iattr, sattr);
copyString(iattr, sattr,
(*(char*(*)(db_int8))expr->func.fptr)(sattr.ivalue));
return;
case dbvmFuncReal2Str:
execute(expr->func.arg[0], iattr, sattr);
copyString(iattr, sattr,
(*(char*(*)(real8))expr->func.fptr)(sattr.fvalue));
return;
case dbvmFuncStr2Str:
execute(expr->func.arg[0], iattr, sattr);
copyString(iattr, sattr,
(*(char*(*)(char const*))expr->func.fptr)(sattr.array.base));
return;
case dbvmInArrayBool:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfBool(sattr, sattr2);
return;
case dbvmInArrayInt1:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfInt1(sattr, sattr2);
return;
case dbvmInArrayInt2:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfInt2(sattr, sattr2);
return;
case dbvmInArrayInt4:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfInt4(sattr, sattr2);
return;
case dbvmInArrayInt8:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfInt8(sattr, sattr2);
return;
case dbvmInArrayReal4:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfReal4(sattr, sattr2);
return;
case dbvmInArrayReal8:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfReal8(sattr, sattr2);
return;
case dbvmInArrayString:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfString(sattr, sattr2);
return;
case dbvmInArrayReference:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchArrayOfReference(sattr, sattr2);
return;
case dbvmInString:
execute(expr->operand[0], iattr, sattr);
execute(expr->operand[1], iattr, sattr2);
searchInString(sattr, sattr2);
return;
default:
assert(false);
}
}
void dbDatabase::handleError(dbErrorClass error, char const* msg, int arg)
{
if (errorHandler != NULL)
{
(*errorHandler)(error, msg, arg);
}
#ifdef THROW_EXCEPTION_ON_ERROR
if (error != NoError)
{
if (error == DatabaseOpenError)
{
fprintf(stderr, "%s\n", msg);
}
else
{
throw dbException(error, msg, arg);
}
}
#else
char buf[256];
switch (error)
{
case QueryError:
fprintf(stderr, "%s in position %d\n", msg, arg);
return;
case ArithmeticError:
fprintf(stderr, "%s\n", msg);
break;
case IndexOutOfRangeError:
fprintf(stderr, "Index %d is out of range\n", arg);
break;
case DatabaseOpenError:
fprintf(stderr, "%s\n", msg);
return;
case FileError:
fprintf(stderr, "%s: %s\n", msg,
dbFile::errorText(arg, buf, sizeof(buf)));
break;
case OutOfMemoryError:
fprintf(stderr,"Not enough memory: failed to allocate %d bytes\n",arg);
break;
case NullReferenceError:
fprintf(stderr, "Null object reference is accessed\n");
break;
case Deadlock:
fprintf(stderr, "Deadlock is caused by upgrading shared locks to exclusive");
break;
case LockRevoked:
fprintf(stderr, "Lock is revoked by some other client");
break;
case InconsistentInverseReference:
fprintf(stderr, "%s\n", msg);
return;
case DatabaseReadOnly:
fprintf(stderr, "Attempt to modify readonly database");
break;
default:
return;
}
abort();
#endif
}
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[].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->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);
}
}
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;
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;
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");
return false;
}
monitor = shm.get();
sprintf(name, "%s.ws", dbName);
if (!writeSem.open(name))
{
handleError(DatabaseOpenError,
"Failed to initialize database writers semaphore");
return false;
}
sprintf(name, "%s.rs", dbName);
if (!readSem.open(name))
{
handleError(DatabaseOpenError,
"Failed to initialize database readers semaphore");
return false;
}
sprintf(name, "%s.us", dbName);
if (!upgradeSem.open(name))
{
handleError(DatabaseOpenError,
"Failed to initialize database upgrade semaphore");
return false;
}
sprintf(name, "%s.bce", dbName);
if (!backupCompletedEvent.open(name))
{
handleError(DatabaseOpenError,
"Failed to initialize database backup completed event");
return false;
}
if (commitDelaySec != 0)
{
sprintf(name, "%s.dce", dbName);
if (!delayedCommitStopTimerEvent.open(name))
{
handleError(DatabaseOpenError,
"Failed to initialize delayed commit event");
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;
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");
return false;
}
if (accessType == dbConcurrentUpdate)
{
sprintf(name, "%s.mcs", dbName);
if (!mutatorCS.create(name, &monitor->mutatorSem))
{
handleError(DatabaseOpenError,
"Failed to initialize database monitor");
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;
memset(monitor->dirtyPagesMap, 0, dbDirtyPageBitmapSize);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?