Main Page   Class Hierarchy   Compound List   File List   Compound Members  

database.h

00001 //-< DATABASE.H >----------------------------------------------------*--------*
00002 // FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *
00003 // (Main Memory Database Management System)                          *   /\|  *
00004 //                                                                   *  /  \  *
00005 //                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
00006 //                          Last update: 23-Dec-98    K.A. Knizhnik  * GARRET *
00007 //-------------------------------------------------------------------*--------*
00008 // Database management
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 // In diskless confiuration database can not be reallocated
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; // milliseconds
00047 const int dbOpenPollInterval = 1000; // milliseconds
00048 const int dbWaitReadyTimeout = 60*1000; // milliseconds
00049 const int dbWaitStatusTimeout = 60*1000; // milliseconds 
00050 const int dbRecoveryConnectionAttempts = 3; 
00051 const int dbStartupConnectionAttempts = 60;
00052 const int dbReplicationWriteTimeout = 60*1000; // milliseconds 
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 // mask for internals object markers
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; // log(sizeof(offs_t))
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; // maximal number of readers concurrently accessing the database
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;  // database file size
00110     int4   curr;  // current root
00111     int4   dirty; // database was not closed normally
00112     int4   initialized; // database is initilaized
00113 #if (dbDatabaseOffsetBits > 32 && defined(ALIGN_HEADER)) || defined(PAD_HEADER)
00114     int4   pad;
00115 #endif
00116     struct { 
00117         offs_t index;           // offset to object index
00118         offs_t shadowIndex;     // offset to shadow index
00119         oid_t  indexSize;       // size of object index
00120         oid_t  shadowIndexSize; // size of object index
00121         oid_t  indexUsed;       // used part of the index   
00122         oid_t  freeList;        // L1 list of free descriptors
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;             // copy of header->root, used to allow read access 
00233                            // to the database during transaction commit
00234     offs_t size; // database 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;     // save context of delayed transaction
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; // milliseconds
00455 
00459         int waitReadyTimeout; // milliseconds
00460 
00464         int waitStatusTimeout; // milliseconds 
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                // Do not specify the following parameter - them are used only for checking
00902                // that application and FastDB library were built with the 
00903                // same compiler options (-DNO_PTHREADS and -REPPLICATION_SUPPORT)
00904                // Mismached parameters should cause linker error
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;         // base address of database file mapping
00933     dbHeader* header;           // database header information
00934     offs_t*   currIndex;        // current database object index
00935     offs_t*   index[2];
00936     unsigned  parThreads;
00937     bool      modified;
00938 
00939     size_t    currRBitmapPage;  //current bitmap page for allocating records
00940     size_t    currRBitmapOffs;  //offset in current bitmap page for allocating
00941                                 //unaligned records
00942     size_t    currPBitmapPage;  //current bitmap page for allocating page objects
00943     size_t    currPBitmapOffs;  //offset in current bitmap page for allocating
00944                                 //page objects
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,  // node is not available 
01693         ST_ONLINE,   // node is available 
01694         ST_ACTIVE,   // primary node is running, replicating changes
01695         ST_STANDBY,  // standby node receives changes from primary node
01696         ST_RECOVERED // node is recovered after the fault
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

Generated on Thu Feb 14 12:42:30 2008 for FastDB by doxygen1.2.18