//-------------------------------------------------------------------------- // Database.h //-------------------------------------------------------------------------- #pragma once //-------------------------------------------------------------------------- // Depends //-------------------------------------------------------------------------- #include "utility.h" #include "query.h" #include "listen.h" //-------------------------------------------------------------------------- // Forward Decls //-------------------------------------------------------------------------- class CDatabaseQuery; //-------------------------------------------------------------------------- // DwordAlign //-------------------------------------------------------------------------- inline DWORD DwordAlign(DWORD cb) { DWORD dw = (cb % 4); return(0 == dw ? 0 : (4 - dw)); } //-------------------------------------------------------------------------- // String Constants //-------------------------------------------------------------------------- #define CCHMAX_DB_FILEPATH (MAX_PATH + MAX_PATH) //-------------------------------------------------------------------------- // DESCENDING //-------------------------------------------------------------------------- #define DESCENDING(_nCompare) ((_nCompare < 0) ? 1 : -1) typedef DWORD TICKCOUNT; //-------------------------------------------------------------------------- // Version and Signatures //-------------------------------------------------------------------------- #define BTREE_SIGNATURE 0xfe12adcf #define BTREE_VERSION 5 //-------------------------------------------------------------------------- // B-Tree Chain Sizes //-------------------------------------------------------------------------- #define BTREE_ORDER 50 #define BTREE_MIN_CAP 25 //-------------------------------------------------------------------------- // Upper Limit on Various Resources //-------------------------------------------------------------------------- #define CMAX_OPEN_STREAMS 512 #define CMAX_OPEN_ROWSETS 32 #define CMAX_RECIPIENTS 15 #define CMAX_CLIENTS 32 //-------------------------------------------------------------------------- // Block Allocate Page Sizes //-------------------------------------------------------------------------- #define CB_CHAIN_PAGE 15900 #define CB_STREAM_PAGE 63360 #define CB_VARIABLE_PAGE 49152 #define CB_STREAM_BLOCK 512 #define CC_MAX_BLOCK_TYPES 16 //-------------------------------------------------------------------------- // Variable Length Block Allocation Sizes //-------------------------------------------------------------------------- #define CB_ALIGN_LARGE 1024 #define CB_FREE_BUCKET 4 #define CC_FREE_BUCKETS 2048 #define CB_MIN_FREE_BUCKET 32 #define CB_MAX_FREE_BUCKET (CB_MIN_FREE_BUCKET + (CB_FREE_BUCKET * CC_FREE_BUCKETS)) //-------------------------------------------------------------------------- // Heap Block Cache //-------------------------------------------------------------------------- #define CB_HEAP_BUCKET 8 #define CC_HEAP_BUCKETS 1024 #define CB_MAX_HEAP_BUCKET (CB_HEAP_BUCKET * CC_HEAP_BUCKETS) //-------------------------------------------------------------------------- // Other Constants //-------------------------------------------------------------------------- #define MEMORY_GUARD_SIGNATURE 0xdeadbeef #define DELETE_ON_CLOSE TRUE //-------------------------------------------------------------------------- // File Mapping Constants //-------------------------------------------------------------------------- #define CB_MAPPED_VIEW 10485760 //-------------------------------------------------------------------------- // Forward Decls //-------------------------------------------------------------------------- class CProgress; class CDatabase; class CDatabaseStream; //-------------------------------------------------------------------------- // Locking Values //-------------------------------------------------------------------------- #define LOCK_VALUE_NONE 0 #define LOCK_VALUE_WRITER -1 //-------------------------------------------------------------------------- // STREAMINDEX //-------------------------------------------------------------------------- typedef WORD STREAMINDEX; typedef LPWORD LPSTREAMINDEX; #define INVALID_STREAMINDEX 0xffff //-------------------------------------------------------------------------- // ROWSETORDINAL //-------------------------------------------------------------------------- typedef BYTE ROWSETORDINAL; //-------------------------------------------------------------------------- // FILEADDRESS //-------------------------------------------------------------------------- typedef DWORD FILEADDRESS; typedef LPDWORD LPFILEADDRESS; //-------------------------------------------------------------------------- // NODEINDEX //-------------------------------------------------------------------------- typedef BYTE NODEINDEX; typedef BYTE *LPNODEINDEX; #define INVALID_NODEINDEX 0xff //-------------------------------------------------------------------------- // BLOCKTYPE //-------------------------------------------------------------------------- typedef enum tagBLOCKTYPE { BLOCK_RECORD, BLOCK_STRING, BLOCK_RESERVED1, BLOCK_TRANSACTION, BLOCK_CHAIN, BLOCK_STREAM, BLOCK_FREE, BLOCK_ENDOFPAGE, BLOCK_RESERVED2, BLOCK_RESERVED3, BLOCK_LAST } BLOCKTYPE; //-------------------------------------------------------------------------- // CHAINDELETETYPE //-------------------------------------------------------------------------- typedef enum tagCHAINDELETETYPE { CHAIN_DELETE_SHARE, CHAIN_DELETE_COALESCE } CHAINDELETETYPE; //-------------------------------------------------------------------------- // CHAINSHARETYPE //-------------------------------------------------------------------------- typedef enum tagCHAINSHARETYPE { CHAIN_SHARE_LEFT, CHAIN_SHARE_RIGHT } CHAINSHARETYPE; //-------------------------------------------------------------------------- // OPERATIONTYPE - Specifies how _UnlinkRecordFromTable from table works //-------------------------------------------------------------------------- typedef enum tagOPERATIONTYPE { OPERATION_DELETE, OPERATION_UPDATE, OPERATION_INSERT } OPERATIONTYPE; //-------------------------------------------------------------------------- // INVOKETYPE //-------------------------------------------------------------------------- typedef enum tagINVOKETYPE { INVOKE_RELEASEMAP = 100, INVOKE_CREATEMAP = 101, INVOKE_CLOSEFILE = 102, INVOKE_OPENFILE = 103, INVOKE_OPENMOVEDFILE = 104 } INVOKETYPE; //-------------------------------------------------------------------------- // FINDRESULT //-------------------------------------------------------------------------- typedef struct tagFINDRESULT { FILEADDRESS faChain; NODEINDEX iNode; BYTE fChanged; BYTE fFound; INT nCompare; } FINDRESULT, *LPFINDRESULT; //-------------------------------------------------------------------------- // ALLOCATEPAGE //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagALLOCATEPAGE { FILEADDRESS faPage; DWORD cbPage; DWORD cbUsed; } ALLOCATEPAGE, *LPALLOCATEPAGE; #pragma pack() //-------------------------------------------------------------------------- // TABLEHEADER //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagTABLEHEADER { DWORD dwSignature; // 4 CLSID clsidExtension; // 20 DWORD dwMinorVersion; // 24 DWORD dwMajorVersion; // 28 DWORD cbUserData; // 32 FILEADDRESS faCatalogOld; // 36 ALLOCATEPAGE AllocateRecord; // 48 ALLOCATEPAGE AllocateChain; // 60 ALLOCATEPAGE AllocateStream; // 72 FILEADDRESS faFreeStreamBlock; // 76 FILEADDRESS faFreeChainBlock; // 80 FILEADDRESS faFreeLargeBlock; // 84 DWORD cbAllocated; // 88 DWORD cbFreed; // 92 DWORD dwNextId; // 96 DWORD fCorrupt; // 100 DWORD fCorruptCheck; // 104 DWORD cActiveThreads; // 108 FILEADDRESS faTransactHead; // 112 FILEADDRESS faTransactTail; // 116 DWORD cTransacts; // 120 DWORD cBadCloses; // 124 FILEADDRESS faNextAllocate; // 128 DWORD cIndexes; // 132 FILEADDRESS rgfaFilter[CMAX_INDEXES]; // 164 DWORD rgbReserved5[8]; // 196 DWORD rgcRecords[CMAX_INDEXES]; // 228 FILEADDRESS rgfaIndex[CMAX_INDEXES]; // 260 INDEXORDINAL rgiIndex[CMAX_INDEXES]; // 292 BYTE rgbReserved4[116]; // 408 BYTE fReserved; // 409 DWORD rgbReserved6[8]; // 196 BYTE rgdwReserved2[192]; // 637 DWORD rgcbAllocated[CC_MAX_BLOCK_TYPES]; // 701 FILEADDRESS rgfaFreeBlock[CC_FREE_BUCKETS]; // 8893 TABLEINDEX rgIndexInfo[CMAX_INDEXES]; // 9293 WORD wTransactSize; // 9405 BYTE rgdwReserved3[110]; } TABLEHEADER, *LPTABLEHEADER; #pragma pack() //-------------------------------------------------------------------------- // BLOCKHEADER //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagBLOCKHEADER { FILEADDRESS faBlock; DWORD cbSize; } BLOCKHEADER, *LPBLOCKHEADER; #pragma pack() //-------------------------------------------------------------------------- // FREEBLOCK //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagFREEBLOCK : public BLOCKHEADER { DWORD cbBlock; DWORD dwReserved; FILEADDRESS faNext; } FREEBLOCK, *LPFREEBLOCK; #pragma pack() //-------------------------------------------------------------------------- // CHAINNODE //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagCHAINNODE { FILEADDRESS faRecord; FILEADDRESS faRightChain; DWORD cRightNodes; } CHAINNODE, *LPCHAINNODE; #pragma pack() //-------------------------------------------------------------------------- // CHAINBLOCK - 636 //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagCHAINBLOCK : public BLOCKHEADER { FILEADDRESS faLeftChain; FILEADDRESS faParent; BYTE iParent; BYTE cNodes; WORD wReserved; DWORD cLeftNodes; CHAINNODE rgNode[BTREE_ORDER + 1]; } CHAINBLOCK, *LPCHAINBLOCK; #pragma pack() //-------------------------------------------------------------------------- // STREAMBLOCK //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagSTREAMBLOCK : public BLOCKHEADER { DWORD cbData; FILEADDRESS faNext; } STREAMBLOCK, *LPSTREAMBLOCK; #pragma pack() //-------------------------------------------------------------------------- // RECORDBLOCK //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagRECORDBLOCK : public BLOCKHEADER { WORD wReserved; BYTE cTags; BYTE bVersion; } RECORDBLOCK, *LPRECORDBLOCK; #pragma pack() //-------------------------------------------------------------------------- // COLUMNTAG //-------------------------------------------------------------------------- #define TAG_DATA_MASK 0xFF800000 #pragma pack(4) typedef struct tagCOLUMNTAG { unsigned iColumn : 7; unsigned fData : 1; unsigned Offset : 24; } COLUMNTAG, *LPCOLUMNTAG; #pragma pack() //-------------------------------------------------------------------------- // RECORDMAP //-------------------------------------------------------------------------- typedef struct tagRECORDMAP { LPCTABLESCHEMA pSchema; BYTE cTags; LPCOLUMNTAG prgTag; DWORD cbTags; DWORD cbData; LPBYTE pbData; } RECORDMAP, *LPRECORDMAP; //-------------------------------------------------------------------------- // OPENSTREAM //-------------------------------------------------------------------------- typedef struct tagOPENSTREAM { BYTE fInUse; FILEADDRESS faStart; FILEADDRESS faMoved; DWORD cOpenCount; LONG lLock; BYTE fDeleteOnClose; } OPENSTREAM, *LPOPENSTREAM; //-------------------------------------------------------------------------- // NOTIFYRECIPIENT //-------------------------------------------------------------------------- typedef struct tagNOTIFYRECIPIENT { HWND hwndNotify; DWORD dwThreadId; DWORD_PTR dwCookie; BYTE fSuspended; BYTE fRelease; BYTE fOrdinalsOnly; DWORD_PTR pNotify; INDEXORDINAL iIndex; } NOTIFYRECIPIENT, *LPNOTIFYRECIPIENT; //-------------------------------------------------------------------------- // CLIENTENTRY //-------------------------------------------------------------------------- typedef struct tagCLIENTENTRY { HWND hwndListen; DWORD dwProcessId; DWORD dwThreadId; DWORD_PTR pDB; DWORD cRecipients; NOTIFYRECIPIENT rgRecipient[CMAX_RECIPIENTS]; } CLIENTENTRY, *LPCLIENTENTRY; //-------------------------------------------------------------------------- // TRANSACTIONBLOCK //-------------------------------------------------------------------------- #pragma pack(4) typedef struct tagTRANSACTIONBLOCK : public BLOCKHEADER { TRANSACTIONTYPE tyTransaction; WORD cRefs; INDEXORDINAL iIndex; ORDINALLIST Ordinals; FILEADDRESS faRecord1; FILEADDRESS faRecord2; FILEADDRESS faNext; FILEADDRESS faPrevious; FILEADDRESS faNextInBatch; } TRANSACTIONBLOCK, *LPTRANSACTIONBLOCK; #pragma pack() //-------------------------------------------------------------------------- // ROWSETINFO //-------------------------------------------------------------------------- typedef struct tagROWSETINFO { ROWSETORDINAL iRowset; INDEXORDINAL iIndex; ROWORDINAL iRow; } ROWSETINFO, *LPROWSETINFO; //-------------------------------------------------------------------------- // ROWSETTABLE //-------------------------------------------------------------------------- typedef struct tagROWSETTABLE { BYTE fInitialized; BYTE cFree; BYTE cUsed; ROWSETORDINAL rgiFree[CMAX_OPEN_ROWSETS]; ROWSETORDINAL rgiUsed[CMAX_OPEN_ROWSETS]; ROWSETINFO rgRowset[CMAX_OPEN_ROWSETS]; } ROWSETTABLE, *LPROWSETTABLE; //-------------------------------------------------------------------------- // SHAREDDATABASE //-------------------------------------------------------------------------- typedef struct tagSHAREDDATABASE { WCHAR szFile[CCHMAX_DB_FILEPATH]; LONG cWaitingForLock; BYTE fCompacting; DWORD dwVersion; DWORD dwQueryVersion; DWORD cNotifyLock; FILEADDRESS faTransactLockHead; FILEADDRESS faTransactLockTail; OPENSTREAM rgStream[CMAX_OPEN_STREAMS]; DWORD cClients; DWORD cNotifyOrdinalsOnly; DWORD cNotifyWithData; DWORD cNotify; DWORD rgcIndexNotify[CMAX_INDEXES]; CLIENTENTRY rgClient[CMAX_CLIENTS]; ROWSETTABLE Rowsets; IF_DEBUG(BYTE fRepairing;) } SHAREDDATABASE, *LPSHAREDDATABASE; //-------------------------------------------------------------------------- // INVOKEPACKAGE //-------------------------------------------------------------------------- typedef struct tagINVOKEPACKAGE { INVOKETYPE tyInvoke; DWORD_PTR pDB; } INVOKEPACKAGE, *LPINVOKEPACKAGE; //-------------------------------------------------------------------------- // MARKBLOCK //-------------------------------------------------------------------------- typedef struct tagMARKBLOCK { DWORD cbBlock; } MARKBLOCK, *LPMARKBLOCK; //-------------------------------------------------------------------------- // FILEVIEW //-------------------------------------------------------------------------- typedef struct tagFILEVIEW *LPFILEVIEW; typedef struct tagFILEVIEW { FILEADDRESS faView; LPBYTE pbView; DWORD cbView; LPFILEVIEW pNext; } FILEVIEW, *LPFILEVIEW; //-------------------------------------------------------------------------- // STORAGEINFO //-------------------------------------------------------------------------- typedef struct tagSTORAGEINFO { LPWSTR pszMap; HANDLE hFile; HANDLE hMap; HANDLE hShare; DWORD cbFile; #ifdef BACKGROUND_MONITOR TICKCOUNT tcMonitor; #endif DWORD cbMappedViews; DWORD cbMappedSpecial; DWORD cAllocated; DWORD cSpecial; LPFILEVIEW prgView; LPFILEVIEW pSpecial; } STORAGEINFO, *LPSTORAGEINFO; //-------------------------------------------------------------------------- // MEMORYTAG //-------------------------------------------------------------------------- typedef struct tagMEMORYTAG { DWORD dwSignature; DWORD cbSize; LPVOID pNext; } MEMORYTAG, *LPMEMORYTAG; //-------------------------------------------------------------------------- // CORRUPTREASON //-------------------------------------------------------------------------- typedef enum tagCORRUPTREASON { REASON_BLOCKSTARTOUTOFRANGE = 10000, REASON_UMATCHINGBLOCKADDRESS = 10002, REASON_BLOCKSIZEOUTOFRANGE = 10003, REASON_INVALIDFIRSTRECORD = 10035, REASON_INVALIDLASTRECORD = 10036, REASON_INVALIDRECORDMAP = 10037 } CORRUPTREASON; //-------------------------------------------------------------------------- // CDatabase //-------------------------------------------------------------------------- class CDatabase : public IDatabase { public: //---------------------------------------------------------------------- // Construction - Destruction //---------------------------------------------------------------------- CDatabase(void); ~CDatabase(void); //---------------------------------------------------------------------- // IUnknown Members //---------------------------------------------------------------------- STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); //---------------------------------------------------------------------- // IDatabase Members //---------------------------------------------------------------------- HRESULT Open(LPCWSTR pszFile, OPENDATABASEFLAGS dwFlags, LPCTABLESCHEMA pSchema, IDatabaseExtension *pExtension); //---------------------------------------------------------------------- // Locking Methods //---------------------------------------------------------------------- STDMETHODIMP Lock(LPHLOCK phLock); STDMETHODIMP Unlock(LPHLOCK phLock); //---------------------------------------------------------------------- // Data Manipulation Methods //---------------------------------------------------------------------- STDMETHODIMP InsertRecord(LPVOID pBinding); STDMETHODIMP UpdateRecord(LPVOID pBinding); STDMETHODIMP DeleteRecord(LPVOID pBinding); STDMETHODIMP FindRecord(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPROWORDINAL piRow); STDMETHODIMP GetRowOrdinal(INDEXORDINAL iIndex, LPVOID pBinding, LPROWORDINAL piRow); STDMETHODIMP FreeRecord(LPVOID pBinding); STDMETHODIMP GetUserData(LPVOID pvUserData, ULONG cbUserData); STDMETHODIMP SetUserData(LPVOID pvUserData, ULONG cbUserData); STDMETHODIMP GetRecordCount(INDEXORDINAL iIndex, LPDWORD pcRecords); //---------------------------------------------------------------------- // Indexing Methods //---------------------------------------------------------------------- STDMETHODIMP GetIndexInfo(INDEXORDINAL iIndex, LPSTR *ppszFilter, LPTABLEINDEX pIndex); STDMETHODIMP ModifyIndex(INDEXORDINAL iIndex, LPCSTR pszFilter, LPCTABLEINDEX pIndex); STDMETHODIMP DeleteIndex(INDEXORDINAL iIndex); //---------------------------------------------------------------------- // Rowset Methods //---------------------------------------------------------------------- STDMETHODIMP CreateRowset(INDEXORDINAL iIndex, CREATEROWSETFLAGS dwFlags, LPHROWSET phRowset); STDMETHODIMP SeekRowset(HROWSET hRowset, SEEKROWSETTYPE tySeek, LONG cRows, LPROWORDINAL piRowNew); STDMETHODIMP QueryRowset(HROWSET hRowset, LONG cWanted, LPVOID *prgpBinding, LPDWORD pcObtained); STDMETHODIMP CloseRowset(LPHROWSET phRowset); //---------------------------------------------------------------------- // Streaming Methods //---------------------------------------------------------------------- STDMETHODIMP CreateStream(LPFILEADDRESS pfaStart); STDMETHODIMP DeleteStream(FILEADDRESS faStart); STDMETHODIMP CopyStream(IDatabase *pDst, FILEADDRESS faStream, LPFILEADDRESS pfaNew); STDMETHODIMP OpenStream(ACCESSTYPE tyAccess, FILEADDRESS faStart, IStream **ppStream); STDMETHODIMP ChangeStreamLock(IStream *pStream, ACCESSTYPE tyAccessNew); //---------------------------------------------------------------------- // Notification Methods //---------------------------------------------------------------------- STDMETHODIMP RegisterNotify(INDEXORDINAL iIndex, REGISTERNOTIFYFLAGS dwFlags, DWORD_PTR dwCookie, IDatabaseNotify *pNotify); STDMETHODIMP DispatchNotify(IDatabaseNotify *pNotify); STDMETHODIMP SuspendNotify(IDatabaseNotify *pNotify); STDMETHODIMP ResumeNotify(IDatabaseNotify *pNotify); STDMETHODIMP UnregisterNotify(IDatabaseNotify *pNotify); STDMETHODIMP LockNotify(LOCKNOTIFYFLAGS dwFlags, LPHLOCK phLock); STDMETHODIMP UnlockNotify(LPHLOCK phLock); STDMETHODIMP GetTransaction(LPHTRANSACTION phTransaction, LPTRANSACTIONTYPE ptyTransaction, LPVOID pRecord1, LPVOID pRecord2, LPINDEXORDINAL piIndex, LPORDINALLIST pOrdinals); //---------------------------------------------------------------------- // Maintenence Methods //---------------------------------------------------------------------- STDMETHODIMP MoveFile(LPCWSTR pszFilePath); STDMETHODIMP SetSize(DWORD cbSize); STDMETHODIMP GetFile(LPWSTR *ppszFile); STDMETHODIMP GetSize(LPDWORD pcbFile, LPDWORD pcbAllocated, LPDWORD pcbFreed, LPDWORD pcbStreams); STDMETHODIMP Repair(void) { return _CheckForCorruption(); } //---------------------------------------------------------------------- // Fast-Heap Methods //---------------------------------------------------------------------- STDMETHODIMP HeapFree(LPVOID pvBuffer); STDMETHODIMP HeapAllocate(DWORD dwFlags, DWORD cbSize, LPVOID *ppBuffer) { *ppBuffer = PHeapAllocate(dwFlags, cbSize); return(*ppBuffer ? S_OK : E_OUTOFMEMORY); } //---------------------------------------------------------------------- // General Utility Methods //---------------------------------------------------------------------- STDMETHODIMP Compact(IDatabaseProgress *pProgress, COMPACTFLAGS dwFlags); STDMETHODIMP GenerateId(LPDWORD pdwId); STDMETHODIMP GetClientCount(LPDWORD pcClients); //---------------------------------------------------------------------- // CDatabase Members //---------------------------------------------------------------------- HRESULT StreamCompareDatabase(CDatabaseStream *pStream, IDatabase *pDatabase); HRESULT GetStreamAddress(CDatabaseStream *pStream, LPFILEADDRESS pfaStream); HRESULT StreamRead(CDatabaseStream *pStream, LPVOID pvData, ULONG cbWanted, ULONG *pcbRead); HRESULT StreamWrite(CDatabaseStream *pStream, const void *pvData, ULONG cb, ULONG *pcbWrote); HRESULT StreamSeek(CDatabaseStream *pStream, LARGE_INTEGER liMove, DWORD dwOrigin, ULARGE_INTEGER *pulNew); HRESULT StreamRelease(CDatabaseStream *pStream); HRESULT StreamGetAddress(CDatabaseStream *pStream, LPFILEADDRESS pfaStart); HRESULT DoInProcessInvoke(INVOKETYPE tyInvoke); #ifdef BACKGROUND_MONITOR HRESULT DoBackgroundMonitor(void); #endif HRESULT BindRecord(LPRECORDMAP pMap, LPVOID pBinding); LPVOID PHeapAllocate(DWORD dwFlags, DWORD cbSize); //---------------------------------------------------------------------- // AllocateBinding //---------------------------------------------------------------------- HRESULT AllocateBinding(LPVOID *ppBinding) { *ppBinding = PHeapAllocate(HEAP_ZERO_MEMORY, m_pSchema->cbBinding); return(*ppBinding ? S_OK : E_OUTOFMEMORY); } private: //---------------------------------------------------------------------- // General Btree Methods //---------------------------------------------------------------------- HRESULT _IsLeafChain(LPCHAINBLOCK pChain); HRESULT _AdjustParentNodeCount(INDEXORDINAL iIndex, FILEADDRESS faChain, LONG lCount); HRESULT _ValidateFileVersions(OPENDATABASEFLAGS dwFlags); HRESULT _ResetTableHeader(void); HRESULT _RemoveClientFromArray(DWORD dwProcessId, DWORD_PTR pDB); HRESULT _BuildQueryTable(void); HRESULT _StreamSychronize(CDatabaseStream *pStream); HRESULT _InitializeExtension(OPENDATABASEFLAGS dwFlags, IDatabaseExtension *pExtension); HRESULT _GetRecordMap(BOOL fGoCorrupt, LPRECORDBLOCK pBlock, LPRECORDMAP pMap); //---------------------------------------------------------------------- // File Mapping / View Utilities //---------------------------------------------------------------------- HRESULT _InitializeFileViews(void); HRESULT _CloseFileViews(BOOL fFlush); HRESULT _AllocateSpecialView(FILEADDRESS faView, DWORD cbView, LPFILEVIEW *ppSpecial); //---------------------------------------------------------------------- // Btree Search / Virtual Scrolling //---------------------------------------------------------------------- HRESULT _GetChainByIndex(INDEXORDINAL iIndex, ROWORDINAL iRow, LPFILEADDRESS pfaChain, LPNODEINDEX piNode); HRESULT _CompareBinding(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, FILEADDRESS faRecord, INT *pnCompare); HRESULT _IsVisible(HQUERY hQuery, LPVOID pBinding); HRESULT _PartialIndexCompare(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPCHAINBLOCK *ppChain, LPNODEINDEX piNode, LPROWORDINAL piRow); HRESULT _FindRecord(INDEXORDINAL iIndex, DWORD cColumns, LPVOID pBinding, LPFILEADDRESS pfaChain, LPNODEINDEX piNode, LPROWORDINAL piRow=NULL, INT *pnCompare=NULL); //---------------------------------------------------------------------- // Btree Deletion Methods //---------------------------------------------------------------------- HRESULT _CollapseChain(LPCHAINBLOCK pChain, NODEINDEX iDelete); HRESULT _ExpandChain(LPCHAINBLOCK pChain, NODEINDEX iNode); HRESULT _IndexDeleteRecord(INDEXORDINAL iIndex, FILEADDRESS faDelete, NODEINDEX iDelete); HRESULT _GetRightSibling(FILEADDRESS faCurrent, LPCHAINBLOCK *ppSibling); HRESULT _GetLeftSibling(FILEADDRESS faCurrent, LPCHAINBLOCK *ppSibling); HRESULT _GetInOrderSuccessor(FILEADDRESS faStart, NODEINDEX iDelete, LPCHAINBLOCK *ppSuccessor); HRESULT _DecideHowToDelete(LPFILEADDRESS pfaShare, FILEADDRESS faDelete, CHAINDELETETYPE *ptyDelete, CHAINSHARETYPE *ptyShare); HRESULT _ChainDeleteShare(INDEXORDINAL iIndex, FILEADDRESS faDelete, FILEADDRESS faShare, CHAINSHARETYPE tyShare); HRESULT _ChainDeleteCoalesce(INDEXORDINAL iIndex, FILEADDRESS faDelete, FILEADDRESS faShare, CHAINSHARETYPE tyShare); //---------------------------------------------------------------------- // Btree Insertion Methods //---------------------------------------------------------------------- HRESULT _IndexInsertRecord(INDEXORDINAL iIndex, FILEADDRESS faChain, FILEADDRESS faRecord, LPNODEINDEX piNode, INT nCompare); HRESULT _ChainInsert(INDEXORDINAL iIndex, LPCHAINBLOCK pChain, LPCHAINNODE pNode, LPNODEINDEX piNodeIndex); HRESULT _SplitChainInsert(INDEXORDINAL iIndex, FILEADDRESS faLeaf); //---------------------------------------------------------------------- // Record Persistence Methods //---------------------------------------------------------------------- HRESULT _GetRecordSize(LPVOID pBinding, LPRECORDMAP pMap); HRESULT _SaveRecord(LPRECORDBLOCK pBlock, LPRECORDMAP pMap, LPVOID pBinding); HRESULT _ReadRecord(FILEADDRESS faRecord, LPVOID pBinding, BOOL fInternal=FALSE); HRESULT _LinkRecordIntoTable(LPRECORDMAP pMap, LPVOID pBinding, BYTE bVersion, LPFILEADDRESS pfaRecord); //---------------------------------------------------------------------- // Notification / Invoke Methods //---------------------------------------------------------------------- HRESULT _DispatchInvoke(INVOKETYPE tyInvoke); HRESULT _DispatchNotification(HTRANSACTION hTransaction); HRESULT _LogTransaction(TRANSACTIONTYPE tyTransaction, INDEXORDINAL iIndex, LPORDINALLIST pOrdinals, FILEADDRESS faRecord1, FILEADDRESS faRecord2); HRESULT _CloseNotificationWindow(LPNOTIFYRECIPIENT pRecipient); HRESULT _FindClient(DWORD dwProcessId, DWORD_PTR dwDB, LPDWORD piClient, LPCLIENTENTRY *ppClient); HRESULT _FindNotifyRecipient(DWORD iClient, IDatabaseNotify *pNotify, LPDWORD piRecipient, LPNOTIFYRECIPIENT *ppRecipient); HRESULT _DispatchPendingNotifications(void); HRESULT _AdjustNotifyCounts(LPNOTIFYRECIPIENT pRecipient, LONG lChange); //---------------------------------------------------------------------- // Rowset Support Methods //---------------------------------------------------------------------- HRESULT _AdjustOpenRowsets(INDEXORDINAL iIndex, ROWORDINAL iRow, OPERATIONTYPE tyOperation); //---------------------------------------------------------------------- // Alloctation Methods //---------------------------------------------------------------------- HRESULT _MarkBlock(BLOCKTYPE tyBlock, FILEADDRESS faBlock, DWORD cbBlock, LPVOID *ppvBlock); HRESULT _ReuseFixedFreeBlock(LPFILEADDRESS pfaFreeHead, BLOCKTYPE tyBlock, DWORD cbBlock, LPVOID *ppvBlock); HRESULT _FreeRecordStorage(OPERATIONTYPE tyOperation, FILEADDRESS faRecord); HRESULT _FreeStreamStorage(FILEADDRESS faStart); HRESULT _SetStorageSize(DWORD cbSize); HRESULT _AllocateBlock(BLOCKTYPE tyBlock, DWORD cbExtra, LPVOID *ppBlock); HRESULT _AllocateFromPage(BLOCKTYPE tyBlock, LPALLOCATEPAGE pPage, DWORD cbPage, DWORD cbBlock, LPVOID *ppvBlock); HRESULT _FreeBlock(BLOCKTYPE tyBlock, FILEADDRESS faBlock); HRESULT _AllocatePage(DWORD cbPage, LPFILEADDRESS pfaAddress); HRESULT _FreeIndex(FILEADDRESS faChain); HRESULT _CopyRecord(FILEADDRESS faRecord, LPFILEADDRESS pfaCopy); HRESULT _FreeTransactBlock(LPTRANSACTIONBLOCK pTransact); HRESULT _CleanupTransactList(void); //---------------------------------------------------------------------- // Compaction Helpers //---------------------------------------------------------------------- HRESULT _CompactMoveRecordStreams(CDatabase *pDstDB, LPVOID pBinding); HRESULT _CompactMoveOpenDeletedStreams(CDatabase *pDstDB); HRESULT _CompactTransferFilters(CDatabase *pDstDB); HRESULT _CompactInsertRecord(LPVOID pBinding); //---------------------------------------------------------------------- // Index Management //---------------------------------------------------------------------- HRESULT _ValidateIndex(INDEXORDINAL iIndex, FILEADDRESS faChain, ULONG cLeftNodes, ULONG *pcRecords); HRESULT _RebuildIndex(INDEXORDINAL iIndex); HRESULT _RecursiveRebuildIndex(INDEXORDINAL iIndex, FILEADDRESS faCurrent, LPVOID pBinding, LPDWORD pcRecords); //---------------------------------------------------------------------- // Corruption Validation and Repair Methods //---------------------------------------------------------------------- HRESULT _HandleOpenMovedFile(void); HRESULT _SetCorrupt(BOOL fGoCorrupt, INT nLine, CORRUPTREASON tyReason, BLOCKTYPE tyBlock, FILEADDRESS faExpected, FILEADDRESS faActual, DWORD cbBlock); HRESULT _CheckForCorruption(void); HRESULT _GetBlock(BLOCKTYPE tyExpected, FILEADDRESS faBlock, LPVOID *ppvBlock, LPMARKBLOCK pMark=NULL, BOOL fGoCorrupt=TRUE); HRESULT _ValidateAndRepairRecord(LPRECORDMAP pMap); HRESULT _ValidateStream(FILEADDRESS faStart); //---------------------------------------------------------------------- // Private Debug Methods //---------------------------------------------------------------------- IF_DEBUG(HRESULT _DebugValidateRecordFormat(void)); IF_DEBUG(HRESULT _DebugValidateUnrefedRecord(FILEADDRESS farecord)); IF_DEBUG(HRESULT _DebugValidateIndexUnrefedRecord(FILEADDRESS faChain, FILEADDRESS faRecord)); private: //---------------------------------------------------------------------- // Prototypes //---------------------------------------------------------------------- LONG m_cRef; LONG m_cExtRefs; HANDLE m_hMutex; #ifdef BACKGROUND_MONITOR HMONITORDB m_hMonitor; #endif DWORD m_dwProcessId; BOOL m_fDirty; LPCTABLESCHEMA m_pSchema; LPSTORAGEINFO m_pStorage; LPTABLEHEADER m_pHeader; LPSHAREDDATABASE m_pShare; HANDLE m_hHeap; BYTE m_fDeconstruct; BYTE m_fInMoveFile; BYTE m_fExclusive; BYTE m_fCompactYield; DWORD m_dwQueryVersion; HQUERY m_rghFilter[CMAX_INDEXES]; IDatabaseExtension *m_pExtension; IUnknown *m_pUnkRelease; LPBYTE m_rgpRecycle[CC_HEAP_BUCKETS]; CRITICAL_SECTION m_csHeap; IF_DEBUG(DWORD m_cbHeapAlloc); IF_DEBUG(DWORD m_cbHeapFree); //---------------------------------------------------------------------- // Friend //---------------------------------------------------------------------- friend CDatabaseQuery; }; //-------------------------------------------------------------------------- // CDatabaseQuery //-------------------------------------------------------------------------- class CDatabaseQuery : public IDatabaseQuery { public: //---------------------------------------------------------------------- // Construction //---------------------------------------------------------------------- CDatabaseQuery(void) { TraceCall("CDatabaseQuery::CDatabaseQuery"); m_cRef = 1; m_hQuery = NULL; m_pDatabase = NULL; } //---------------------------------------------------------------------- // De-Construction //---------------------------------------------------------------------- ~CDatabaseQuery(void) { TraceCall("CDatabaseQuery::~CDatabaseQuery"); CloseQuery(&m_hQuery, m_pDatabase); SafeRelease(m_pDatabase); } //---------------------------------------------------------------------- // IUnknown Members //---------------------------------------------------------------------- STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) { TraceCall("CDatabaseQuery::QueryInterface"); *ppv = NULL; if (IID_IUnknown == riid) *ppv = (IUnknown *)this; else if (IID_IDatabaseQuery == riid) *ppv = (IDatabaseQuery *)this; else return TraceResult(E_NOINTERFACE); ((IUnknown *)*ppv)->AddRef(); return S_OK; } //---------------------------------------------------------------------- // IDatabaseQuery::AddRef //---------------------------------------------------------------------- STDMETHODIMP_(ULONG) AddRef(void) { TraceCall("CDatabaseQuery::AddRef"); return InterlockedIncrement(&m_cRef); } //---------------------------------------------------------------------- // IDatabaseQuery::Release //---------------------------------------------------------------------- STDMETHODIMP_(ULONG) Release(void) { TraceCall("CDatabaseQuery::Release"); LONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) delete this; return (ULONG)cRef; } //---------------------------------------------------------------------- // CDatabaseQuery::Initialize //---------------------------------------------------------------------- HRESULT Initialize(IDatabase *pDatabase, LPCSTR pszQuery) { TraceCall("CDatabaseQuery::Initialize"); pDatabase->QueryInterface(IID_CDatabase, (LPVOID *)&m_pDatabase); return(ParseQuery(pszQuery, m_pDatabase->m_pSchema, &m_hQuery, m_pDatabase)); } //---------------------------------------------------------------------- // CDatabaseQuery::Evaluate //---------------------------------------------------------------------- STDMETHODIMP Evaluate(LPVOID pBinding) { TraceCall("CDatabaseQuery::Evaluate"); return(EvaluateQuery(m_hQuery, pBinding, m_pDatabase->m_pSchema, m_pDatabase, m_pDatabase->m_pExtension)); } private: //---------------------------------------------------------------------- // Private Data //---------------------------------------------------------------------- LONG m_cRef; HQUERY m_hQuery; CDatabase *m_pDatabase; }; //-------------------------------------------------------------------------- // PTagFromOrdinal //-------------------------------------------------------------------------- inline LPCOLUMNTAG PTagFromOrdinal(LPRECORDMAP pMap, COLUMNORDINAL iColumn);