📄 database.h
字号:
//-< DATABASE.H >----------------------------------------------------*--------*// FastDB Version 1.0 (c) 1999 GARRET * ? *// (Main Memory Database Management System) * /\| *// * / \ *// Created: 20-Nov-98 K.A. Knizhnik * / [] \ *// Last update: 23-Dec-98 K.A. Knizhnik * GARRET *//-------------------------------------------------------------------*--------*// Database management//-------------------------------------------------------------------*--------*#ifndef __DATABASE_H__#define __DATABASE_H__#include "class.h"#include "reference.h"#include "file.h"BEGIN_FASTDB_NAMESPACE/** * Default size of memory mapping object for the database (bytes) */#ifdef DISKLESS_CONFIGURATION// In diskless confiuration database can not be reallocatedconst size_t dbDefaultInitDatabaseSize = 32*1024*1024;#elseconst size_t dbDefaultInitDatabaseSize = 1024*1024;#endif/** * Default initial index size (number of objects) */const size_t dbDefaultInitIndexSize = 512*1024;/** * Quantum of extension of allocated memory */const size_t dbDefaultExtensionQuantum = 4*1024*1024;/** * Maximal number of threads which can be spawned to perform parallel sequentila search */const unsigned dbMaxParallelSearchThreads = 64;/** * Internal objects tags */enum dbInternalObject { dbTableRow, dbPageObjectMarker, dbTtreeMarker, dbTtreeNodeMarker, dbHashTableMarker, dbHashTableItemMarker, dbRtreeMarker, dbRtreePageMarker, dbInternalObjectMarker = 7 // mask for internals object markers}; const offs_t dbFreeHandleMarker = (offs_t)1 << (sizeof(offs_t)*8 - 1); const size_t dbAllocationQuantumBits = 4;const size_t dbAllocationQuantum = 1 << dbAllocationQuantumBits;const size_t dbPageBits = 12;const size_t dbPageSize = 1 << dbPageBits;const size_t dbIdsPerPage = dbPageSize / sizeof(oid_t);const size_t dbHandlesPerPage = dbPageSize / sizeof(offs_t);const size_t dbHandleBits = 1 + sizeof(offs_t)/4; // log(sizeof(offs_t))const size_t dbBitmapSegmentBits = dbPageBits + 3 + dbAllocationQuantumBits;const size_t dbBitmapSegmentSize = 1 << dbBitmapSegmentBits;const size_t dbBitmapPages = 1 << (dbDatabaseOffsetBits-dbBitmapSegmentBits);const size_t dbDirtyPageBitmapSize = 1 << (dbDatabaseOidBits-dbPageBits+dbHandleBits-3);const size_t dbDefaultSelectionLimit = 2000000000;const int dbBMsearchThreshold = 512;const char dbMatchAnyOneChar = '_';const char dbMatchAnySubstring = '%';const int dbMaxReaders = 64; // maximal number of readers concurrently accessing the database/** * Predefined object identifiers */enum dbPredefinedIds { dbInvalidId, dbMetaTableId, dbBitmapId, dbFirstUserId = dbBitmapId + dbBitmapPages};/** * Database header */class dbHeader { public: offs_t size; // database file size int4 curr; // current root int4 dirty; // database was not closed normally int4 initialized; // database is initilaized int4 pad; struct { offs_t index; // offset to object index offs_t shadowIndex; // offset to shadow index oid_t indexSize; // size of object index oid_t shadowIndexSize; // size of object index oid_t indexUsed; // used part of the index oid_t freeList; // L1 list of free descriptors } root[2]; int4 majorVersion; int4 minorVersion; int4 mode; enum { MODE_OID_64 = 0x01, MODE_OFFS_64 = 0x02, MODE_AUTOINCREMENT = 0x04, MODE_RECTANGLE_DIM = 0x08 }; int getVersion() { return majorVersion*100 + minorVersion; } bool isCompatible(); static int getCurrentMode();};union dbSynthesizedAttribute;struct dbInheritedAttribute;class dbDatabaseThreadContext;class dbAnyCursor;class dbQuery;class dbExprNode;class dbMonitor { public: sharedsem_t sem; sharedsem_t mutatorSem; int nReaders; int nWriters; int nConcurrentWriters; int nWaitReaders; int nWaitWriters; int waitForUpgrade; int forceCommitCount; int backupInProgress; int uncommittedChanges; int curr; // copy of header->root, used to allow read access // to the database during transaction commit int commitInProgress; int concurrentTransId; unsigned lastDeadlockRecoveryTime; int version; int users; dbProcessId ownerPid; dbDatabaseThreadContext* delayedCommitContext; // save context of delayed transaction int4 dirtyPagesMap[dbDirtyPageBitmapSize/4]; int sharedLockOwner[dbMaxReaders]; int exclusiveLockOwner; int clientId; int upgradeId; int modified;};/** * Double linked list */class FASTDB_DLL_ENTRY dbL2List { public: dbL2List* next; dbL2List* prev; void link(dbL2List* elem) { elem->prev = this; elem->next = next; next = next->prev = elem; } void unlink() { next->prev = prev; prev->next = next; next = prev = this; } bool isEmpty() { return next == this; } void reset() { next = prev = this; } dbL2List() { next = prev = this; } ~dbL2List() { unlink(); }};class dbVisitedObject { public: dbVisitedObject* next; oid_t oid; dbVisitedObject(oid_t oid, dbVisitedObject* chain) { this->oid = oid; next = chain; }}; #ifdef AUTO_DETECT_PROCESS_CRASHstruct dbWatchDogContext : dbL2List { dbThread thread; dbWatchDog watchDog; int clientId; dbDatabase* db; dbMutex* mutex;};#endiftemplate<class T> class dbHArray;/** * Database class */class FASTDB_DLL_ENTRY dbDatabase { friend class dbSelection; friend class dbAnyCursor; friend class dbHashTable; friend class dbQuery; friend class dbTtree; friend class dbTtreeNode; friend class dbRtree; friend class dbRtreePage; friend class dbParallelQueryContext; friend class dbServer; friend class dbColumnBinding; friend class dbUserFunctionArgument; friend class dbAnyContainer; friend class dbFile; friend class dbCLI; friend class GiSTdb;#ifdef HAS_TEMPLATE_FRIENDS template<class T> friend class dbHArray;#else friend class dbAnyHArray;#endif public: /** * Open database * @param databaseName database name * @param fielName path to the database file * (if null, then file name daatbaseName + ".fdb" will be used) * @param waitLockTimeoutMsec timeout for waiting locks, by default disabled * @param commitDelaySec delayed commit timeout, by default disabled * @return <code>true</code> if database was successfully opened */ bool open(char const* databaseName, char const* fileName = NULL, time_t waitLockTimeoutMsec = INFINITE, time_t commitDelaySec = 0); /** * Close database */ void close(); /** * Commit transaction */ void commit(); /** * Release all locks hold by transaction allowing other clients to proceed * but do not flush changes to the disk */ void precommit(); /** * Rollback transaction */ void rollback(); /** * Schedule backup * @param fileName path to backup file. If name ends with '?', then * each backup willbe placed in seprate file with '?' replaced with current timestamp * @param periodSec preiod of performing backups in seconds */ void scheduleBackup(char const* fileName, time_t periodSec); /** * Attach current thread to the database. This method should be executed * for all threads except one which opened the database. */ void attach(); enum DetachFlags { COMMIT = 1, DESTROY_CONTEXT = 2 }; /** * Detach thread from the database. * @param flags mask of DetachFlags COMMIT and DESTROY_CONTEXT */ void detach(int flags = COMMIT|DESTROY_CONTEXT); /** * Exclusivly lock the database. */ void lock() { beginTransaction(dbExclusiveLock); } /** * Perform backup to the file with specified name * @param file path to the backup file * @param comactify if true then databae will be compactificated during backup - * i.e. all used objects will be placed together without holes; if false then * backup is performed by just writting memory mapped object to the backup file. * @return whether backup was succeseful or not */ bool backup(char const* file, bool compactify); /** * Perform backup to the specified file * @param file opened file to path to the backup file. This file will not be closed after * backup completion. * @param comactify if true then databae will be compactificated during backup - * i.e. all used objects will be placed together without holes; if false then * backup is performed by just writting memory mapped object to the backup file. * @return whether backup was succeseful or not */ bool backup(dbFile* file, bool compactify); /** * Assign table to the database * @param desc table descriptor */ void assign(dbTableDescriptor& desc) { assert(((void)"Table is not yet assigned to the database", desc.tableId == 0)); desc.db = this; desc.fixedDatabase = true; } /** * Set concurrency level for sequential search and sort operations. * By default, FastDB tries to detect number of CPUs in system and create * the same number of threads. * @param nThreads maximal number of threads to be created for * perfroming cincurrent sequential search and sorting. */ void setConcurrency(unsigned nThreads); /** * Get size allocated in the database since open * @return delta between size of allocated and deallocated data */ long getAllocatedSize() { return allocatedSize; } /** * Get size of the database file * @return database file size */ long getDatabaseSize() { return header->size; } /** * Get number of threads accessing database in shared mode (readonly) * @return number of granted shared locks */ int getNumberOfReaders() { return monitor->nReaders; } /** * Get number of threads accessing database in exclusiveh mode (for update) * @return number of granted exclusive locks (can be either 0 either 1) */ int getNumberOfWriters() { return monitor->nWriters; } /** * Get number of threads blocked while starting read-only transaction * @return number of threads which shared lock request was blocked */ int getNumberOfBlockedReaders() { return monitor->nReaders; } /** * Get number of threads blocked while starting update transaction * @return number of threads which exclusive lock request was blocked */ int getNumberOfBlockedWriters() { return monitor->nWriters; } /** * Get number of processes attached to the database * @return number of processes openned the database */ int getNumberOfUsers() { return monitor->users; } /** * Enable deletion of columns from the table when correspondent fields * are renamed from class descriptor. By default it is switched of * and database allows to delete fields only from empty table (to prevent * unindented loose of data). * @param enabled true to enable column deletion in non empty tables */ void allowColumnsDeletion(bool enabled = true) { confirmDeleteColumns = enabled; } /** * Prepare query. This method can be used for explicit compilation of query and * it's validation * @param cursor result set * @param query query expression * @return <code>true</code> if query is successfully compiled, <code>false</code> othgerwise */ bool prepareQuery(dbAnyCursor* cursor, dbQuery& query); enum dbErrorClass { NoError, QueryError, ArithmeticError, IndexOutOfRangeError, DatabaseOpenError, FileError, OutOfMemoryError, Deadlock, NullReferenceError, LockRevoked, FileLimitExeeded, InconsistentInverseReference, DatabaseReadOnly }; typedef void (*dbErrorHandler)(int error, char const* msg, int msgarg, void* context); /** * Set error handler. Handler should be no-return function which perform stack unwind. * @param newHandler new error handler * @return previous handler */ dbErrorHandler setErrorHandler(dbErrorHandler newHandler, void* errorHandlerContext = NULL); /** * Error handler. * It can be redifined by application to implement application specific error handling. * @param error class of the error * @param msg error message * @param arg optional argument */ virtual void handleError(dbErrorClass error, char const* msg = NULL, int arg = 0); /** * Insert record in the database
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -