diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 14:18:43 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 14:18:43 +0000 |
commit | 215e8c7210756d6d9033f8d742a6cd0e9be132aa (patch) | |
tree | d1a56131d83c8298e6183cf17b912037ae63b9c9 /store/source/stordata.cxx |
initial import
Diffstat (limited to 'store/source/stordata.cxx')
-rw-r--r-- | store/source/stordata.cxx | 1754 |
1 files changed, 1754 insertions, 0 deletions
diff --git a/store/source/stordata.cxx b/store/source/stordata.cxx new file mode 100644 index 000000000..06078297b --- /dev/null +++ b/store/source/stordata.cxx @@ -0,0 +1,1754 @@ +/************************************************************************* + * + * $RCSfile: stordata.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:18:32 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 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 + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _STORE_STORDATA_CXX_ "$Revision: 1.1.1.1 $" + +#ifndef _SAL_TYPES_H_ +#include <sal/types.h> +#endif + +#ifndef _VOS_DIAGNOSE_HXX_ +#include <vos/diagnose.hxx> +#endif +#ifndef _VOS_MACROS_HXX_ +#include <vos/macros.hxx> +#endif +#ifndef _VOS_MUTEX_HXX_ +#include <vos/mutex.hxx> +#endif + +#ifndef _STORE_TYPES_H_ +#include <store/types.h> +#endif +#ifndef _STORE_MACROS_HXX_ +#include <store/macros.hxx> +#endif + +#ifndef _STORE_STORBASE_HXX_ +#include <storbase.hxx> +#endif +#ifndef _STORE_STORDATA_HXX_ +#include <stordata.hxx> +#endif + +#ifdef _USE_NAMESPACE +using namespace store; +#endif + +/*======================================================================== + * + * OStoreIndirectionPageData implementation. + * + *======================================================================*/ +/* + * OStoreIndirectionPageData. + */ +OStoreIndirectionPageData::OStoreIndirectionPageData (sal_uInt16 nPageSize) + : OStorePageData (nPageSize) +{ + initialize(); +} + +/* + * initialize. + */ +void OStoreIndirectionPageData::initialize (void) +{ + base::m_aGuard.m_nMagic = STORE_MAGIC_INDIRECTPAGE; + base::m_aDescr.m_nUsed += self::size(); + self::m_aGuard.m_nMagic = 0; + + sal_uInt16 i, n = capacityCount(); + for (i = 0; i < n; i++) + m_pData[i] = STORE_PAGE_NULL; +} + +/* + * swap. + */ +void OStoreIndirectionPageData::swap (const D& rDescr) +{ +#ifdef OSL_BIGENDIAN + m_aGuard.swap(); + + sal_uInt16 i, n = capacityCount (rDescr); + for (i = 0; i < n; i++) + m_pData[i] = VOS_SWAPDWORD(m_pData[i]); +#endif /* OSL_BIGENDIAN */ +} + +/*======================================================================== + * + * OStoreIndirectionPageObject implementation. + * + *======================================================================*/ +/* + * swap. + */ +void OStoreIndirectionPageObject::swap (const D& rDescr) +{ +#ifdef OSL_BIGENDIAN + base::swap (rDescr); + m_rPage.swap (rDescr); +#endif /* OSL_BIGENDIAN */ +} + +/* + * guard. + */ +void OStoreIndirectionPageObject::guard (const D& rDescr) +{ + base::guard (rDescr); + m_rPage.guard (rDescr); +} + +/* + * verify. + */ +storeError OStoreIndirectionPageObject::verify (const D& rDescr) +{ + storeError eErrCode = base::verify (rDescr); + if (eErrCode != store_E_None) + return eErrCode; + else + return m_rPage.verify (rDescr); +} + +/* + * get (single indirect). + */ +storeError OStoreIndirectionPageObject::get ( + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + if (!(nSingle < m_rPage.capacityCount())) + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); + + // Obtain data page location. + sal_uInt32 nAddr = m_rPage.m_pData[nSingle]; + if (nAddr == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + // Load data page. + rData.location (nAddr); + storeError eErrCode = rBIOS.load (rData); + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * get (double indirect). + */ +storeError OStoreIndirectionPageObject::get ( + sal_uInt16 nDouble, + sal_uInt16 nSingle, + page *&rpSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + if (!((nDouble < m_rPage.capacityCount()) && + (nSingle < m_rPage.capacityCount()) )) + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); + + // Check single indirect page location. + if (m_rPage.m_pData[nDouble] == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + // Check single indirect page buffer. + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) page(nPageSize); + } + + // Load single indirect page. + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (m_rPage.m_pData[nDouble]); + + storeError eErrCode = rBIOS.load (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Get single indirect. + eErrCode = aSingle.get (nSingle, rData, rBIOS, NULL); + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * get (triple indirect). + */ +storeError OStoreIndirectionPageObject::get ( + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + page *&rpDouble, + page *&rpSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + if (!((nTriple < m_rPage.capacityCount()) && + (nDouble < m_rPage.capacityCount()) && + (nSingle < m_rPage.capacityCount()) )) + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); + + // Check double indirect page location. + if (m_rPage.m_pData[nTriple] == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + // Check double indirect page buffer. + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) page(nPageSize); + } + + // Load double indirect page. + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (m_rPage.m_pData[nTriple]); + + storeError eErrCode = rBIOS.load (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Get double indirect. + eErrCode = aDouble.get (nDouble, nSingle, rpSingle, rData, rBIOS, NULL); + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * put (single indirect). + */ +storeError OStoreIndirectionPageObject::put ( + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + storeError eErrCode = store_E_InvalidAccess; + if (!(nSingle < m_rPage.capacityCount())) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Obtain data page location. + rData.location (m_rPage.m_pData[nSingle]); + if (rData.location() == STORE_PAGE_NULL) + { + // Allocate data page. + eErrCode = rBIOS.allocate (rData); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Save data page location. + m_rPage.m_pData[nSingle] = rData.location(); + touch(); + + // Save this page. + eErrCode = rBIOS.save (*this); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + else + { + // Save data page. + eErrCode = rBIOS.save (rData); + } + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * put (double indirect). + */ +storeError OStoreIndirectionPageObject::put ( + sal_uInt16 nDouble, + sal_uInt16 nSingle, + page *&rpSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + storeError eErrCode = store_E_InvalidAccess; + if (!((nDouble < m_rPage.capacityCount()) && + (nSingle < m_rPage.capacityCount()) )) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Check single indirect page buffer. + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) page(nPageSize); + } + + // Obtain single indirect page location. + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (m_rPage.m_pData[nDouble]); + if (aSingle.location() == STORE_PAGE_NULL) + { + // Initialize single indirect page buffer. + rpSingle->initialize(); + + // Allocate single indirect page. + eErrCode = rBIOS.allocate (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Save single indirect page location. + m_rPage.m_pData[nDouble] = aSingle.location(); + touch(); + + // Save this page. + eErrCode = rBIOS.save (*this); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + else + { + // Load single indirect page. + eErrCode = rBIOS.load (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Put single indirect. + eErrCode = aSingle.put (nSingle, rData, rBIOS, NULL); + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * put (triple indirect). + */ +storeError OStoreIndirectionPageObject::put ( + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + page *&rpDouble, + page *&rpSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + storeError eErrCode = store_E_InvalidAccess; + if (!((nTriple < m_rPage.capacityCount()) && + (nDouble < m_rPage.capacityCount()) && + (nSingle < m_rPage.capacityCount()) )) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Check double indirect page buffer. + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) page(nPageSize); + } + + // Obtain double indirect page location. + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (m_rPage.m_pData[nTriple]); + if (aDouble.location() == STORE_PAGE_NULL) + { + // Initialize double indirect page buffer. + rpDouble->initialize(); + + // Allocate double indirect page. + eErrCode = rBIOS.allocate (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Save double indirect page location. + m_rPage.m_pData[nTriple] = aDouble.location(); + touch(); + + // Save this page. + eErrCode = rBIOS.save (*this); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + else + { + // Load double indirect page. + eErrCode = rBIOS.load (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Put double indirect. + eErrCode = aDouble.put (nDouble, nSingle, rpSingle, rData, rBIOS, NULL); + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * truncate (single indirect). + */ +storeError OStoreIndirectionPageObject::truncate ( + sal_uInt16 nSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + sal_uInt16 i, n = m_rPage.capacityCount(); + if (!(nSingle < n)) + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); + + // Save PageDescriptor. + D aDescr (m_rPage.m_aDescr); + + // Acquire Lock. + storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate. + for (i = n; i > nSingle; i--) + { + // Obtain data page location. + sal_uInt32 nAddr = m_rPage.m_pData[i - 1]; + if (nAddr == STORE_PAGE_NULL) continue; + + // Free data page. + rData.location (nAddr); + eErrCode = rBIOS.free (rData); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Clear pointer to data page. + m_rPage.m_pData[i - 1] = STORE_PAGE_NULL; + touch(); + } + + // Check for modified page. + if (dirty()) + { + // Save this page. + eErrCode = rBIOS.save (*this); + if (eErrCode != store_E_None) + { + // Must not happen. + VOS_TRACE("OStoreIndirectionPageObject::truncate(): save failed"); + + // Release Lock and Leave. + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Release Lock and Leave. + eErrCode = rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * truncate (double indirect). + */ +storeError OStoreIndirectionPageObject::truncate ( + sal_uInt16 nDouble, + sal_uInt16 nSingle, + page *&rpSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Acquire Mutex. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + if (!((nDouble < m_rPage.capacityCount()) && + (nSingle < m_rPage.capacityCount()) )) + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); + + // Save PageDescriptor. + D aDescr (m_rPage.m_aDescr); + + // Acquire Lock. + storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate. + sal_uInt16 i, n = m_rPage.capacityCount(); + for (i = n; i > nDouble + 1; i--) + { + // Obtain single indirect page location. + sal_uInt32 nAddr = m_rPage.m_pData[i - 1]; + if (nAddr == STORE_PAGE_NULL) continue; + + // Check single indirect page buffer. + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) page(nPageSize); + } + + // Load single indirect page. + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (nAddr); + + eErrCode = rBIOS.load (aSingle); + if (eErrCode == store_E_None) + { + // Truncate to zero direct pages. + eErrCode = aSingle.truncate (0, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Free single indirect page. + eErrCode = rBIOS.free (aSingle); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + else + { + if (eErrCode != store_E_InvalidChecksum) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Clear pointer to single indirect page. + m_rPage.m_pData[i - 1] = STORE_PAGE_NULL; + touch(); + } + + // Obtain last single indirect page location. + sal_uInt32 nAddr = m_rPage.m_pData[nDouble]; + if (nAddr != STORE_PAGE_NULL) + { + // Check single indirect page buffer. + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) page(nPageSize); + } + + // Load last single indirect page. + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (nAddr); + + eErrCode = rBIOS.load (aSingle); + if (eErrCode == store_E_None) + { + // Truncate to 'nSingle' direct pages. + eErrCode = aSingle.truncate (nSingle, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + else + { + if (eErrCode != store_E_InvalidChecksum) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Check for complete truncation. + if (nSingle == 0) + { + // Free last single indirect page. + eErrCode = rBIOS.free (aSingle); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Clear pointer to last single indirect page. + m_rPage.m_pData[nDouble] = STORE_PAGE_NULL; + touch(); + } + } + + // Check for modified page. + if (dirty()) + { + // Save this page. + eErrCode = rBIOS.save (*this); + if (eErrCode != store_E_None) + { + // Must not happen. + VOS_TRACE("OStoreIndirectionPageObject::truncate(): save failed"); + + // Release Lock and Leave. + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Release Lock and Leave. + eErrCode = rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * truncate (triple indirect). + */ +storeError OStoreIndirectionPageObject::truncate ( + sal_uInt16 nTriple, + sal_uInt16 nDouble, + sal_uInt16 nSingle, + page *&rpDouble, + page *&rpSingle, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Check arguments. + if (!((nTriple < m_rPage.capacityCount()) && + (nDouble < m_rPage.capacityCount()) && + (nSingle < m_rPage.capacityCount()) )) + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); + + // Save PageDescriptor. + D aDescr (m_rPage.m_aDescr); + + // Acquire Lock. + storeError eErrCode = rBIOS.acquireLock (aDescr.m_nAddr, aDescr.m_nSize); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate. + sal_uInt16 i, n = m_rPage.capacityCount(); + for (i = n; i > nTriple + 1; i--) + { + // Obtain double indirect page location. + sal_uInt32 nAddr = m_rPage.m_pData[i - 1]; + if (nAddr == STORE_PAGE_NULL) continue; + + // Check double indirect page buffer. + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) page(nPageSize); + } + + // Load double indirect page. + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (nAddr); + + eErrCode = rBIOS.load (aDouble); + if (eErrCode == store_E_None) + { + // Truncate to zero single indirect pages. + eErrCode = aDouble.truncate ( + 0, 0, rpSingle, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Free double indirect page. + eErrCode = rBIOS.free (aDouble); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + else + { + if (eErrCode != store_E_InvalidChecksum) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Clear pointer to double indirect page. + m_rPage.m_pData[i - 1] = STORE_PAGE_NULL; + touch(); + } + + // Obtain last double indirect page location. + sal_uInt32 nAddr = m_rPage.m_pData[nTriple]; + if (nAddr != STORE_PAGE_NULL) + { + // Check double indirect page buffer. + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) page(nPageSize); + } + + // Load last double indirect page. + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (nAddr); + + eErrCode = rBIOS.load (aDouble); + if (eErrCode == store_E_None) + { + // Truncate to 'nDouble', 'nSingle' pages. + eErrCode = aDouble.truncate ( + nDouble, nSingle, rpSingle, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + else + { + if (eErrCode != store_E_InvalidChecksum) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Check for complete truncation. + if ((nDouble + nSingle) == 0) + { + // Free last double indirect page. + eErrCode = rBIOS.free (aDouble); + if (eErrCode != store_E_None) + { + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Clear pointer to last double indirect page. + m_rPage.m_pData[nTriple] = STORE_PAGE_NULL; + touch(); + } + } + + // Check for modified page. + if (dirty()) + { + // Save this page. + eErrCode = rBIOS.save (*this); + if (eErrCode != store_E_None) + { + // Must not happen. + VOS_TRACE("OStoreIndirectionPageObject::truncate(): save failed"); + + // Release Lock and Leave. + rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + } + + // Release Lock and Leave. + eErrCode = rBIOS.releaseLock (aDescr.m_nAddr, aDescr.m_nSize); + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/*======================================================================== + * + * OStoreDirectoryDataBlock::LinkTable implementation. + * + *======================================================================*/ +/* + * LinkTable::LinkTable. + */ +OStoreDirectoryDataBlock::LinkTable::LinkTable (void) +{ + initialize(); +} + +/* + * LinkTable::initialize. + */ +void OStoreDirectoryDataBlock::LinkTable::initialize (void) +{ + sal_Int32 i; + for (i = 0; i < STORE_LIMIT_DATAPAGE_DIRECT; i++) + m_pDirect[i] = STORE_PAGE_NULL; + for (i = 0; i < STORE_LIMIT_DATAPAGE_SINGLE; i++) + m_pSingle[i] = STORE_PAGE_NULL; + for (i = 0; i < STORE_LIMIT_DATAPAGE_DOUBLE; i++) + m_pDouble[i] = STORE_PAGE_NULL; + for (i = 0; i < STORE_LIMIT_DATAPAGE_TRIPLE; i++) + m_pTriple[i] = STORE_PAGE_NULL; +} + +/* + * LinkTable::swap. + */ +void OStoreDirectoryDataBlock::LinkTable::swap (void) +{ +#ifdef OSL_BIGENDIAN + sal_Int32 i; + for (i = 0; i < STORE_LIMIT_DATAPAGE_DIRECT; i++) + m_pDirect[i] = VOS_SWAPDWORD(m_pDirect[i]); + for (i = 0; i < STORE_LIMIT_DATAPAGE_SINGLE; i++) + m_pSingle[i] = VOS_SWAPDWORD(m_pSingle[i]); + for (i = 0; i < STORE_LIMIT_DATAPAGE_DOUBLE; i++) + m_pDouble[i] = VOS_SWAPDWORD(m_pDouble[i]); + for (i = 0; i < STORE_LIMIT_DATAPAGE_TRIPLE; i++) + m_pTriple[i] = VOS_SWAPDWORD(m_pTriple[i]); +#endif /* OSL_BIGENDIAN */ +} + +/*======================================================================== + * + * OStoreDirectoryPageObject implementation. + * + *======================================================================*/ +/* + * swap. + */ +void OStoreDirectoryPageObject::swap (const D& rDescr) +{ +#ifdef OSL_BIGENDIAN + base::swap (rDescr); + m_rPage.swap (rDescr); +#endif /* OSL_BIGENDIAN */ +} + +/* + * guard. + */ +void OStoreDirectoryPageObject::guard (const D& rDescr) +{ + base::guard (rDescr); + m_rPage.guard (rDescr); +} + +/* + * verify. + */ +storeError OStoreDirectoryPageObject::verify (const D& rDescr) +{ + storeError eErrCode = base::verify (rDescr); + if (eErrCode != store_E_None) + return eErrCode; + else + return m_rPage.verify (rDescr); +} + +/* + * scope (external data page). + */ +OStoreDirectoryPageData::ChunkScope +OStoreDirectoryPageObject::scope ( + sal_uInt32 nPage, + page::DataBlock::LinkDescriptor &rDescr) const +{ + typedef OStoreIndirectionPageData indirect; + sal_uInt32 index0, index1, index2, index3; + + // direct. + sal_uInt32 nCount = m_rPage.m_aDataBlock.directCount(); + sal_uInt32 nLimit = nCount; + if (nPage < nLimit) + { + // Page to index reduction. + index0 = nPage; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + + // Done. + return page::SCOPE_DIRECT; + } + nPage -= nLimit; + + // single indirect. + sal_uInt32 nCapacity = indirect::capacityCount(m_rPage.m_aDescr); + nCount = m_rPage.m_aDataBlock.singleCount(); + nLimit = nCount * nCapacity; + if (nPage < nLimit) + { + // Page to index reduction. + sal_uInt32 n = nPage; + + // Reduce to single indirect i(1), direct n = i(0). + index1 = n / nCapacity; + index0 = n % nCapacity; + + // Verify reduction. + n = index1 * nCapacity + index0; + VOS_POSTCOND(n == nPage, "wrong math on indirect indices"); + if (n != nPage) + return page::SCOPE_UNKNOWN; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); + + // Done. + return page::SCOPE_SINGLE; + } + nPage -= nLimit; + + // double indirect. + nCount = m_rPage.m_aDataBlock.doubleCount(); + nLimit = nCount * nCapacity * nCapacity; + if (nPage < nLimit) + { + // Page to index reduction. + sal_uInt32 n = nPage; + + // Reduce to double indirect i(2), single indirect n = i(0). + index2 = n / (nCapacity * nCapacity); + n = n % (nCapacity * nCapacity); + + // Reduce to single indirect i(1), direct n = i(0). + index1 = n / nCapacity; + index0 = n % nCapacity; + + // Verify reduction. + n = index2 * nCapacity * nCapacity + + index1 * nCapacity + index0; + VOS_POSTCOND(n == nPage, "wrong math on double indirect indices"); + if (n != nPage) + return page::SCOPE_UNKNOWN; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); + rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff); + + // Done. + return page::SCOPE_DOUBLE; + } + nPage -= nLimit; + + // triple indirect. + nCount = m_rPage.m_aDataBlock.tripleCount(); + nLimit = nCount * nCapacity * nCapacity * nCapacity; + if (nPage < nLimit) + { + // Page to index reduction. + sal_uInt32 n = nPage; + + // Reduce to triple indirect i(3), double indirect n. + index3 = n / (nCapacity * nCapacity * nCapacity); + n = n % (nCapacity * nCapacity * nCapacity); + + // Reduce to double indirect i(2), single indirect n. + index2 = n / (nCapacity * nCapacity); + n = n % (nCapacity * nCapacity); + + // Reduce to single indirect i(1), direct n = i(0). + index1 = n / nCapacity; + index0 = n % nCapacity; + + // Verify reduction. + n = index3 * nCapacity * nCapacity * nCapacity + + index2 * nCapacity * nCapacity + + index1 * nCapacity + index0; + VOS_POSTCOND(n == nPage, "wrong math on triple indirect indices"); + if (n != nPage) + return page::SCOPE_UNKNOWN; + + // Setup LinkDescriptor indices. + rDescr.m_nIndex0 = (sal_uInt16)(index0 & 0xffff); + rDescr.m_nIndex1 = (sal_uInt16)(index1 & 0xffff); + rDescr.m_nIndex2 = (sal_uInt16)(index2 & 0xffff); + rDescr.m_nIndex3 = (sal_uInt16)(index3 & 0xffff); + + // Done. + return page::SCOPE_TRIPLE; + } + + // Unreachable (more than triple indirect). + return page::SCOPE_UNREACHABLE; +} + +/* + * get (external data page). + */ +storeError OStoreDirectoryPageObject::get ( + sal_uInt32 nPage, + indirect *&rpSingle, + indirect *&rpDouble, + indirect *&rpTriple, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Determine scope and link indices. + page::DataBlock::LinkDescriptor aLink; + page::ChunkScope eScope = scope (nPage, aLink); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + sal_uInt32 nAddr = directLink (aLink.m_nIndex0); + if (nAddr == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + rData.location (nAddr); + eErrCode = rBIOS.load (rData); + } + else if (eScope == page::SCOPE_SINGLE) + { + sal_uInt32 nAddr = singleLink (aLink.m_nIndex1); + if (nAddr == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (nAddr); + + eErrCode = rBIOS.load (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + eErrCode = aSingle.get ( + aLink.m_nIndex0, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_DOUBLE) + { + sal_uInt32 nAddr = doubleLink (aLink.m_nIndex2); + if (nAddr == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (nAddr); + + eErrCode = rBIOS.load (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + eErrCode = aDouble.get ( + aLink.m_nIndex1, + aLink.m_nIndex0, + rpSingle, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_TRIPLE) + { + sal_uInt32 nAddr = tripleLink (aLink.m_nIndex3); + if (nAddr == STORE_PAGE_NULL) + STORE_METHOD_LEAVE(pMutex, store_E_NotExists); + + if (rpTriple == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpTriple = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aTriple (*rpTriple); + aTriple.location (nAddr); + + eErrCode = rBIOS.load (aTriple); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + eErrCode = aTriple.get ( + aLink.m_nIndex2, + aLink.m_nIndex1, + aLink.m_nIndex0, + rpDouble, + rpSingle, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_UNREACHABLE) + { + // Out of scope. + eErrCode = store_E_CantSeek; + } + else + { + // Unknown scope. + VOS_TRACE("OStoreDirectoryPageObject::get(): scope failed"); + eErrCode = store_E_Unknown; + } + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * put (external data page). + */ +storeError OStoreDirectoryPageObject::put ( + sal_uInt32 nPage, + indirect *&rpSingle, + indirect *&rpDouble, + indirect *&rpTriple, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Determine scope and link indices. + page::DataBlock::LinkDescriptor aLink; + page::ChunkScope eScope = scope (nPage, aLink); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + rData.location (directLink (aLink.m_nIndex0)); + if (rData.location() == STORE_PAGE_NULL) + { + eErrCode = rBIOS.allocate (rData); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + directLink (aLink.m_nIndex0, rData.location()); + } + else + { + eErrCode = rBIOS.save (rData); + } + } + else if (eScope == page::SCOPE_SINGLE) + { + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (singleLink (aLink.m_nIndex1)); + if (aSingle.location() == STORE_PAGE_NULL) + { + rpSingle->initialize(); + + eErrCode = rBIOS.allocate (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + singleLink (aLink.m_nIndex1, aSingle.location()); + } + else + { + eErrCode = rBIOS.load (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + eErrCode = aSingle.put ( + aLink.m_nIndex0, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_DOUBLE) + { + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (doubleLink (aLink.m_nIndex2)); + if (aDouble.location() == STORE_PAGE_NULL) + { + rpDouble->initialize(); + + eErrCode = rBIOS.allocate (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + doubleLink (aLink.m_nIndex2, aDouble.location()); + } + else + { + eErrCode = rBIOS.load (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + eErrCode = aDouble.put ( + aLink.m_nIndex1, + aLink.m_nIndex0, + rpSingle, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_TRIPLE) + { + if (rpTriple == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpTriple = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aTriple (*rpTriple); + aTriple.location (tripleLink (aLink.m_nIndex3)); + if (aTriple.location() == STORE_PAGE_NULL) + { + rpTriple->initialize(); + + eErrCode = rBIOS.allocate (aTriple); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + tripleLink (aLink.m_nIndex3, aTriple.location()); + } + else + { + eErrCode = rBIOS.load (aTriple); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + eErrCode = aTriple.put ( + aLink.m_nIndex2, + aLink.m_nIndex1, + aLink.m_nIndex0, + rpDouble, + rpSingle, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_UNREACHABLE) + { + // Out of scope. + eErrCode = store_E_CantSeek; + } + else + { + // Unknown scope. + VOS_TRACE("OStoreDirectoryPageObject::put(): scope failed"); + eErrCode = store_E_Unknown; + } + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * truncate (external data page). + */ +storeError OStoreDirectoryPageObject::truncate ( + sal_uInt32 nPage, + indirect *&rpSingle, + indirect *&rpDouble, + indirect *&rpTriple, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + // Determine scope and link indices. + page::DataBlock::LinkDescriptor aLink; + page::ChunkScope eScope = scope (nPage, aLink); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + // Truncate all triple indirect pages. + eErrCode = truncate ( + page::SCOPE_TRIPLE, 0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate all double indirect pages. + eErrCode = truncate ( + page::SCOPE_DOUBLE, 0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate all single indirect pages. + eErrCode = truncate ( + page::SCOPE_SINGLE, 0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate direct pages, including 'aLink.m_nIndex0'. + eErrCode = truncate ( + eScope, aLink.m_nIndex0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + } + else if (eScope == page::SCOPE_SINGLE) + { + // Truncate all triple indirect pages. + eErrCode = truncate ( + page::SCOPE_TRIPLE, 0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate all double indirect pages. + eErrCode = truncate ( + page::SCOPE_DOUBLE, 0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate single indirect pages, downto 'aLink.m_nIndex1'. + eErrCode = truncate ( + eScope, aLink.m_nIndex1 + 1, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Obtain last single indirect page location. + sal_uInt32 nAddr = singleLink (aLink.m_nIndex1); + if (nAddr != STORE_PAGE_NULL) + { + // Check single indirect page buffer. + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) indirect(nPageSize); + } + + // Load last single indirect page. + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (nAddr); + + eErrCode = rBIOS.load (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate to ... pages. + eErrCode = aSingle.truncate ( + aLink.m_nIndex0, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Check for complete truncation. + if (aLink.m_nIndex0 == 0) + { + // Free last single indirect page. + eErrCode = rBIOS.free (aSingle); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Clear pointer to last single indirect page. + singleLink (aLink.m_nIndex1, STORE_PAGE_NULL); + } + } + } + else if (eScope == page::SCOPE_DOUBLE) + { + // Truncate all triple indirect pages. + eErrCode = truncate ( + page::SCOPE_TRIPLE, 0, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate double indirect pages, downto 'aLink.m_nIndex2'. + eErrCode = truncate ( + eScope, aLink.m_nIndex2 + 1, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Obtain last double indirect page location. + sal_uInt32 nAddr = doubleLink (aLink.m_nIndex2); + if (nAddr != STORE_PAGE_NULL) + { + // Check double indirect page buffer. + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) indirect(nPageSize); + } + + // Load last double indirect page. + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (nAddr); + + eErrCode = rBIOS.load (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate to ... pages. + eErrCode = aDouble.truncate ( + aLink.m_nIndex1, + aLink.m_nIndex0, + rpSingle, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Check for complete truncation. + if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0) + { + // Free last double indirect page. + eErrCode = rBIOS.free (aDouble); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Clear pointer to last double indirect page. + doubleLink (aLink.m_nIndex2, STORE_PAGE_NULL); + } + } + } + else if (eScope == page::SCOPE_TRIPLE) + { + // Truncate triple indirect pages, downto 'aLink.m_nIndex3'. + eErrCode = truncate ( + eScope, aLink.m_nIndex3 + 1, + rpSingle, rpDouble, rpTriple, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Obtain last triple indirect page location. + sal_uInt32 nAddr = tripleLink (aLink.m_nIndex3); + if (nAddr != STORE_PAGE_NULL) + { + // Check triple indirect page buffer. + if (rpTriple == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpTriple = new(nPageSize) indirect(nPageSize); + } + + // Load last triple indirect page. + OStoreIndirectionPageObject aTriple (*rpTriple); + aTriple.location (nAddr); + + eErrCode = rBIOS.load (aTriple); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Truncate to ... pages. + eErrCode = aTriple.truncate ( + aLink.m_nIndex2, + aLink.m_nIndex1, + aLink.m_nIndex0, + rpDouble, rpSingle, + rData, rBIOS, NULL); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Check for complete truncation. + if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0) + { + // Free last triple indirect page. + eErrCode = rBIOS.free (aTriple); + if (eErrCode != store_E_None) + STORE_METHOD_LEAVE(pMutex, eErrCode); + + // Clear pointer to last triple indirect page. + tripleLink (aLink.m_nIndex3, STORE_PAGE_NULL); + } + } + } + else if (eScope == page::SCOPE_UNREACHABLE) + { + // Out of scope. + eErrCode = store_E_CantSeek; + } + else + { + // Unknown scope. + VOS_TRACE("OStoreDirectoryPageObject::put(): scope failed"); + eErrCode = store_E_Unknown; + } + + // Leave. + STORE_METHOD_LEAVE(pMutex, eErrCode); +} + +/* + * truncate (external data page scope; private). + */ +storeError OStoreDirectoryPageObject::truncate ( + page::ChunkScope eScope, + sal_uInt16 nRemain, + indirect *&rpSingle, + indirect *&rpDouble, + indirect *&rpTriple, + OStoreDataPageObject &rData, + OStorePageBIOS &rBIOS, + NAMESPACE_VOS(IMutex) *pMutex) +{ + // Enter. + STORE_METHOD_ENTER(pMutex); + + storeError eErrCode = store_E_None; + if (eScope == page::SCOPE_DIRECT) + { + // Truncate direct data pages. + sal_uInt16 i, n = m_rPage.m_aDataBlock.directCount(); + for (i = n; i > nRemain; i--) + { + // Obtain data page location. + sal_uInt32 nAddr = directLink (i - 1); + if (nAddr == STORE_PAGE_NULL) continue; + + // Free data page. + rData.location (nAddr); + eErrCode = rBIOS.free (rData); + if (eErrCode != store_E_None) + break; + + // Clear pointer to data page. + directLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + if (eScope == page::SCOPE_SINGLE) + { + // Truncate single indirect pages. + sal_uInt16 i, n = m_rPage.m_aDataBlock.singleCount(); + for (i = n; i > nRemain; i--) + { + // Obtain single indirect page location. + sal_uInt32 nAddr = singleLink (i - 1); + if (nAddr == STORE_PAGE_NULL) continue; + + // Check single indirect page buffer. + if (rpSingle == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpSingle = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aSingle (*rpSingle); + aSingle.location (nAddr); + + // Load single indirect page. + eErrCode = rBIOS.load (aSingle); + if (eErrCode != store_E_None) + break; + + // Truncate to zero data pages. + eErrCode = aSingle.truncate ( + 0, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + break; + + // Free single indirect page. + eErrCode = rBIOS.free (aSingle); + if (eErrCode != store_E_None) + break; + + // Clear pointer to single indirect page. + singleLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + if (eScope == page::SCOPE_DOUBLE) + { + // Truncate double indirect pages. + sal_uInt16 i, n = m_rPage.m_aDataBlock.doubleCount(); + for (i = n; i > nRemain; i--) + { + // Obtain double indirect page location. + sal_uInt32 nAddr = doubleLink (i - 1); + if (nAddr == STORE_PAGE_NULL) continue; + + // Check double indirect page buffer. + if (rpDouble == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpDouble = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aDouble (*rpDouble); + aDouble.location (nAddr); + + // Load double indirect page. + eErrCode = rBIOS.load (aDouble); + if (eErrCode != store_E_None) + break; + + // Truncate to zero single indirect pages. + eErrCode = aDouble.truncate ( + 0, 0, rpSingle, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + break; + + // Free double indirect page. + eErrCode = rBIOS.free (aDouble); + if (eErrCode != store_E_None) + break; + + // Clear pointer to double indirect page. + doubleLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + if (eScope == page::SCOPE_TRIPLE) + { + // Truncate triple indirect pages. + sal_uInt16 i, n = m_rPage.m_aDataBlock.tripleCount(); + for (i = n; i > nRemain; i--) + { + // Obtain triple indirect page location. + sal_uInt32 nAddr = tripleLink (i - 1); + if (nAddr == STORE_PAGE_NULL) continue; + + // Check triple indirect page buffer. + if (rpTriple == NULL) + { + sal_uInt16 nPageSize = m_rPage.m_aDescr.m_nSize; + rpTriple = new(nPageSize) indirect(nPageSize); + } + + OStoreIndirectionPageObject aTriple (*rpTriple); + aTriple.location (nAddr); + + // Load triple indirect page. + eErrCode = rBIOS.load (aTriple); + if (eErrCode != store_E_None) + break; + + // Truncate to zero double indirect pages. + eErrCode = aTriple.truncate ( + 0, 0, 0, rpDouble, rpSingle, rData, rBIOS, NULL); + if (eErrCode != store_E_None) + break; + + // Free triple indirect page. + eErrCode = rBIOS.free (aTriple); + if (eErrCode != store_E_None) + break; + + // Clear pointer to triple indirect page. + tripleLink (i - 1, STORE_PAGE_NULL); + } + + // Done. + STORE_METHOD_LEAVE(pMutex, eErrCode); + } + + // Invalid scope. + STORE_METHOD_LEAVE(pMutex, store_E_InvalidAccess); +} + |