📄 database.h
字号:
dbHeader* header; // database header information
offs_t* currIndex; // current database object index
offs_t* index[2];
unsigned parThreads;
bool modified;
size_t currRBitmapPage; //current bitmap page for allocating records
size_t currRBitmapOffs; //offset in current bitmap page for allocating
//unaligned records
size_t currPBitmapPage; //current bitmap page for allocating page objects
size_t currPBitmapOffs; //offset in current bitmap page for allocating
//page objects
struct dbLocation {
offs_t pos;
size_t size;
dbLocation* next;
};
dbLocation* reservedChain;
char* databaseName;
int databaseNameLen;
char* fileName;
int version;
size_t committedIndexSize;
size_t currIndexSize;
oid_t updatedRecordId;
unsigned waitLockTimeout;
size_t fileSizeLimit;
bool uncommittedChanges;
dbHashFunction hashFunction;
dbFile file;
dbSharedObject<dbMonitor> shm;
dbGlobalCriticalSection cs;
dbGlobalCriticalSection mutatorCS;
dbInitializationMutex initMutex;
dbSemaphore writeSem;
dbSemaphore readSem;
dbSemaphore upgradeSem;
dbEvent backupCompletedEvent;
dbMonitor* monitor;
dbTableDescriptor* tables;
int* bitmapPageAvailableSpace;
bool opened;
offs_t allocatedSize;
offs_t deallocatedSize;
time_t commitDelay;
time_t commitTimeout;
time_t commitTimerStarted;
dbMutex delayedCommitStartTimerMutex;
dbMutex delayedCommitStopTimerMutex;
dbLocalEvent delayedCommitStartTimerEvent;
dbEvent delayedCommitStopTimerEvent;
dbLocalEvent commitThreadSyncEvent;
bool delayedCommitEventsOpened;
dbMutex backupMutex;
dbLocalEvent backupInitEvent;
char* backupFileName;
time_t backupPeriod;
bool stopDelayedCommitThread;
dbThread backupThread;
dbThread commitThread;
int accessCount;
dbL2List threadContextList;
dbMutex threadContextListMutex;
dbErrorHandler errorHandler;
void* errorHandlerContext;
int schemeVersion;
dbVisitedObject* visitedChain;
bool confirmDeleteColumns;
int maxClientId;
int selfId;
#ifdef AUTO_DETECT_PROCESS_CRASH
dbWatchDog selfWatchDog;
dbL2List watchDogThreadContexts;
dbMutex* watchDogMutex;
#endif
unsigned parallelScanThreshold;
/**
* Loads all class descriptors. This method should be used SubSQL and any other apllication
* which is should work with ANY database file.
* @return metatable descriptor
*/
dbTableDescriptor* loadMetaTable();
void cleanup(dbInitializationMutex::initializationStatus status, int step);
void delayedCommit();
void backupScheduler();
static void thread_proc delayedCommitProc(void* arg) {
((dbDatabase*)arg)->delayedCommit();
}
static void thread_proc backupSchedulerProc(void* arg) {
((dbDatabase*)arg)->backupScheduler();
}
virtual bool isReplicated();
#ifdef AUTO_DETECT_PROCESS_CRASH
/**
* Revoke lock of crashed client
* @param clientId ID of crashed client
*/
void revokeLock(int clientId);
/**
* Watch dog thread procedure
* @param ctx watch dog context
*/
static void watchDogThread(dbWatchDogContext* ctx);
/**
* Start watch dog threads for new clients
*/
void startWatchDogThreads();
/**
* Add information about lock owner
*/
void addLockOwner();
/**
* Remove information about lock owner
*/
void removeLockOwner(int clientId);
#endif
/**
* Commit transaction
* @param ctx thread context
*/
void commit(dbDatabaseThreadContext* ctx);
/**
* Restore consistency of table list of rows (last record should contain null reference
* in next field). This method is used during recovery after crash and during rollback.
*/
void restoreTablesConsistency();
/**
* Check if OID corresponds to the valid object
* @param oid inspected OID
* @return whether OID is valid or not
*/
bool isValidOid(oid_t oid) {
if (oid < dbFirstUserId || oid >= currIndexSize) {
return false;
}
return !(currIndex[oid]&(dbFreeHandleMarker|dbInternalObjectMarker));
}
/**
* Get table row
* @param oid object indentifier
* @return object with this oid
*/
dbRecord* getRow(oid_t oid) {
assert(!(currIndex[oid]&(dbFreeHandleMarker|dbInternalObjectMarker)));
return (dbRecord*)(baseAddr + currIndex[oid]);
}
/**
* Prepare for row insertion or update. If record with such OID
* not exists or it is first time when it was changed during this transaction or
* size of recrod is changed, than new record is alocated in the database.
* Otherwisepointer to existed recordis returned.
* @param oid object indetifier
* @param newSize size of new object
* @return pointer inside database where object should should be stored
*/
dbRecord* putRow(oid_t oid, size_t newSize);
/**
* Prepare for object update ithout changing its size
* @param oid object indetifier
* @return pointer inside database where object should should be stored
*/
dbRecord* putRow(oid_t oid) {
if (oid < committedIndexSize && index[0][oid] == index[1][oid]) {
size_t size = getRow(oid)->size;
size_t pageNo = oid/dbHandlesPerPage;
monitor->dirtyPagesMap[pageNo >> 5] |= 1 << (pageNo & 31);
cloneBitmap(currIndex[oid], size);
allocate(size, oid);
}
return (dbRecord*)(baseAddr + currIndex[oid]);
}
/**
* Get record by OID
* @param oid object identifier
* @return pointer to the record inside database
*/
byte* get(oid_t oid) {
return baseAddr + (currIndex[oid] & ~dbInternalObjectMarker);
}
/**
* Prepare for update of internal object.
* @param oid internal object identifier
* @return pointer to the record inside database
*/
byte* put(oid_t oid) {
if (oid < committedIndexSize && index[0][oid] == index[1][oid]) {
offs_t offs = currIndex[oid];
size_t size = internalObjectSize[offs & dbInternalObjectMarker];
size_t pageNo = oid/dbHandlesPerPage;
monitor->dirtyPagesMap[pageNo >> 5] |= 1 << (pageNo & 31);
allocate(size, oid);
cloneBitmap(offs & ~dbInternalObjectMarker, size);
}
return baseAddr + (currIndex[oid] & ~dbInternalObjectMarker);
}
/**
* Check whether query is prefix search: "'key' like field+'%'"
* @param cursor result set
* @param expr evaluated expression
* @param andExpr if not null, then it is used as filter to all records selected by
* index search
* @param indexedFile [out] used to return information about which field was used
* to perfrom index search and so order in which selected records are sorted.
* If this order is the same as requested by "order by" clause, then no extra sorting
* is needed.
* @return true if search was performed using indeices, false if index is not applicable
* and sequential search is required
*/
bool isPrefixSearch(dbAnyCursor* cursor,
dbExprNode* expr, dbExprNode* andExpr,
dbFieldDescriptor* &indexedField);
/**
* Check whether search can be performed using indices
* @param cursor result set
* @param expr evaluated expression
* @param andExpr if not null, then it is used as filter to all records selected by
* index search
* @param indexedFile [out] used to return information about which field was used
* to perfrom index search and so order in which selected records are sorted.
* If this order is the same as requested by "order by" clause, then no extra sorting
* is needed.
* @return true if search was performed using indeices, false if index is not applicable
* and sequential search is required
*/
bool isIndexApplicable(dbAnyCursor* cursor,
dbExprNode* expr, dbExprNode* andExpr,
dbFieldDescriptor* &indexedField);
/**
* Check whether expression can be evaluated unsing index.
* If index is applicable, than index search is performed and result
* is stored in the cursor.
* @param cursor result set
* @param expr evaluated expression
* @param andExpr if not null, then it is used as filter to all records selected by
* index search
* @return true if expression was evaluated using index, false if index is not applicable
* and sequential search is required
*/
bool isIndexApplicable(dbAnyCursor* cursor,
dbExprNode* expr, dbExprNode* andExpr);
/**
* If query predicate contains operands from other tables (accessed by references)
* and inverse references exists, then FastDB performs
* indexed search in referenced table and then go back using inverse referenced to
* query table. followInverseReference method performs this backward traversal of inverse
* references.
* @param expr evaluated expression
* @param andExpr if not null, then it is used as filter to all records selected by
* index search
* @param cursor cursor to collect selected records
* @param iref OID of the selected records in referenced table
*/
bool followInverseReference(dbExprNode* expr, dbExprNode* andExpr,
dbAnyCursor* cursor, oid_t iref);
/**
* Check if there is inverse reference in the table rerefrenced from search predicate.
* @param expr evaluated expression
* @param nExistsClause number of exists clauses in search wrapping this expression
* @return true if inverse reference(s) exists and it is possible to perform backward
* traversal
*/
bool existsInverseReference(dbExprNode* expr, int nExistsClauses);
/**
* Execute expression. This method is most frequently recursivly called during
* evaluation of search predicate.
* @param expr expression to be executed
* @param iattr inherited attributes - attributes passed top-down
* (information like cursor, current record, ...)
* @param sattr synthesized attribute - sttributes passed down-top
* (value of expression)
*/
static void _fastcall execute(dbExprNode* expr,
dbInheritedAttribute& iattr,
dbSynthesizedAttribute& sattr);
/**
* Evaluate epression. This method initialie initiainherited attributes and invoke
* execute method
* @param expr expression to be evaluated
* @param oid OID of the inspected record
* @param seaqched table
* @param cursor result set
* @return true if this record match search condition, false otherwise
*/
bool evaluate(dbExprNode* expr, oid_t oid, dbTable* table, dbAnyCursor* cursor);
/**
* Select all records from the table
* @param cursor result set
*/
void select(dbAnyCursor* cursor);
/**
* Execute select query
* @param cursor result set
* @param query query expression
*/
void select(dbAnyCursor* cursor, dbQuery& query);
/**
* Perform table traverse: execute queries with "start from (follow by)" clause
* @param cursor result set
* @param query query expression
*/
void traverse(dbAnyCursor* cursor, dbQuery& query);
/**
* Update record
* @param oid record identifier
* @param table descriptor of the table to which record belongs
* @param record updated image of the record
*/
void update(oid_t oid, dbTableDescriptor* table, void const* record);
/**
* Remove record from the database
* @param table descriptor of the table to which record belongs
* @param oid record identifier
*/
void remove(dbTableDescriptor* table, oid_t oid);
/**
* Allocate object in the database
* e@param size size of alocated object
* @param oid if oid is not 0, then allocated region position is stored in correcpondent
* cell of object index (needed for allocation of bitmap pages)
* @return position of allcoated region
*/
offs_t allocate(size_t size, oid_t oid = 0);
/**
* Deallocate region
* @param pos start position of region
* @param size of region
*/
void deallocate(offs_t pos, size_t size);
/**
* Checks whther allocated size is greater than size of databae file and recreate
* memory mapping object with larger size n the last case
* @param size allocated size
*/
void extend(offs_t size);
/**
* Clone memory allocation bitmap for region [pos, pos+size)
* @param pos start of region
* @param size size of region
*/
void cloneBitmap(offs_t pos, size_t size);
/**
* Allocate object identifier(s)
* @param number of allocated object indentifiers
* @return object idenitifer (in case if n greater than 1, all n subsequent OIDs are
* allocated and first one is returned
*/
oid_t allocateId(int n = 1);
/**
* Free object identifier(s)
* @param oid deallocated object identifer (or first of n deallocated subsequent identifiers
* if n greater than 1)
* @param number of allocated object indentifiers
*/
void freeId(oid_t oid, int n = 1);
/**
* Update record in in all active cursors if it this record is checnged in the database
* @param oid object indentifier of checnged record
* @param removed true if record was removed
*/
void updateCursors(oid_t oid, bool removed = false);
/**
* Perform database recovery after fault
*/
void recovery();
/**
* Check if program works with correct version of memory mapped object (if memory mapped
* object is reallocated by some client, its version number is incremented, so
* all other client will be able to notice it and also reallocate their memory
* mapping objects.
* @return true if memory mapping object was successfully reallocated or no reallocation
* is needed at all
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -