/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: storbase.hxx,v $ * * $Revision: 1.9 $ * * last change: $Author: hr $ $Date: 2006-06-20 00:33:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ #ifndef _STORE_STORBASE_HXX_ #define _STORE_STORBASE_HXX_ "$Revision: 1.9 $" #ifndef _SAL_TYPES_H_ #include #endif #ifndef _RTL_ALLOC_H_ #include #endif #ifndef _RTL_STRING_H_ #include #endif #ifndef _RTL_REF_HXX_ #include #endif #ifndef _OSL_ENDIAN_H_ #include #endif #ifndef _OSL_MUTEX_HXX_ #include #endif #ifndef _STORE_TYPES_H_ #include #endif #ifndef _STORE_OBJECT_HXX_ #include #endif #ifndef _STORE_LOCKBYTE_HXX_ #include #endif #ifndef INCLUDED_CSTDDEF #include #define INCLUDED_CSTDDEF #endif #ifndef INCLUDED_CSTRING #include #define INCLUDED_CSTRING #endif /*======================================================================== * * store common internals. * *======================================================================*/ /* MSVC 6.0 still has std functions in global namespace */ #if defined(_MSC_VER) && (_MSC_VER <= 1310) #define __STORE_CSTD #else #define __STORE_CSTD std #endif /* _MSC_VER */ #ifndef __STORE_DELETEZ #define __STORE_DELETEZ(p) (delete p, p = 0) #endif /* * __store_memcpy. */ inline void __store_memcpy (void * dst, const void * src, sal_Size n) { __STORE_CSTD::memcpy (dst, src, n); } /* * __store_memmove. */ inline void __store_memmove (void * dst, const void * src, sal_Size n) { __STORE_CSTD::memmove (dst, src, n); } /* * __store_memset. */ inline void __store_memset (void * dst, int val, sal_Size n) { __STORE_CSTD::memset (dst, val, n); } namespace store { /*======================================================================== * * OStorePageGuard. * *======================================================================*/ struct OStorePageGuard { /** Representation. */ sal_uInt32 m_nMagic; sal_uInt32 m_nCRC32; /** Construction. */ OStorePageGuard (sal_uInt32 nMagic = 0, sal_uInt32 nCRC32 = 0) : m_nMagic (nMagic), m_nCRC32 (nCRC32) {} OStorePageGuard (const OStorePageGuard& rOther) : m_nMagic (rOther.m_nMagic), m_nCRC32 (rOther.m_nCRC32) {} OStorePageGuard& operator= (const OStorePageGuard& rOther) { m_nMagic = rOther.m_nMagic; m_nCRC32 = rOther.m_nCRC32; return *this; } /** Comparison. */ sal_Bool operator== (const OStorePageGuard& rOther) const { return ((m_nMagic == rOther.m_nMagic) && (m_nCRC32 == rOther.m_nCRC32) ); } /** swap (internal and external representation). */ void swap (void) { #ifdef OSL_BIGENDIAN m_nMagic = OSL_SWAPDWORD(m_nMagic); m_nCRC32 = OSL_SWAPDWORD(m_nCRC32); #endif /* OSL_BIGENDIAN */ } /** CRC polynomial 0xEDB88320. */ static const sal_uInt32 m_pTable[256]; static sal_uInt32 updcrc32 (sal_uInt32 crc, sal_uInt8 octet) { return m_pTable[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8); } static sal_uInt32 crc32 ( sal_uInt32 nCRC32, const void *pData, sal_Size nSize); }; /*======================================================================== * * OStorePageDescriptor. * *======================================================================*/ #define STORE_PAGE_NULL ((sal_uInt32)(~0)) struct OStorePageDescriptor { /** Representation. */ sal_uInt32 m_nAddr; sal_uInt16 m_nSize; sal_uInt16 m_nUsed; /** Construction. */ OStorePageDescriptor ( sal_uInt32 nAddr = STORE_PAGE_NULL, sal_uInt16 nSize = 0, sal_uInt16 nUsed = 0) : m_nAddr (nAddr), m_nSize (nSize), m_nUsed (nUsed) {} OStorePageDescriptor (const OStorePageDescriptor& rOther) : m_nAddr (rOther.m_nAddr), m_nSize (rOther.m_nSize), m_nUsed (rOther.m_nUsed) {} OStorePageDescriptor& operator= (const OStorePageDescriptor& rOther) { m_nAddr = rOther.m_nAddr; m_nSize = rOther.m_nSize; m_nUsed = rOther.m_nUsed; return *this; } /** Comparison. */ sal_Bool operator== (const OStorePageDescriptor& rOther) const { return ((m_nAddr == rOther.m_nAddr) && (m_nSize == rOther.m_nSize) ); } sal_Bool operator<= (const OStorePageDescriptor& rOther) const { return ((m_nAddr == rOther.m_nAddr) && (m_nSize <= rOther.m_nSize) ); } sal_Bool operator< (const OStorePageDescriptor& rOther) const { if (m_nAddr == rOther.m_nAddr) return (m_nSize < rOther.m_nSize); else return (m_nAddr < rOther.m_nAddr); } /** swap (internal and external representation). */ void swap (void) { #ifdef OSL_BIGENDIAN m_nAddr = OSL_SWAPDWORD(m_nAddr); m_nSize = OSL_SWAPWORD(m_nSize); m_nUsed = OSL_SWAPWORD(m_nUsed); #endif /* OSL_BIGENDIAN */ } }; /*======================================================================== * * OStorePageKey. * *======================================================================*/ struct OStorePageKey { /** Representation. */ sal_uInt32 m_nLow; sal_uInt32 m_nHigh; /** Construction. */ OStorePageKey (sal_uInt32 nLow = 0, sal_uInt32 nHigh = 0) : m_nLow (nLow), m_nHigh (nHigh) {} OStorePageKey (const OStorePageKey& rOther) : m_nLow (rOther.m_nLow), m_nHigh (rOther.m_nHigh) {} OStorePageKey& operator= (const OStorePageKey& rOther) { m_nLow = rOther.m_nLow; m_nHigh = rOther.m_nHigh; return *this; } /** Comparison. */ sal_Bool operator== (const OStorePageKey& rOther) const { return ((m_nLow == rOther.m_nLow ) && (m_nHigh == rOther.m_nHigh) ); } sal_Bool operator< (const OStorePageKey& rOther) const { if (m_nHigh == rOther.m_nHigh) return (m_nLow < rOther.m_nLow); else return (m_nHigh < rOther.m_nHigh); } /** swap (internal and external representation). */ void swap (void) { #ifdef OSL_BIGENDIAN m_nLow = OSL_SWAPDWORD(m_nLow); m_nHigh = OSL_SWAPDWORD(m_nHigh); #endif /* OSL_BIGENDIAN */ } }; /*======================================================================== * * OStorePageLink. * *======================================================================*/ struct OStorePageLink { /** Representation. */ sal_uInt32 m_nAddr; /** Construction. */ OStorePageLink (sal_uInt32 nAddr = STORE_PAGE_NULL) : m_nAddr (nAddr) {} OStorePageLink (const OStorePageLink& rOther) : m_nAddr (rOther.m_nAddr) {} OStorePageLink& operator= (const OStorePageLink& rOther) { m_nAddr = rOther.m_nAddr; return *this; } /** Comparison. */ sal_Bool operator== (const OStorePageLink& rOther) const { return (m_nAddr == rOther.m_nAddr); } sal_Bool operator< (const OStorePageLink& rOther) const { return (m_nAddr < rOther.m_nAddr); } /** Operation. */ void link (OStorePageLink& rPred) { OStorePageLink tmp (rPred); rPred = *this; *this = tmp; } void unlink (OStorePageLink& rPred) { rPred = *this; *this = OStorePageLink(); } /** swap (internal and external representation). */ void swap (void) { #ifdef OSL_BIGENDIAN m_nAddr = OSL_SWAPDWORD(m_nAddr); #endif /* OSL_BIGENDIAN */ } }; /*======================================================================== * * OStorePageNameBlock. * *======================================================================*/ struct OStorePageNameBlock { typedef OStorePageGuard G; typedef OStorePageKey K; /** Representation. */ G m_aGuard; K m_aKey; sal_uInt32 m_nAttrib; sal_Char m_pData[STORE_MAXIMUM_NAMESIZE]; /** size. */ static sal_uInt16 size (void) { return sal_uInt16(sizeof(G) + sizeof(K) + sizeof(sal_uInt32) + sizeof(sal_Char[STORE_MAXIMUM_NAMESIZE])); } /** initialize. */ void initialize (void) { m_aGuard = G(); m_aKey = K(); m_nAttrib = 0; __store_memset (m_pData, 0, sizeof(m_pData)); } /** Construction. */ OStorePageNameBlock (void) : m_nAttrib (0) { __store_memset (m_pData, 0, sizeof(m_pData)); } /** Comparison. */ sal_Bool operator== (const OStorePageNameBlock& rOther) const { return (m_aGuard == rOther.m_aGuard); } /** swap (internal and external representation). */ void swap (void) { #ifdef OSL_BIGENDIAN m_aGuard.swap(); m_aKey.swap(); m_nAttrib = OSL_SWAPDWORD(m_nAttrib); #endif /* OSL_BIGENDIAN */ } /** guard (external representation). */ void guard (void) { sal_uInt32 nCRC32 = 0; nCRC32 = G::crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = G::crc32 (nCRC32, &m_aKey, size() - sizeof(G)); #ifdef OSL_BIGENDIAN nCRC32 = OSL_SWAPDWORD(nCRC32); #endif /* OSL_BIGENDIAN */ m_aGuard.m_nCRC32 = nCRC32; } /** verify (external representation). */ storeError verify (void) { sal_uInt32 nCRC32 = 0; nCRC32 = G::crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = G::crc32 (nCRC32, &m_aKey, size() - sizeof(G)); #ifdef OSL_BIGENDIAN nCRC32 = OSL_SWAPDWORD(nCRC32); #endif /* OSL_BIGENDIAN */ if (m_aGuard.m_nCRC32 != nCRC32) return store_E_InvalidChecksum; else return store_E_None; } /** namei. */ static storeError namei ( const rtl_String *pPath, const rtl_String *pName, K &rKey) { // Check parameter. if (!(pPath && pName)) return store_E_InvalidParameter; // Check name length. if (!(pName->length < STORE_MAXIMUM_NAMESIZE)) return store_E_NameTooLong; // Transform pathname into key. rKey.m_nLow = G::crc32 (0, pName->buffer, pName->length); rKey.m_nHigh = G::crc32 (0, pPath->buffer, pPath->length); // Done. return store_E_None; } }; /*======================================================================== * * OStorePageData. * *======================================================================*/ struct OStorePageData { typedef OStorePageGuard G; typedef OStorePageDescriptor D; typedef OStorePageLink L; /** Representation. */ G m_aGuard; D m_aDescr; L m_aMarked; L m_aUnused; /** size. */ static sal_uInt16 size (void) { return sal_uInt16(sizeof(G) + sizeof(D) + 2 * sizeof(L)); } /** location. */ sal_uInt32 location (void) const { return m_aDescr.m_nAddr; } void location (sal_uInt32 nAddr) { m_aDescr.m_nAddr = nAddr; } /** Allocation. */ static void* operator new (size_t n) { return rtl_allocateMemory (n); } static void* operator new (size_t, sal_uInt16 nPageSize) { return rtl_allocateMemory (nPageSize); } static void operator delete (void *p) { rtl_freeMemory (p); } static void operator delete (void *p, sal_uInt16) { rtl_freeMemory (p); } /** Construction. */ OStorePageData (sal_uInt16 nPageSize) { m_aDescr.m_nSize = nPageSize; m_aDescr.m_nUsed = size(); } OStorePageData& operator= (const OStorePageData& rOther) { m_aGuard = rOther.m_aGuard; m_aDescr = rOther.m_aDescr; m_aMarked = rOther.m_aMarked; m_aUnused = rOther.m_aUnused; return *this; } /** Comparison. */ sal_Bool operator== (const OStorePageData& rOther) const { return ((m_aGuard == rOther.m_aGuard ) && (m_aDescr == rOther.m_aDescr ) && (m_aMarked == rOther.m_aMarked) && (m_aUnused == rOther.m_aUnused) ); } /** swap (internal and external representation). */ void swap () { #ifdef OSL_BIGENDIAN m_aGuard.swap(); m_aDescr.swap(); m_aMarked.swap(); m_aUnused.swap(); #endif /* OSL_BIGENDIAN */ } /** guard (external representation). */ void guard () { sal_uInt32 nCRC32 = 0; nCRC32 = G::crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = G::crc32 (nCRC32, &m_aDescr, size() - sizeof(G)); #ifdef OSL_BIGENDIAN nCRC32 = OSL_SWAPDWORD(nCRC32); #endif /* OSL_BIGENDIAN */ m_aGuard.m_nCRC32 = nCRC32; } /** verify (external representation). */ storeError verify () { sal_uInt32 nCRC32 = 0; nCRC32 = G::crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32)); nCRC32 = G::crc32 (nCRC32, &m_aDescr, size() - sizeof(G)); #ifdef OSL_BIGENDIAN nCRC32 = OSL_SWAPDWORD(nCRC32); #endif /* OSL_BIGENDIAN */ if (m_aGuard.m_nCRC32 != nCRC32) return store_E_InvalidChecksum; else return store_E_None; } }; /*======================================================================== * * OStorePageObject. * *======================================================================*/ class OStorePageObject { typedef OStorePageData page; typedef OStorePageDescriptor D; public: /** Allocation. */ static void * operator new (std::size_t n) SAL_THROW(()) { return rtl_allocateMemory (sal_uInt32(n)); } static void operator delete (void * p, std::size_t) SAL_THROW(()) { rtl_freeMemory (p); } /** Construction. */ inline OStorePageObject (page& rPage); /** Destruction. */ virtual ~OStorePageObject (void); /** External representation. */ virtual void swap (const D& rDescr); virtual void guard (const D& rDescr); virtual storeError verify (const D& rDescr); /** Data. */ inline OStorePageData& getData (void); /** State. */ inline sal_Bool dirty (void) const; inline void clean (void); inline void touch (void); /** Location. */ inline sal_uInt32 location (void) const; inline void location (sal_uInt32 nAddr); private: /** Representation. */ page &m_rPage; sal_Bool m_bDirty; }; inline OStorePageObject::OStorePageObject (page& rPage) : m_rPage (rPage), m_bDirty (sal_False) { } inline OStorePageData& OStorePageObject::getData (void) { return m_rPage; } inline sal_Bool OStorePageObject::dirty (void) const { return m_bDirty; } inline void OStorePageObject::clean (void) { m_bDirty = sal_False; } inline void OStorePageObject::touch (void) { m_bDirty = sal_True; } inline sal_uInt32 OStorePageObject::location (void) const { return m_rPage.location(); } inline void OStorePageObject::location (sal_uInt32 nAddr) { m_rPage.location (nAddr); touch(); } #define STORE_METHOD_ENTER(pMutex) \ if ((pMutex)) (pMutex)->acquire() #define STORE_METHOD_LEAVE(pMutex, eErrCode) \ { \ if ((pMutex)) (pMutex)->release(); \ return (eErrCode); \ } /*======================================================================== * * OStorePageBIOS. * *======================================================================*/ struct OStoreSuperBlockPage; struct OStorePageACL; class OStorePageBIOS : public store::OStoreObject { public: /** Construction. */ OStorePageBIOS (void); /** Conversion into Mutex& */ inline operator osl::Mutex& (void) const; /** Initialization. * @param pLockBytes [in] * @param eAccessMode [in] * @return store_E_None upon success */ virtual storeError initialize ( ILockBytes *pLockBytes, storeAccessMode eAccessMode); /** getPageSize. */ storeError getPageSize (sal_uInt16 &rnPageSize); /** acquireLock. */ storeError acquireLock ( sal_uInt32 nAddr, sal_uInt32 nSize); /** releaseLock. */ storeError releaseLock ( sal_uInt32 nAddr, sal_uInt32 nSize); /** read. */ storeError read ( sal_uInt32 nAddr, void *pData, sal_uInt32 nSize); /** write. */ storeError write ( sal_uInt32 nAddr, const void *pData, sal_uInt32 nSize); /** isModified. */ inline sal_Bool isModified (void) const; /** isWriteable. */ inline sal_Bool isWriteable (void) const; /** isValid. */ inline sal_Bool isValid (void) const; /** Page Access. */ storeError acquirePage ( const OStorePageDescriptor& rDescr, storeAccessMode eMode); storeError releasePage (const OStorePageDescriptor& rDescr); sal_uInt32 getRefererCount (void); /** Page Allocation. */ enum Allocation { ALLOCATE_FIRST = 0, ALLOCATE_BEST = 1, ALLOCATE_EOF = 2 }; storeError allocate ( OStorePageObject& rPage, Allocation eAllocation = ALLOCATE_FIRST); virtual storeError free ( OStorePageObject& rPage); /** Page I/O. */ virtual storeError load ( OStorePageObject& rPage); virtual storeError save ( OStorePageObject& rPage); /** close. * @return store_E_None upon success. */ virtual storeError close (void); /** flush. * @return store_E_None upon success. */ virtual storeError flush (void); /** size. */ storeError size (sal_uInt32 &rnSize); /** ScanContext. */ struct ScanContext { /** Representation. */ OStorePageDescriptor m_aDescr; sal_uInt32 m_nSize; sal_uInt32 m_nMagic; /** Construction. */ inline ScanContext (void); /** isValid. */ inline sal_Bool isValid (void) const; }; /** scanBegin. */ storeError scanBegin ( ScanContext &rCtx, sal_uInt32 nMagic = 0); /** scanNext. */ storeError scanNext ( ScanContext &rCtx, OStorePageObject &rPage); protected: /** Destruction (OReference). */ virtual ~OStorePageBIOS (void); /** create (SuperBlock). */ storeError create ( sal_uInt16 nPageSize = STORE_DEFAULT_PAGESIZE); /** Page Maintenance. */ storeError peek ( OStorePageData &rData); storeError poke ( OStorePageData &rData); storeError poke ( OStorePageObject &rPage); private: /** Representation. */ rtl::Reference m_xLockBytes; osl::Mutex m_aMutex; OStorePageACL *m_pAcl; typedef OStoreSuperBlockPage SuperPage; SuperPage *m_pSuper; sal_Bool m_bModified : 1; sal_Bool m_bWriteable : 1; /** SuperBlock verification and repair. */ storeError verify (SuperPage *&rpSuper); storeError repair (SuperPage *&rpSuper); /** Not implemented. */ OStorePageBIOS (const OStorePageBIOS&); OStorePageBIOS& operator= (const OStorePageBIOS&); }; inline OStorePageBIOS::operator osl::Mutex& (void) const { return (osl::Mutex&)m_aMutex; } inline sal_Bool OStorePageBIOS::isModified (void) const { return m_bModified; } inline sal_Bool OStorePageBIOS::isWriteable (void) const { return m_bWriteable; } inline sal_Bool OStorePageBIOS::isValid (void) const { return m_xLockBytes.is(); } inline OStorePageBIOS::ScanContext::ScanContext (void) : m_aDescr (0, 0, 0), m_nSize (0), m_nMagic (0) { } inline sal_Bool OStorePageBIOS::ScanContext::isValid (void) const { return (m_aDescr.m_nAddr < m_nSize); } /*======================================================================== * * The End. * *======================================================================*/ } // namespace store #endif /* !_STORE_STORBASE_HXX_ */