⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 database.h

📁 用于嵌入式环境的数据库
💻 H
📖 第 1 页 / 共 3 页
字号:
     * Get database version
     */
    int  getVersion();

    /**
     * Specify database file size limit. Attempt to exeed this limit cause database error.
     * @param limit maximal file size in bytes
     */
    void setFileSizeLimit(size_t limit) { 
        dbFileSizeLimit = limit;
    }

#ifndef NO_MEMBER_TEMPLATES
    /**
     * Insert record in the database
     * @param record transient object to be insrted in the database
     * @return reference to the created object
     */
    template<class T>
    dbReference<T> insert(T const& record) {
        dbReference<T> ref;
        insertRecord(lookupTable(&T::dbDescriptor), &ref, &record);
        return ref;
    }
#endif
    /**
     * Find cloned table desciptor assigned to this database 
     * @param des static unassigned table descriptor
     * @return clone of this table descriptor assigned to this databae or NULL
     * if not found.
     */
    dbTableDescriptor* lookupTable(dbTableDescriptor* desc);

    enum dbAccessType { 
        dbReadOnly         = 0,
        dbAllAccess        = 1,
        dbConcurrentRead   = 2,
        dbConcurrentUpdate = 3
    };
    /**
     * Database constructor
     * @param type access type: <code>dbDatabase::dbReadOnly</code> or <code>dbDatabase::dbAllAcces</code>
     * @param dbInitSize initial size of the database. If FastDB is compiled with 
     * DISKLESS_CONFIGURATION option, then in this parameter <B>MAXIMAL</B> size of the 
     * database should be specified (in this mode database can not be reallocated)
     * @param dbExtensionQuantum quentum for extending memory allocation bitmap 
     * @param dbInitIndexSize initial index size (objects)
     * @param nThreads concurrency level for sequential search and sort operations 
     * @see setConcurrency(unsigned nThreads)
     */
    dbDatabase(dbAccessType type = dbAllAccess,
               size_t dbInitSize = dbDefaultInitDatabaseSize,
               size_t dbExtensionQuantum = dbDefaultExtensionQuantum,
               size_t dbInitIndexSize = dbDefaultInitIndexSize,
               int nThreads = 1 
               // Do not specify the last parameter - it is only for checking
               // that application and GigaBASE library were built with the 
               // same compiler options (-DNO_PTHREADS is critical)
               // Mismached parameters should cause linker error
#ifdef NO_PTHREADS
               , bool usePthreads = false
#endif
               );
    /** 
     * Database detructor
     */
    virtual ~dbDatabase(); 

    const dbAccessType accessType;
    const size_t initSize;
    const size_t extensionQuantum;
    const size_t initIndexSize;

    static unsigned dbParallelScanThreshold; 

  protected:
    static size_t internalObjectSize[];

    dbThreadPool threadPool;

    dbThreadContext<dbDatabaseThreadContext> threadContext;

    byte*     baseAddr;         // base address of database file mapping
    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    mmapSize;
    
    size_t    committedIndexSize;
    size_t    currIndexSize;
    oid_t     updatedRecordId;

    unsigned  dbWaitLockTimeout;

    size_t    dbFileSizeLimit;

    bool      uncommittedChanges;

    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;

    long                      allocatedSize;
    
    time_t                    commitDelay;     
    time_t                    commitTimeout;
    time_t                    commitTimerStarted;
    
    dbMutex                   delayedCommitStartTimerMutex;
    dbMutex                   delayedCommitStopTimerMutex;
    dbLocalEvent              delayedCommitStartTimerEvent; 
    dbEvent                   delayedCommitStopTimerEvent; 
    dbLocalEvent              commitThreadSyncEvent;

    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;
#endif
    
    void delayedCommit();
    void backupScheduler();

    static void thread_proc delayedCommitProc(void* arg) { 
        ((dbDatabase*)arg)->delayedCommit();
    }

    static void thread_proc backupSchedulerProc(void* arg) { 
        ((dbDatabase*)arg)->backupScheduler();
    }

#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();

    /**
     * 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 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 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -