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

📄 database.h

📁 用于嵌入式环境的数据库
💻 H
📖 第 1 页 / 共 3 页
字号:
//-< 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"

/**
 * Default size of memory mapping object for the database (bytes)
 */
#ifdef DISKLESS_CONFIGURATION
// In diskless confiuration database can not be reallocated
const size_t dbDefaultInitDatabaseSize = 32*1024*1024;
#else
const 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,
    dbHArrayPageMarker,
    
    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
    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;
};

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  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;
};

/**
 * 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_CRASH
struct dbWatchDogContext { 
    dbThread    thread;
    dbWatchDog  watchDog;
    int         clientId;
    dbDatabase* db;
};
#endif

template<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 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 specified file
     * @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);
    
    /**
     * 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;
    }

    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
     * @param table table descriptor
     * @param ref   [out] pointer to the references where ID of created object will be stored
     * @param record pointer to the transient object to be inserted in the table
     */
    void insertRecord(dbTableDescriptor* table, dbAnyReference* ref, 
                      void const* record);

    /**
     * Check if database is opened
     */
    bool isOpen() const { return opened; }

    /**

⌨️ 快捷键说明

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