00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __DATABASE_H__
00012 #define __DATABASE_H__
00013
00014 #include "class.h"
00015 #include "reference.h"
00016 #include "file.h"
00017
00018 BEGIN_FASTDB_NAMESPACE
00019
00023 #ifdef DISKLESS_CONFIGURATION
00024
00025 const size_t dbDefaultInitDatabaseSize = 32*1024*1024;
00026 #else
00027 const size_t dbDefaultInitDatabaseSize = 1024*1024;
00028 #endif
00029
00033 const size_t dbDefaultInitIndexSize = 512*1024;
00034
00038 const size_t dbDefaultExtensionQuantum = 4*1024*1024;
00039
00043 const unsigned dbMaxParallelSearchThreads = 64;
00044
00045 const int dbDefaultParallelScanThreshold = 1000;
00046 const int dbDefaultPollInterval = 100*1000;
00047 const int dbOpenPollInterval = 1000;
00048 const int dbWaitReadyTimeout = 60*1000;
00049 const int dbWaitStatusTimeout = 60*1000;
00050 const int dbRecoveryConnectionAttempts = 3;
00051 const int dbStartupConnectionAttempts = 60;
00052 const int dbReplicationWriteTimeout = 60*1000;
00053 const int dbMaxAsyncRecoveryIterations = 1000;
00054 const int dbTableHashSize = 1009;
00055
00059 enum dbInternalObject {
00060 dbTableRow,
00061 dbPageObjectMarker,
00062 dbTtreeMarker,
00063 dbTtreeNodeMarker,
00064 dbHashTableMarker,
00065 dbHashTableItemMarker,
00066 dbRtreeMarker,
00067 dbRtreePageMarker,
00068
00069 dbInternalObjectMarker = 7
00070 };
00071
00072 const offs_t dbFreeHandleMarker = (offs_t)1 << (sizeof(offs_t)*8 - 1);
00073
00074 const size_t dbAllocationQuantumBits = 4;
00075 const size_t dbAllocationQuantum = 1 << dbAllocationQuantumBits;
00076 const size_t dbPageBits = 12;
00077 const size_t dbPageSize = 1 << dbPageBits;
00078 const size_t dbIdsPerPage = dbPageSize / sizeof(oid_t);
00079 const size_t dbHandlesPerPage = dbPageSize / sizeof(offs_t);
00080 const size_t dbHandleBits = 1 + sizeof(offs_t)/4;
00081 const size_t dbBitmapSegmentBits = dbPageBits + 3 + dbAllocationQuantumBits;
00082 const size_t dbBitmapSegmentSize = 1 << dbBitmapSegmentBits;
00083 const size_t dbBitmapPages = 1 << (dbDatabaseOffsetBits-dbBitmapSegmentBits);
00084 const size_t dbDirtyPageBitmapSize = 1 << (dbDatabaseOidBits-dbPageBits+dbHandleBits-3);
00085 const size_t dbDefaultSelectionLimit = 2000000000;
00086
00087 const int dbBMsearchThreshold = 512;
00088
00089 const char dbMatchAnyOneChar = '_';
00090 const char dbMatchAnySubstring = '%';
00091
00092 const int dbMaxReaders = 64;
00093
00097 enum dbPredefinedIds {
00098 dbInvalidId,
00099 dbMetaTableId,
00100 dbBitmapId,
00101 dbFirstUserId = dbBitmapId + dbBitmapPages
00102 };
00103
00107 class dbHeader {
00108 public:
00109 offs_t size;
00110 int4 curr;
00111 int4 dirty;
00112 int4 initialized;
00113 #if (dbDatabaseOffsetBits > 32 && defined(ALIGN_HEADER)) || defined(PAD_HEADER)
00114 int4 pad;
00115 #endif
00116 struct {
00117 offs_t index;
00118 offs_t shadowIndex;
00119 oid_t indexSize;
00120 oid_t shadowIndexSize;
00121 oid_t indexUsed;
00122 oid_t freeList;
00123 } root[2];
00124
00125 int4 majorVersion;
00126 int4 minorVersion;
00127 int4 mode;
00128
00129 enum {
00130 MODE_OID_64 = 0x01,
00131 MODE_OFFS_64 = 0x02,
00132 MODE_AUTOINCREMENT = 0x04,
00133 MODE_RECTANGLE_DIM = 0x08
00134 };
00135
00136 int getVersion() {
00137 return majorVersion*100 + minorVersion;
00138 }
00139
00140 bool isCompatible();
00141 static int getCurrentMode();
00142 };
00143
00144 union dbSynthesizedAttribute;
00145 struct dbInheritedAttribute;
00146 class dbDatabaseThreadContext;
00147 class dbAnyCursor;
00148 class dbQuery;
00149 class dbExprNode;
00150
00151 struct dbMemoryStatistic {
00152 offs_t used;
00153 offs_t free;
00154 offs_t nHoles;
00155 offs_t minHoleSize;
00156 offs_t maxHoleSize;
00157 size_t nHolesOfSize[dbDatabaseOffsetBits];
00158 };
00159
00160 class FixedSizeAllocator
00161 {
00162 struct Hole {
00163 Hole* next;
00164 offs_t offs;
00165 };
00166
00167 size_t minSize;
00168 size_t maxSize;
00169 size_t quantum;
00170 size_t nChains;
00171 size_t bufSize;
00172 Hole** chains;
00173 Hole* vacant;
00174 Hole* holes;
00175
00176 public:
00177 size_t hits;
00178 size_t faults;
00179 size_t retries;
00180
00181 FixedSizeAllocator();
00182 ~FixedSizeAllocator();
00183
00184 void init(size_t minSize, size_t maxSize, size_t quantum, size_t bufSize);
00185 void reset();
00186
00187 offs_t allocate(size_t size) {
00188 if (size - minSize <= maxSize - minSize) {
00189 size_t i = (size - minSize + quantum - 1) / quantum;
00190 Hole* hole = chains[i];
00191 if (hole != NULL) {
00192 hits += 1;
00193 chains[i] = hole->next;
00194 hole->next = vacant;
00195 vacant = hole;
00196 return hole->offs;
00197 }
00198 faults += 1;
00199 }
00200 return 0;
00201 }
00202
00203 bool free(offs_t offs, size_t size) {
00204 if (vacant != NULL && size - minSize <= maxSize - minSize) {
00205 size_t i = (size - minSize + quantum - 1) / quantum;
00206 Hole* hole = vacant;
00207 vacant = hole->next;
00208 hole->next = chains[i];
00209 chains[i] = hole;
00210 hole->offs = offs;
00211 return true;
00212 }
00213 return false;
00214 }
00215 };
00216
00217
00218 class dbMonitor {
00219 public:
00220 sharedsem_t sem;
00221 sharedsem_t mutatorSem;
00222 int nReaders;
00223 int nWriters;
00224 int nConcurrentWriters;
00225 int nWaitReaders;
00226 int nWaitWriters;
00227 int waitForUpgrade;
00228 int forceCommitCount;
00229 int backupInProgress;
00230 int uncommittedChanges;
00231
00232 int curr;
00233
00234 offs_t size;
00235
00236 int commitInProgress;
00237 int concurrentTransId;
00238
00239 unsigned lastDeadlockRecoveryTime;
00240
00241 int version;
00242 int users;
00243
00244 dbProcessId ownerPid;
00245
00246 dbDatabaseThreadContext* delayedCommitContext;
00247
00248 int4 dirtyPagesMap[dbDirtyPageBitmapSize/4];
00249
00250 int sharedLockOwner[dbMaxReaders];
00251 int exclusiveLockOwner;
00252 int clientId;
00253 int upgradeId;
00254
00255 int modified;
00256
00257 #ifdef DO_NOT_REUSE_OID_WITHIN_SESSION
00258 struct {
00259 oid_t head;
00260 oid_t tail;
00261 } sessionFreeList[2];
00262 #endif
00263 };
00264
00268 class FASTDB_DLL_ENTRY dbL2List {
00269 public:
00270 dbL2List* next;
00271 dbL2List* prev;
00272
00273 void link(dbL2List* elem) {
00274 elem->prev = this;
00275 elem->next = next;
00276 next = next->prev = elem;
00277 }
00278 void unlink() {
00279 next->prev = prev;
00280 prev->next = next;
00281 next = prev = this;
00282 }
00283 bool isEmpty() {
00284 return next == this;
00285 }
00286 void reset() {
00287 next = prev = this;
00288 }
00289 dbL2List() {
00290 next = prev = this;
00291 }
00292 ~dbL2List() {
00293 unlink();
00294 }
00295 };
00296
00297 class dbVisitedObject {
00298 public:
00299 dbVisitedObject* next;
00300 oid_t oid;
00301
00302 dbVisitedObject(oid_t oid, dbVisitedObject* chain) {
00303 this->oid = oid;
00304 next = chain;
00305 }
00306 };
00307
00308 #ifdef AUTO_DETECT_PROCESS_CRASH
00309 struct dbWatchDogContext : dbL2List {
00310 dbThread thread;
00311 dbWatchDog watchDog;
00312 int clientId;
00313 dbDatabase* db;
00314 dbMutex* mutex;
00315 };
00316 #endif
00317
00318 template<class T>
00319 class dbHArray;
00320
00321 class dbXmlContext;
00322 class dbXmlScanner;
00323
00324 typedef unsigned (*dbHashFunction)(byte* key, int type, int keylen);
00325
00329 class FASTDB_DLL_ENTRY dbDatabase {
00330 friend class dbSelection;
00331 friend class dbAnyCursor;
00332 friend class dbHashTable;
00333 friend class dbQuery;
00334 friend class dbTtree;
00335 friend class dbTtreeNode;
00336 friend class dbRtree;
00337 friend class dbRtreePage;
00338 friend class dbParallelQueryContext;
00339 friend class dbServer;
00340 friend class dbColumnBinding;
00341 friend class dbUserFunctionArgument;
00342 friend class dbAnyContainer;
00343 friend class dbFile;
00344 friend class dbCLI;
00345 friend class GiSTdb;
00346
00347 #ifdef HAS_TEMPLATE_FRIENDS
00348 template<class T>
00349 friend class dbHArray;
00350 #else
00351 friend class dbAnyHArray;
00352 #endif
00353
00354 public:
00364 bool open(char const* databaseName,
00365 char const* fileName = NULL,
00366 time_t waitLockTimeoutMsec = INFINITE,
00367 time_t commitDelaySec = 0);
00368
00369 enum dbAccessType {
00370 dbReadOnly,
00371 dbAllAccess,
00372 dbConcurrentRead,
00373 dbConcurrentUpdate
00374 };
00375
00379 struct OpenParameters {
00383 char const* databaseName;
00384
00388 char const* databaseFilePath;
00389
00393 time_t transactionCommitDelay;
00394
00398 time_t waitLockTimeoutMsec;
00399
00403 dbAccessType accessType;
00404
00408 size_t initSize;
00409
00413 size_t extensionQuantum;
00414
00418 size_t initIndexSize;
00419
00423 int nThreads;
00424
00429 offs_t freeSpaceReuseThreshold;
00430
00434 int parallelScanThreshold;
00435
00439 int nodeId;
00440
00444 char** nodeAddresses;
00445
00449 int nNodes;
00450
00454 int pollInterval;
00455
00459 int waitReadyTimeout;
00460
00464 int waitStatusTimeout;
00465
00469 int recoveryConnectionAttempts;
00470
00474 int startupConnectionAttempts;
00475
00481 int replicationWriteTimeout;
00482
00488 int maxAsyncRecoveryIterations;
00489
00490 OpenParameters() {
00491 databaseName = NULL;
00492 databaseFilePath = NULL;
00493 transactionCommitDelay = 0;
00494 waitLockTimeoutMsec = INFINITE;
00495 accessType = dbAllAccess;
00496 extensionQuantum = dbDefaultExtensionQuantum;
00497 initSize = dbDefaultInitDatabaseSize;
00498 initIndexSize = dbDefaultInitIndexSize;
00499 nThreads = 1;
00500 freeSpaceReuseThreshold = dbDefaultExtensionQuantum;
00501 nodeId = 0;
00502 nodeAddresses = NULL;
00503 nNodes = 0;
00504 parallelScanThreshold = dbDefaultParallelScanThreshold;
00505 pollInterval = dbDefaultPollInterval;
00506 waitReadyTimeout = dbWaitReadyTimeout;
00507 waitStatusTimeout = dbWaitStatusTimeout;
00508 recoveryConnectionAttempts = dbRecoveryConnectionAttempts;
00509 startupConnectionAttempts = dbStartupConnectionAttempts;
00510 replicationWriteTimeout = dbReplicationWriteTimeout;
00511 maxAsyncRecoveryIterations = dbMaxAsyncRecoveryIterations;
00512 }
00513 };
00514
00520 bool open(OpenParameters& params);
00521
00525 void close();
00526
00530 void commit();
00531
00536 void precommit();
00537
00541 void rollback();
00542
00549 void scheduleBackup(char const* fileName, time_t periodSec);
00550
00555 void attach();
00556
00562 void attach(dbDatabaseThreadContext* ctx);
00563
00564
00565 enum DetachFlags {
00566 COMMIT = 1,
00567 DESTROY_CONTEXT = 2
00568 };
00573 void detach(int flags = COMMIT|DESTROY_CONTEXT);
00574
00575 enum dbLockType {
00576 dbSharedLock,
00577 dbExclusiveLock,
00578 dbCommitLock
00579 };
00580
00584 void lock(dbLockType lock = dbExclusiveLock) { beginTransaction(lock); }
00585
00594 bool backup(char const* file, bool compactify);
00595
00605 bool backup(dbFile* file, bool compactify);
00606
00611 void assign(dbTableDescriptor& desc) {
00612 assert(((void)"Table is not yet assigned to the database",
00613 desc.tableId == 0));
00614 desc.db = this;
00615 desc.fixedDatabase = true;
00616 }
00617
00625 void setConcurrency(unsigned nThreads);
00626
00631 long getAllocatedSize() { return allocatedSize; }
00632
00637 long getDatabaseSize() { return header->size; }
00638
00643 int getNumberOfReaders() {
00644 return monitor->nReaders;
00645 }
00646
00651 int getNumberOfWriters() {
00652 return monitor->nWriters;
00653 }
00654
00659 int getNumberOfBlockedReaders() {
00660 return monitor->nReaders;
00661 }
00662
00667 int getNumberOfBlockedWriters() {
00668 return monitor->nWriters;
00669 }
00670
00675 int getNumberOfUsers() {
00676 return monitor->users;
00677 }
00678
00686 void allowColumnsDeletion(bool enabled = true) {
00687 confirmDeleteColumns = enabled;
00688 }
00689
00697 bool prepareQuery(dbAnyCursor* cursor, dbQuery& query);
00698
00699 enum dbErrorClass {
00700 NoError,
00701 QueryError,
00702 ArithmeticError,
00703 IndexOutOfRangeError,
00704 DatabaseOpenError,
00705 FileError,
00706 OutOfMemoryError,
00707 Deadlock,
00708 NullReferenceError,
00709 LockRevoked,
00710 FileLimitExeeded,
00711 InconsistentInverseReference,
00712 DatabaseReadOnly,
00713 AssertionFailed
00714 };
00715 static char const* const errorMessage[];
00716 typedef void (*dbErrorHandler)(int error, char const* msg, int msgarg, void* context);
00717
00723 dbErrorHandler setErrorHandler(dbErrorHandler newHandler, void* errorHandlerContext = NULL);
00724
00732 virtual void handleError(dbErrorClass error, char const* msg = NULL,
00733 int arg = 0);
00734
00743 virtual void formatErrorMessage(char* buf, size_t bufSize, dbErrorClass error, char const* msg = NULL, int arg = 0);
00744
00748 virtual void fatalError();
00749
00756 void insertRecord(dbTableDescriptor* table, dbAnyReference* ref,
00757 void const* record);
00758
00762 bool isOpen() const { return opened; }
00763
00764
00768 bool isCommitted();
00769
00773 bool isAttached();
00774
00778 bool isUpdateTransaction();
00779
00783 int getVersion();
00784
00789 void setFileSizeLimit(size_t limit) {
00790 fileSizeLimit = limit;
00791 }
00792
00793 #ifdef FUZZY_CHECKPOINT
00794
00799 void setFuzzyCheckpointBuffer(size_t nPages) {
00800 file.setCheckpointBufferSize(nPages);
00801 }
00802 #endif
00803
00804 #ifndef NO_MEMBER_TEMPLATES
00805
00810 template<class T>
00811 dbReference<T> insert(T const& record) {
00812 dbReference<T> ref;
00813 insertRecord(lookupTable(&T::dbDescriptor), &ref, &record);
00814 return ref;
00815 }
00816 #endif
00817
00823 dbTableDescriptor* lookupTable(dbTableDescriptor* desc);
00824
00829 void getMemoryStatistic(dbMemoryStatistic& stat);
00830
00835 int getNumberOfProceededTransactions() {
00836 return monitor->concurrentTransId - 1;
00837 }
00838
00844 bool isValidOid(oid_t oid) {
00845 if (oid < dbFirstUserId || oid >= currIndexSize) {
00846 return false;
00847 }
00848 return !(currIndex[oid]&(dbFreeHandleMarker|dbInternalObjectMarker));
00849 }
00850
00855 void exportDatabaseToXml(FILE* out);
00856
00862 bool importDatabaseFromXml(FILE* in);
00863
00871 void setFixedSizeAllocator(size_t minSize, size_t maxSize, size_t quantum, size_t bufSize) {
00872 fixedSizeAllocator.init(minSize, maxSize, quantum, bufSize);
00873 }
00874
00875 enum dbThreadMode {
00876 dbNotUsePthreads,
00877 dbUsePthreads
00878 };
00879
00880 enum dbReplicationMode {
00881 dbReplicated,
00882 dbStandalone
00883 };
00884
00896 dbDatabase(dbAccessType type = dbAllAccess,
00897 size_t dbInitSize = dbDefaultInitDatabaseSize,
00898 size_t dbExtensionQuantum = dbDefaultExtensionQuantum,
00899 size_t dbInitIndexSize = dbDefaultInitIndexSize,
00900 int nThreads = 1
00901
00902
00903
00904
00905 #ifdef NO_PTHREADS
00906 , dbThreadMode threadMode = dbNotUsePthreads
00907 #endif
00908 #ifdef REPLICATION_SUPPORT
00909 , dbReplicationMode replicationMode = dbReplicated
00910 #endif
00911 );
00915 virtual ~dbDatabase();
00916
00917 dbAccessType accessType;
00918 size_t initSize;
00919 size_t extensionQuantum;
00920 size_t initIndexSize;
00921 offs_t freeSpaceReuseThreshold;
00922
00923 protected:
00924 static size_t internalObjectSize[];
00925
00926 dbThreadPool threadPool;
00927
00928 FixedSizeAllocator fixedSizeAllocator;
00929
00930 dbThreadContext<dbDatabaseThreadContext> threadContext;
00931
00932 byte* baseAddr;
00933 dbHeader* header;
00934 offs_t* currIndex;
00935 offs_t* index[2];
00936 unsigned parThreads;
00937 bool modified;
00938
00939 size_t currRBitmapPage;
00940 size_t currRBitmapOffs;
00941
00942 size_t currPBitmapPage;
00943 size_t currPBitmapOffs;
00944
00945 struct dbLocation {
00946 offs_t pos;
00947 size_t size;
00948 dbLocation* next;
00949 };
00950 dbLocation* reservedChain;
00951
00952 char* databaseName;
00953 int databaseNameLen;
00954 char* fileName;
00955 int version;
00956
00957 size_t committedIndexSize;
00958 size_t currIndexSize;
00959 oid_t updatedRecordId;
00960
00961 unsigned waitLockTimeout;
00962
00963 size_t fileSizeLimit;
00964 bool uncommittedChanges;
00965
00966 dbHashFunction hashFunction;
00967
00968 dbFile file;
00969 dbSharedObject<dbMonitor> shm;
00970 dbGlobalCriticalSection cs;
00971 dbGlobalCriticalSection mutatorCS;
00972 dbInitializationMutex initMutex;
00973 dbSemaphore writeSem;
00974 dbSemaphore readSem;
00975 dbSemaphore upgradeSem;
00976 dbEvent backupCompletedEvent;
00977 dbMonitor* monitor;
00978
00979 dbTableDescriptor* tables;
00980
00981 int* bitmapPageAvailableSpace;
00982 bool opened;
00983
00984 offs_t allocatedSize;
00985 offs_t deallocatedSize;
00986
00987 time_t commitDelay;
00988 time_t commitTimeout;
00989 time_t commitTimerStarted;
00990
00991 dbMutex delayedCommitStartTimerMutex;
00992 dbMutex delayedCommitStopTimerMutex;
00993 dbLocalEvent delayedCommitStartTimerEvent;
00994 dbEvent delayedCommitStopTimerEvent;
00995 dbLocalEvent commitThreadSyncEvent;
00996 bool delayedCommitEventsOpened;
00997
00998 dbMutex backupMutex;
00999 dbLocalEvent backupInitEvent;
01000 char* backupFileName;
01001 time_t backupPeriod;
01002 bool stopDelayedCommitThread;
01003
01004 dbThread backupThread;
01005 dbThread commitThread;
01006
01007 int accessCount;
01008
01009 dbL2List threadContextList;
01010 dbMutex threadContextListMutex;
01011
01012 dbErrorHandler errorHandler;
01013 void* errorHandlerContext;
01014 int schemeVersion;
01015 dbVisitedObject* visitedChain;
01016
01017 bool confirmDeleteColumns;
01018
01019 int maxClientId;
01020 int selfId;
01021
01022 dbXmlContext* xmlContext;
01023
01024 #ifdef AUTO_DETECT_PROCESS_CRASH
01025 dbWatchDog selfWatchDog;
01026 dbL2List watchDogThreadContexts;
01027 dbMutex* watchDogMutex;
01028 #endif
01029
01030 unsigned parallelScanThreshold;
01031 dbTableDescriptor* tableHash[dbTableHashSize];
01032
01033 void exportScheme(FILE* out);
01034 void exportClass(FILE* out, char* name, dbFieldDescriptor* fieldList);
01035
01036 oid_t mapId(long id);
01037 bool importField(char* terminator, dbFieldDescriptor* fd, byte* rec, dbXmlScanner& scanner);
01038 bool importRecord(char* terminator, dbFieldDescriptor* fieldList, byte* rec, dbXmlScanner& scanner);
01039 void insertRecord(dbTableDescriptor* desc, oid_t oid, void const* record);
01040
01046 dbTableDescriptor* loadMetaTable();
01047
01048 void cleanup(dbInitializationMutex::initializationStatus status, int step);
01049
01050 void delayedCommit();
01051 void backupScheduler();
01052
01053 static void thread_proc delayedCommitProc(void* arg) {
01054 ((dbDatabase*)arg)->delayedCommit();
01055 }
01056
01057 static void thread_proc backupSchedulerProc(void* arg) {
01058 ((dbDatabase*)arg)->backupScheduler();
01059 }
01060
01061 virtual bool isReplicated();
01062
01063 virtual void close0();
01064
01065 #ifdef AUTO_DETECT_PROCESS_CRASH
01066
01070 void revokeLock(int clientId);
01071
01076 static void watchDogThread(dbWatchDogContext* ctx);
01077
01081 void startWatchDogThreads();
01082
01086 void addLockOwner();
01087
01091 void removeLockOwner(int clientId);
01092 #endif
01093
01098 void commit(dbDatabaseThreadContext* ctx);
01099
01104 void restoreTablesConsistency();
01105
01111 dbRecord* getRow(oid_t oid) {
01112 assert(!(currIndex[oid]&(dbFreeHandleMarker|dbInternalObjectMarker)));
01113 return (dbRecord*)(baseAddr + currIndex[oid]);
01114 }
01115
01125 dbRecord* putRow(oid_t oid, size_t newSize);
01126
01132 dbRecord* putRow(oid_t oid) {
01133 if (oid < committedIndexSize && index[0][oid] == index[1][oid]) {
01134 size_t size = getRow(oid)->size;
01135 size_t pageNo = oid/dbHandlesPerPage;
01136 monitor->dirtyPagesMap[pageNo >> 5] |= 1 << (pageNo & 31);
01137 cloneBitmap(currIndex[oid], size);
01138 allocate(size, oid);
01139 }
01140 return (dbRecord*)(baseAddr + currIndex[oid]);
01141 }
01142
01148 byte* get(oid_t oid) {
01149 return baseAddr + (currIndex[oid] & ~dbInternalObjectMarker);
01150 }
01151
01157 byte* put(oid_t oid) {
01158 if (oid < committedIndexSize && index[0][oid] == index[1][oid]) {
01159 offs_t offs = currIndex[oid];
01160 size_t size = internalObjectSize[offs & dbInternalObjectMarker];
01161 size_t pageNo = oid/dbHandlesPerPage;
01162 monitor->dirtyPagesMap[pageNo >> 5] |= 1 << (pageNo & 31);
01163 allocate(size, oid);
01164 cloneBitmap(offs & ~dbInternalObjectMarker, size);
01165 }
01166 return baseAddr + (currIndex[oid] & ~dbInternalObjectMarker);
01167 }
01168
01182 bool isPrefixSearch(dbAnyCursor* cursor,
01183 dbExprNode* expr, dbExprNode* andExpr,
01184 dbFieldDescriptor* &indexedField);
01185
01199 bool isIndexApplicable(dbAnyCursor* cursor,
01200 dbExprNode* expr, dbExprNode* andExpr,
01201 dbFieldDescriptor* &indexedField);
01202
01214 bool isIndexApplicable(dbAnyCursor* cursor,
01215 dbExprNode* expr, dbExprNode* andExpr);
01216
01229 bool followInverseReference(dbExprNode* expr, dbExprNode* andExpr,
01230 dbAnyCursor* cursor, oid_t iref);
01231
01239 bool existsInverseReference(dbExprNode* expr, int nExistsClauses);
01240
01250 static void _fastcall execute(dbExprNode* expr,
01251 dbInheritedAttribute& iattr,
01252 dbSynthesizedAttribute& sattr);
01253
01263 bool evaluate(dbExprNode* expr, oid_t oid, dbTable* table, dbAnyCursor* cursor);
01264
01269 void select(dbAnyCursor* cursor);
01270
01276 void select(dbAnyCursor* cursor, dbQuery& query);
01277
01283 void traverse(dbAnyCursor* cursor, dbQuery& query);
01284
01291 void update(oid_t oid, dbTableDescriptor* table, void const* record);
01292
01298 void remove(dbTableDescriptor* table, oid_t oid);
01299
01307 offs_t allocate(size_t size, oid_t oid = 0);
01308
01314 void deallocate(offs_t pos, size_t size);
01315
01321 void extend(offs_t size);
01322
01328 void cloneBitmap(offs_t pos, size_t size);
01329
01336 oid_t allocateId(int n = 1);
01337
01344 void freeId(oid_t oid, int n = 1);
01345
01351 void updateCursors(oid_t oid, bool removed = false);
01352
01356 void recovery();
01357
01366 bool checkVersion();
01367
01373 oid_t allocateObject(dbInternalObject marker) {
01374 oid_t oid = allocateId();
01375 offs_t pos = allocate(internalObjectSize[marker]) + marker;
01376 currIndex[oid] = pos;
01377 return oid;
01378 }
01379
01386 oid_t allocateRow(oid_t tableId, size_t size)
01387 {
01388 oid_t oid = allocateId();
01389 allocateRow(tableId, oid, size);
01390 return oid;
01391 }
01392
01400 void allocateRow(oid_t tableId, oid_t oid, size_t size);
01401
01407 void freeRow(oid_t tableId, oid_t oid);
01408
01412 void freeObject(oid_t oid);
01413
01417 static void deleteCompiledQuery(dbExprNode* tree);
01418
01425 bool beginTransaction(dbLockType);
01426
01430 void endTransaction() {
01431 endTransaction(threadContext.get());
01432 }
01433
01438 void endTransaction(dbDatabaseThreadContext* ctx);
01439
01440 virtual void waitTransactionAcknowledgement();
01441
01446 void initializeMetaTable();
01447
01455 bool loadScheme(bool alter);
01456
01462 bool completeDescriptorsInitialization();
01463
01469 void reformatTable(oid_t tableId, dbTableDescriptor* desc);
01470
01478 bool addIndices(bool alter, dbTableDescriptor* desc);
01479
01485 oid_t addNewTable(dbTableDescriptor* desc);
01486
01492 void updateTableDescriptor(dbTableDescriptor* desc, oid_t tableId);
01493
01502 void insertInverseReference(dbFieldDescriptor* fd,
01503 oid_t reverseId, oid_t targetId);
01504
01510 void removeInverseReferences(dbTableDescriptor* desc, oid_t oid);
01511
01520 void removeInverseReference(dbFieldDescriptor* fd,
01521 oid_t reverseId, oid_t targetId);
01522
01527 void deleteTable(dbTableDescriptor* desc);
01528
01533 void dropTable(dbTableDescriptor* desc);
01534
01539 void createIndex(dbFieldDescriptor* fd);
01540
01545 void createHashTable(dbFieldDescriptor* fd);
01546
01551 void dropIndex(dbFieldDescriptor* fd);
01552
01557 void dropHashTable(dbFieldDescriptor* fd);
01558
01564 void linkTable(dbTableDescriptor* table, oid_t tableId);
01565
01570 void unlinkTable(dbTableDescriptor* table);
01571
01578 bool wasReserved(offs_t pos, size_t size);
01579
01588 void reserveLocation(dbLocation& location, offs_t pos, size_t size);
01589
01594 void commitLocation();
01595
01601 dbTableDescriptor* findTable(char const* name);
01602
01609 dbTableDescriptor* findTableByName(char const* name);
01610
01615 dbTableDescriptor* getTables() {
01616 return tables;
01617 }
01618
01622 void setDirty();
01623
01629 bool isFree(offs_t pos, int objBitSize);
01630
01636 void markAsAllocated(offs_t pos, int objBitSize);
01637
01638 };
01639
01640
01641 #ifdef REPLICATION_SUPPORT
01642
01643 #include "sockio.h"
01644
01645 class FASTDB_DLL_ENTRY dbConnection {
01646 public:
01647 socket_t* reqSock;
01648 socket_t* respSock;
01649 dbLocalEvent statusEvent;
01650 dbLocalEvent readyEvent;
01651 dbLocalEvent useEvent;
01652 dbLocalEvent committedEvent;
01653 dbMutex writeCS;
01654 int useCount;
01655 int waitUseEventFlag;
01656 int waitStatusEventFlag;
01657 int status;
01658 int updateCounter;
01659 int nRecoveredPages;
01660
01661 dbConnection() {
01662 readyEvent.open();
01663 useEvent.open();
01664 statusEvent.open();
01665 committedEvent.open();
01666 useCount = 0;
01667 waitUseEventFlag = 0;
01668 waitStatusEventFlag = 0;
01669 status = 0;
01670 reqSock = respSock = NULL;
01671 nRecoveredPages = 0;
01672 }
01673 ~dbConnection() {
01674 readyEvent.close();
01675 useEvent.close();
01676 statusEvent.close();
01677 committedEvent.close();
01678 delete reqSock;
01679 delete respSock;
01680 }
01681 };
01682
01683 class FASTDB_DLL_ENTRY dbReplicatedDatabase : public dbDatabase {
01684 friend class dbFile;
01685 protected:
01686 char** serverURL;
01687 int nServers;
01688 int id;
01689 dbConnection* con;
01690
01691 enum NodeStatus {
01692 ST_OFFLINE,
01693 ST_ONLINE,
01694 ST_ACTIVE,
01695 ST_STANDBY,
01696 ST_RECOVERED
01697 };
01698
01699 dbLocalEvent startEvent;
01700 dbLocalEvent recoveredEvent;
01701 dbMutex startCS;
01702 dbMutex commitCS;
01703 fd_set inputSD;
01704 int nInputSD;
01705
01706 int activeNodeId;
01707 int masterNodeId;
01708 bool onlineRecovery;
01709 bool handshake;
01710 dbMutex sockCS;
01711 socket_t* acceptSock;
01712 dbThread readerThread;
01713
01714 int pollInterval;
01715 int waitReadyTimeout;
01716 int waitStatusTimeout;
01717 int recoveryConnectionAttempts;
01718 int startupConnectionAttempts;
01719 int replicationWriteTimeout;
01720 int maxAsyncRecoveryIterations;
01721
01722 static void thread_proc startReader(void* arg);
01723
01724 void waitTransactionAcknowledgement();
01725
01726 void reader();
01727 virtual void close0();
01728 virtual bool isReplicated();
01729
01730 public:
01731 void deleteConnection(int nodeId);
01732 void lockConnection(int nodeId);
01733 void unlockConnection(int nodeId);
01734 void changeActiveNode();
01735 void addConnection(int nodeId, socket_t* s);
01736 bool writeReq(int nodeId, ReplicationRequest const& hdr,
01737 void* body = NULL, size_t bodySize = 0);
01738 bool writeResp(int nodeId, ReplicationRequest const& hdr);
01739
01740 bool open(char const* databaseName, char const* fileName,
01741 int id, char* servers[], int nServers);
01742 bool open(OpenParameters& params);
01743
01744 int getNumberOfOnlineNodes();
01745
01746 dbReplicatedDatabase(dbAccessType type = dbAllAccess,
01747 size_t dbInitSize = dbDefaultInitDatabaseSize,
01748 size_t dbExtensionQuantum = dbDefaultExtensionQuantum,
01749 size_t dbInitIndexSize = dbDefaultInitIndexSize,
01750 int nThreads = 1);
01751 };
01752 #endif
01753
01754 template<class T>
01755 dbReference<T> insert(T const& record) {
01756 dbReference<T> ref;
01757 T::dbDescriptor.getDatabase()->insertRecord(&T::dbDescriptor, &ref, &record);
01758 return ref;
01759 }
01760
01761 #ifdef NO_MEMBER_TEMPLATES
01762 template<class T>
01763 dbReference<T> insert(dbDatabase& db, T const& record) {
01764 dbReference<T> ref;
01765 db.insertRecord(db.lookupTable(&T::dbDescriptor), &ref, &record);
01766 return ref;
01767 }
01768 #endif
01769
01773 class dbSearchContext {
01774 public:
01775 dbDatabase* db;
01776 dbExprNode* condition;
01777 dbAnyCursor* cursor;
01778 char* firstKey;
01779 int firstKeyInclusion;
01780 char* lastKey;
01781 int lastKeyInclusion;
01782 int type;
01783 int sizeofType;
01784 int prefixLength;
01785 dbUDTComparator comparator;
01786 int offs;
01787 int probes;
01788 };
01789
01790
01791 END_FASTDB_NAMESPACE
01792
01793 #endif