| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_store.hxx" |
| |
| #include "stordata.hxx" |
| |
| #include "sal/types.h" |
| #include "osl/diagnose.h" |
| |
| #include "store/types.h" |
| #include "storbase.hxx" |
| #include "storbios.hxx" |
| |
| using namespace store; |
| |
| /*======================================================================== |
| * |
| * OStoreDataPageObject implementation. |
| * |
| *======================================================================*/ |
| /* |
| * guard. |
| */ |
| storeError OStoreDataPageObject::guard (sal_uInt32 nAddr) |
| { |
| return PageHolderObject< page >::guard (m_xPage, nAddr); |
| } |
| |
| /* |
| * verify. |
| */ |
| storeError OStoreDataPageObject::verify (sal_uInt32 nAddr) const |
| { |
| return PageHolderObject< page >::verify (m_xPage, nAddr); |
| } |
| |
| /*======================================================================== |
| * |
| * OStoreIndirectionPageObject implementation. |
| * |
| *======================================================================*/ |
| /* |
| * store_truncate_Impl (single indirect page). |
| */ |
| static storeError store_truncate_Impl ( |
| sal_uInt32 nAddr, |
| sal_uInt16 nSingle, |
| OStorePageBIOS &rBIOS) |
| { |
| if (nAddr != STORE_PAGE_NULL) |
| { |
| // Load single indirect page. |
| OStoreIndirectionPageObject aSingle; |
| storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); |
| if (eErrCode == store_E_None) |
| { |
| // Truncate to 'nSingle' direct pages. |
| eErrCode = aSingle.truncate (nSingle, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| else |
| { |
| if (eErrCode != store_E_InvalidChecksum) |
| return eErrCode; |
| } |
| |
| // Check for complete truncation. |
| if (nSingle == 0) |
| { |
| // Free single indirect page. |
| eErrCode = rBIOS.free (nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| } |
| return store_E_None; |
| } |
| |
| /* |
| * store_truncate_Impl (double indirect page). |
| */ |
| static storeError store_truncate_Impl ( |
| sal_uInt32 nAddr, |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStorePageBIOS &rBIOS) |
| { |
| if (nAddr != STORE_PAGE_NULL) |
| { |
| // Load double indirect page. |
| OStoreIndirectionPageObject aDouble; |
| storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); |
| if (eErrCode == store_E_None) |
| { |
| // Truncate to 'nDouble', 'nSingle' pages. |
| eErrCode = aDouble.truncate (nDouble, nSingle, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| else |
| { |
| if (eErrCode != store_E_InvalidChecksum) |
| return eErrCode; |
| } |
| |
| // Check for complete truncation. |
| if ((nDouble + nSingle) == 0) |
| { |
| // Free double indirect page. |
| eErrCode = rBIOS.free (nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| } |
| return store_E_None; |
| } |
| |
| /* |
| * store_truncate_Impl (triple indirect page). |
| */ |
| static storeError store_truncate_Impl ( |
| sal_uInt32 nAddr, |
| sal_uInt16 nTriple, |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStorePageBIOS &rBIOS) |
| { |
| if (nAddr != STORE_PAGE_NULL) |
| { |
| // Load triple indirect page. |
| OStoreIndirectionPageObject aTriple; |
| storeError eErrCode = rBIOS.loadObjectAt (aTriple, nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate to 'nTriple', 'nDouble', 'nSingle' pages. |
| eErrCode = aTriple.truncate (nTriple, nDouble, nSingle, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Check for complete truncation. |
| if ((nTriple + nDouble + nSingle) == 0) |
| { |
| // Free triple indirect page. |
| eErrCode = rBIOS.free (nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| } |
| return store_E_None; |
| } |
| |
| /* |
| * loadOrCreate. |
| */ |
| storeError OStoreIndirectionPageObject::loadOrCreate ( |
| sal_uInt32 nAddr, |
| OStorePageBIOS & rBIOS) |
| { |
| if (nAddr == STORE_PAGE_NULL) |
| { |
| storeError eErrCode = construct<page>(rBIOS.allocator()); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| eErrCode = rBIOS.allocate (*this); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Save location pending at caller. |
| return store_E_Pending; |
| } |
| return rBIOS.loadObjectAt (*this, nAddr); |
| } |
| |
| /* |
| * guard. |
| */ |
| storeError OStoreIndirectionPageObject::guard (sal_uInt32 nAddr) |
| { |
| return PageHolderObject< page >::guard (m_xPage, nAddr); |
| } |
| |
| /* |
| * verify. |
| */ |
| storeError OStoreIndirectionPageObject::verify (sal_uInt32 nAddr) const |
| { |
| return PageHolderObject< page >::verify (m_xPage, nAddr); |
| } |
| |
| /* |
| * read (single indirect). |
| */ |
| storeError OStoreIndirectionPageObject::read ( |
| sal_uInt16 nSingle, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page const & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!(nSingle < nLimit)) |
| return store_E_InvalidAccess; |
| |
| // Obtain data page location. |
| sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| // Load data page and leave. |
| return rBIOS.loadObjectAt (rData, nAddr); |
| } |
| |
| /* |
| * read (double indirect). |
| */ |
| storeError OStoreIndirectionPageObject::read ( |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page const & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!((nDouble < nLimit) && (nSingle < nLimit))) |
| return store_E_InvalidAccess; |
| |
| // Check single indirect page location. |
| sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nDouble]); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| // Load single indirect page. |
| OStoreIndirectionPageObject aSingle; |
| storeError eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Read single indirect and leave. |
| return aSingle.read (nSingle, rData, rBIOS); |
| } |
| |
| /* |
| * read (triple indirect). |
| */ |
| storeError OStoreIndirectionPageObject::read ( |
| sal_uInt16 nTriple, |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page const & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) |
| return store_E_InvalidAccess; |
| |
| // Check double indirect page location. |
| sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nTriple]); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| // Load double indirect page. |
| OStoreIndirectionPageObject aDouble; |
| storeError eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Read double indirect and leave. |
| return aDouble.read (nDouble, nSingle, rData, rBIOS); |
| } |
| |
| /* |
| * write (single indirect). |
| */ |
| storeError OStoreIndirectionPageObject::write ( |
| sal_uInt16 nSingle, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!(nSingle < nLimit)) |
| return store_E_InvalidAccess; |
| |
| // Obtain data page location. |
| sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[nSingle]); |
| if (nAddr == STORE_PAGE_NULL) |
| { |
| // Allocate data page. |
| storeError eErrCode = rBIOS.allocate (rData); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Store data page location. |
| rPage.m_pData[nSingle] = store::htonl(rData.location()); |
| |
| // Save this page. |
| return rBIOS.saveObjectAt (*this, location()); |
| } |
| else |
| { |
| // Save data page. |
| return rBIOS.saveObjectAt (rData, nAddr); |
| } |
| } |
| |
| /* |
| * write (double indirect). |
| */ |
| storeError OStoreIndirectionPageObject::write ( |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!((nDouble < nLimit) && (nSingle < nLimit))) |
| return store_E_InvalidAccess; |
| |
| // Load or create single indirect page. |
| OStoreIndirectionPageObject aSingle; |
| storeError eErrCode = aSingle.loadOrCreate (store::ntohl(rPage.m_pData[nDouble]), rBIOS); |
| if (eErrCode != store_E_None) |
| { |
| if (eErrCode != store_E_Pending) |
| return eErrCode; |
| rPage.m_pData[nDouble] = store::htonl(aSingle.location()); |
| |
| eErrCode = rBIOS.saveObjectAt (*this, location()); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| |
| // Write single indirect and leave. |
| return aSingle.write (nSingle, rData, rBIOS); |
| } |
| |
| /* |
| * write (triple indirect). |
| */ |
| storeError OStoreIndirectionPageObject::write ( |
| sal_uInt16 nTriple, |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) |
| return store_E_InvalidAccess; |
| |
| // Load or create double indirect page. |
| OStoreIndirectionPageObject aDouble; |
| storeError eErrCode = aDouble.loadOrCreate (store::ntohl(rPage.m_pData[nTriple]), rBIOS); |
| if (eErrCode != store_E_None) |
| { |
| if (eErrCode != store_E_Pending) |
| return eErrCode; |
| rPage.m_pData[nTriple] = store::htonl(aDouble.location()); |
| |
| eErrCode = rBIOS.saveObjectAt (*this, location()); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| } |
| |
| // Write double indirect and leave. |
| return aDouble.write (nDouble, nSingle, rData, rBIOS); |
| } |
| |
| /* |
| * truncate (single indirect). |
| */ |
| storeError OStoreIndirectionPageObject::truncate ( |
| sal_uInt16 nSingle, |
| OStorePageBIOS & rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!(nSingle < nLimit)) |
| return store_E_InvalidAccess; |
| |
| // Truncate. |
| storeError eErrCode = store_E_None; |
| for (sal_uInt16 i = nLimit; i > nSingle; i--) |
| { |
| // Obtain data page location. |
| sal_uInt32 const nAddr = store::ntohl(rPage.m_pData[i - 1]); |
| if (nAddr != STORE_PAGE_NULL) |
| { |
| // Free data page. |
| eErrCode = rBIOS.free (nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Clear pointer to data page. |
| rPage.m_pData[i - 1] = STORE_PAGE_NULL; |
| touch(); |
| } |
| } |
| |
| // Check for modified page. |
| if (dirty()) |
| { |
| // Save this page. |
| eErrCode = rBIOS.saveObjectAt (*this, location()); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| /* |
| * truncate (double indirect). |
| */ |
| storeError OStoreIndirectionPageObject::truncate ( |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!((nDouble < nLimit) && (nSingle < nLimit))) |
| return store_E_InvalidAccess; |
| |
| // Truncate. |
| storeError eErrCode = store_E_None; |
| for (sal_uInt16 i = nLimit; i > nDouble + 1; i--) |
| { |
| // Truncate single indirect page to zero direct pages. |
| eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Clear pointer to single indirect page. |
| rPage.m_pData[i - 1] = STORE_PAGE_NULL; |
| touch(); |
| } |
| |
| // Truncate last single indirect page to 'nSingle' direct pages. |
| eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nDouble]), nSingle, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Check for complete truncation. |
| if (nSingle == 0) |
| { |
| // Clear pointer to last single indirect page. |
| rPage.m_pData[nDouble] = STORE_PAGE_NULL; |
| touch(); |
| } |
| |
| // Check for modified page. |
| if (dirty()) |
| { |
| // Save this page. |
| eErrCode = rBIOS.saveObjectAt (*this, location()); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| /* |
| * truncate (triple indirect). |
| */ |
| storeError OStoreIndirectionPageObject::truncate ( |
| sal_uInt16 nTriple, |
| sal_uInt16 nDouble, |
| sal_uInt16 nSingle, |
| OStorePageBIOS &rBIOS) |
| { |
| PageHolderObject< page > xImpl (m_xPage); |
| page & rPage = (*xImpl); |
| |
| // Check arguments. |
| sal_uInt16 const nLimit = rPage.capacityCount(); |
| if (!((nTriple < nLimit) && (nDouble < nLimit) && (nSingle < nLimit))) |
| return store_E_InvalidAccess; |
| |
| // Truncate. |
| storeError eErrCode = store_E_None; |
| for (sal_uInt16 i = nLimit; i > nTriple + 1; i--) |
| { |
| // Truncate double indirect page to zero single indirect pages. |
| eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[i - 1]), 0, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Clear pointer to double indirect page. |
| rPage.m_pData[i - 1] = STORE_PAGE_NULL; |
| touch(); |
| } |
| |
| // Truncate last double indirect page to 'nDouble', 'nSingle' pages. |
| eErrCode = store_truncate_Impl (store::ntohl(rPage.m_pData[nTriple]), nDouble, nSingle, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Check for complete truncation. |
| if ((nDouble + nSingle) == 0) |
| { |
| // Clear pointer to last double indirect page. |
| rPage.m_pData[nTriple] = STORE_PAGE_NULL; |
| touch(); |
| } |
| |
| // Check for modified page. |
| if (dirty()) |
| { |
| // Save this page. |
| eErrCode = rBIOS.saveObjectAt (*this, location()); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| /*======================================================================== |
| * |
| * OStoreDirectoryPageObject implementation. |
| * |
| *======================================================================*/ |
| /* |
| * guard. |
| */ |
| storeError OStoreDirectoryPageObject::guard (sal_uInt32 nAddr) |
| { |
| return PageHolderObject< page >::guard (m_xPage, nAddr); |
| } |
| |
| /* |
| * verify. |
| */ |
| storeError OStoreDirectoryPageObject::verify (sal_uInt32 nAddr) const |
| { |
| return PageHolderObject< page >::verify (m_xPage, nAddr); |
| // OLD: m_rPage.verifyVersion (STORE_MAGIC_DIRECTORYPAGE); |
| } |
| |
| /* |
| * scope (external data page; private). |
| */ |
| OStoreDirectoryPageData::ChunkScope |
| OStoreDirectoryPageObject::scope ( |
| sal_uInt32 nPage, |
| page::DataBlock::LinkDescriptor &rDescr) const |
| { |
| page const & rPage = PAGE(); |
| OStoreDirectoryDataBlock const & rDataBlock = rPage.m_aDataBlock; |
| |
| sal_uInt32 index0, index1, index2, index3; |
| |
| // direct. |
| sal_uInt32 nCount = rDataBlock.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 const nCapacity = indirect::capacityCount(rPage.m_aDescr); |
| nCount = rDataBlock.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; |
| OSL_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 = rDataBlock.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; |
| OSL_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 = rDataBlock.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; |
| OSL_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; |
| } |
| |
| #if 0 /* NYI */ |
| /* |
| * chunk (external data page). |
| */ |
| inode::ChunkDescriptor OStoreDirectoryPageObject::chunk (sal_uInt32 nOffset) |
| { |
| // @@@ INSUFFICIENT: NEED SCOPE AS WELL @@@ |
| sal_uInt32 nCapacity = m_rPage.capacity(); |
| if (nOffset < nCapacity) |
| // Internal scope (inode page). |
| return inode::ChunkDescriptor (nOffset, nCapacity); |
| else |
| // External scope (data page). |
| return inode::ChunkDescriptor (nOffset - nCapacity, data::capacity(m_rPage.m_aDescr)); |
| |
| inode::ChunkScope eScope = m_rPage.scope(nOffset); |
| if (eScope == inode::SCOPE_INTERNAL) |
| // Inode page (internal scope). |
| return inode::ChunkDescriptor (nOffset, m_rPage.capacity()); |
| else |
| // Data page (external scope). |
| return inode::ChunkDescriptor (nOffset - m_rPage.capacity(), data::capacity(m_rPage.m_aDescr)); |
| } |
| #endif /* NYI */ |
| |
| /* |
| * read (external data page). |
| */ |
| storeError OStoreDirectoryPageObject::read ( |
| sal_uInt32 nPage, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| // 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 const nAddr = directLink (aLink.m_nIndex0); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| eErrCode = rBIOS.loadObjectAt (rData, nAddr); |
| } |
| else if (eScope == page::SCOPE_SINGLE) |
| { |
| sal_uInt32 const nAddr = singleLink (aLink.m_nIndex1); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| OStoreIndirectionPageObject aSingle; |
| eErrCode = rBIOS.loadObjectAt (aSingle, nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| eErrCode = aSingle.read (aLink.m_nIndex0, rData, rBIOS); |
| } |
| else if (eScope == page::SCOPE_DOUBLE) |
| { |
| sal_uInt32 const nAddr = doubleLink (aLink.m_nIndex2); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| OStoreIndirectionPageObject aDouble; |
| eErrCode = rBIOS.loadObjectAt (aDouble, nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| eErrCode = aDouble.read (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); |
| } |
| else if (eScope == page::SCOPE_TRIPLE) |
| { |
| sal_uInt32 const nAddr = tripleLink (aLink.m_nIndex3); |
| if (nAddr == STORE_PAGE_NULL) |
| return store_E_NotExists; |
| |
| OStoreIndirectionPageObject aTriple; |
| eErrCode = rBIOS.loadObjectAt (aTriple, nAddr); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| eErrCode = aTriple.read (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); |
| } |
| else if (eScope == page::SCOPE_UNREACHABLE) |
| { |
| // Out of scope. |
| eErrCode = store_E_CantSeek; |
| } |
| else |
| { |
| // Unknown scope. |
| OSL_TRACE("OStoreDirectoryPageObject::get(): scope failed"); |
| eErrCode = store_E_Unknown; |
| } |
| |
| // Leave. |
| return eErrCode; |
| } |
| |
| /* |
| * write (external data page). |
| */ |
| storeError OStoreDirectoryPageObject::write ( |
| sal_uInt32 nPage, |
| OStoreDataPageObject &rData, |
| OStorePageBIOS &rBIOS) |
| { |
| // 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 const nAddr = directLink (aLink.m_nIndex0); |
| if (nAddr == STORE_PAGE_NULL) |
| { |
| // Allocate data page. |
| eErrCode = rBIOS.allocate (rData); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Store data page location. |
| directLink (aLink.m_nIndex0, rData.location()); |
| } |
| else |
| { |
| // Save data page. |
| eErrCode = rBIOS.saveObjectAt (rData, nAddr); |
| } |
| } |
| else if (eScope == page::SCOPE_SINGLE) |
| { |
| OStoreIndirectionPageObject aSingle; |
| eErrCode = aSingle.loadOrCreate (singleLink (aLink.m_nIndex1), rBIOS); |
| if (eErrCode != store_E_None) |
| { |
| if (eErrCode != store_E_Pending) |
| return eErrCode; |
| singleLink (aLink.m_nIndex1, aSingle.location()); |
| } |
| |
| eErrCode = aSingle.write (aLink.m_nIndex0, rData, rBIOS); |
| } |
| else if (eScope == page::SCOPE_DOUBLE) |
| { |
| OStoreIndirectionPageObject aDouble; |
| eErrCode = aDouble.loadOrCreate (doubleLink (aLink.m_nIndex2), rBIOS); |
| if (eErrCode != store_E_None) |
| { |
| if (eErrCode != store_E_Pending) |
| return eErrCode; |
| doubleLink (aLink.m_nIndex2, aDouble.location()); |
| } |
| |
| eErrCode = aDouble.write (aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); |
| } |
| else if (eScope == page::SCOPE_TRIPLE) |
| { |
| OStoreIndirectionPageObject aTriple; |
| eErrCode = aTriple.loadOrCreate (tripleLink (aLink.m_nIndex3), rBIOS); |
| if (eErrCode != store_E_None) |
| { |
| if (eErrCode != store_E_Pending) |
| return eErrCode; |
| tripleLink (aLink.m_nIndex3, aTriple.location()); |
| } |
| |
| eErrCode = aTriple.write (aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rData, rBIOS); |
| } |
| else if (eScope == page::SCOPE_UNREACHABLE) |
| { |
| // Out of scope. |
| eErrCode = store_E_CantSeek; |
| } |
| else |
| { |
| // Unknown scope. |
| OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed"); |
| eErrCode = store_E_Unknown; |
| } |
| |
| // Leave. |
| return eErrCode; |
| } |
| |
| /* |
| * truncate (external data page). |
| */ |
| storeError OStoreDirectoryPageObject::truncate ( |
| sal_uInt32 nPage, |
| OStorePageBIOS &rBIOS) |
| { |
| // 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, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate all double indirect pages. |
| eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate all single indirect pages. |
| eErrCode = truncate (page::SCOPE_SINGLE, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate direct pages, including 'aLink.m_nIndex0'. |
| eErrCode = truncate (eScope, aLink.m_nIndex0, rBIOS); |
| } |
| else if (eScope == page::SCOPE_SINGLE) |
| { |
| // Truncate all triple indirect pages. |
| eErrCode = truncate (page::SCOPE_TRIPLE, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate all double indirect pages. |
| eErrCode = truncate (page::SCOPE_DOUBLE, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate single indirect pages, downto 'aLink.m_nIndex1'. |
| eErrCode = truncate (eScope, aLink.m_nIndex1 + 1, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate last single indirect page to ... pages. |
| eErrCode = store_truncate_Impl (singleLink (aLink.m_nIndex1), aLink.m_nIndex0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Check for complete truncation. |
| if (aLink.m_nIndex0 == 0) |
| { |
| // 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, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate double indirect pages, downto 'aLink.m_nIndex2'. |
| eErrCode = truncate (eScope, aLink.m_nIndex2 + 1, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate last double indirect page to ... pages. |
| eErrCode = store_truncate_Impl ( |
| doubleLink (aLink.m_nIndex2), aLink.m_nIndex1, aLink.m_nIndex0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Check for complete truncation. |
| if ((aLink.m_nIndex1 + aLink.m_nIndex0) == 0) |
| { |
| // 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, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Truncate last triple indirect page to ... pages. |
| eErrCode = store_truncate_Impl ( |
| tripleLink (aLink.m_nIndex3), aLink.m_nIndex2, aLink.m_nIndex1, aLink.m_nIndex0, rBIOS); |
| if (eErrCode != store_E_None) |
| return eErrCode; |
| |
| // Check for complete truncation. |
| if ((aLink.m_nIndex2 + aLink.m_nIndex1 + aLink.m_nIndex0) == 0) |
| { |
| // 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. |
| OSL_TRACE("OStoreDirectoryPageObject::put(): scope failed"); |
| eErrCode = store_E_Unknown; |
| } |
| |
| // Leave. |
| return eErrCode; |
| } |
| |
| /* |
| * truncate (external data page scope; private). |
| */ |
| storeError OStoreDirectoryPageObject::truncate ( |
| page::ChunkScope eScope, |
| sal_uInt16 nRemain, |
| OStorePageBIOS &rBIOS) |
| { |
| OStoreDirectoryDataBlock const & rDataBlock = PAGE().m_aDataBlock; |
| |
| // Enter. |
| storeError eErrCode = store_E_None; |
| if (eScope == page::SCOPE_DIRECT) |
| { |
| // Truncate direct data pages. |
| sal_uInt16 i, n = rDataBlock.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. |
| eErrCode = rBIOS.free (nAddr); |
| if (eErrCode != store_E_None) |
| break; |
| |
| // Clear pointer to data page. |
| directLink (i - 1, STORE_PAGE_NULL); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| if (eScope == page::SCOPE_SINGLE) |
| { |
| // Truncate single indirect pages. |
| sal_uInt16 i, n = rDataBlock.singleCount(); |
| for (i = n; i > nRemain; i--) |
| { |
| // Truncate single indirect page to zero data pages. |
| eErrCode = store_truncate_Impl (singleLink (i - 1), 0, rBIOS); |
| if (eErrCode != store_E_None) |
| break; |
| |
| // Clear pointer to single indirect page. |
| singleLink (i - 1, STORE_PAGE_NULL); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| if (eScope == page::SCOPE_DOUBLE) |
| { |
| // Truncate double indirect pages. |
| sal_uInt16 i, n = rDataBlock.doubleCount(); |
| for (i = n; i > nRemain; i--) |
| { |
| // Truncate double indirect page to zero single indirect pages. |
| eErrCode = store_truncate_Impl (doubleLink (i - 1), 0, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| break; |
| |
| // Clear pointer to double indirect page. |
| doubleLink (i - 1, STORE_PAGE_NULL); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| if (eScope == page::SCOPE_TRIPLE) |
| { |
| // Truncate triple indirect pages. |
| sal_uInt16 i, n = rDataBlock.tripleCount(); |
| for (i = n; i > nRemain; i--) |
| { |
| // Truncate to zero double indirect pages. |
| eErrCode = store_truncate_Impl (tripleLink (i - 1), 0, 0, 0, rBIOS); |
| if (eErrCode != store_E_None) |
| break; |
| |
| // Clear pointer to triple indirect page. |
| tripleLink (i - 1, STORE_PAGE_NULL); |
| } |
| |
| // Done. |
| return eErrCode; |
| } |
| |
| // Invalid scope. |
| return store_E_InvalidAccess; |
| } |