LCOV - code coverage report
Current view: top level - store/source - stortree.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 179 221 81.0 %
Date: 2012-08-25 Functions: 15 15 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 161 334 48.2 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : 
      21                 :            : #include "stortree.hxx"
      22                 :            : 
      23                 :            : #include "sal/types.h"
      24                 :            : #include "osl/diagnose.h"
      25                 :            : 
      26                 :            : #include "store/types.h"
      27                 :            : 
      28                 :            : #include "storbase.hxx"
      29                 :            : #include "storbios.hxx"
      30                 :            : 
      31                 :            : using namespace store;
      32                 :            : 
      33                 :            : /*========================================================================
      34                 :            :  *
      35                 :            :  * OStoreBTreeNodeData implementation.
      36                 :            :  *
      37                 :            :  *======================================================================*/
      38                 :            : /*
      39                 :            :  * OStoreBTreeNodeData.
      40                 :            :  */
      41                 :       7561 : OStoreBTreeNodeData::OStoreBTreeNodeData (sal_uInt16 nPageSize)
      42         [ +  + ]:      15122 :     : OStorePageData (nPageSize)
      43                 :            : {
      44                 :       7561 :     base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
      45                 :       7561 :     base::m_aDescr.m_nUsed  = store::htons(self::thePageSize); // usageCount(0)
      46                 :       7561 :     self::m_aGuard.m_nMagic = store::htonl(0); // depth(0)
      47                 :            : 
      48                 :       7561 :     sal_uInt16 const n = capacityCount();
      49                 :       7561 :     T const          t;
      50                 :            : 
      51         [ +  + ]:     230926 :     for (sal_uInt16 i = 1; i < n; i++)
      52                 :     223365 :         m_pData[i] = t;
      53                 :       7561 : }
      54                 :            : 
      55                 :            : /*
      56                 :            :  * find.
      57                 :            :  */
      58                 :    6315338 : sal_uInt16 OStoreBTreeNodeData::find (const T& t) const
      59                 :            : {
      60                 :    6315338 :     register sal_Int32 l = 0;
      61                 :    6315338 :     register sal_Int32 r = usageCount() - 1;
      62                 :            : 
      63         [ +  + ]:   26436781 :     while (l < r)
      64                 :            :     {
      65                 :   20774951 :         register sal_Int32 const m = ((l + r) >> 1);
      66                 :            : 
      67         [ +  + ]:   20774951 :         if (t.m_aKey == m_pData[m].m_aKey)
      68                 :     653508 :             return ((sal_uInt16)(m));
      69         [ +  + ]:   20121443 :         if (t.m_aKey < m_pData[m].m_aKey)
      70                 :    8515308 :             r = m - 1;
      71                 :            :         else
      72                 :   11606135 :             l = m + 1;
      73                 :            :     }
      74                 :            : 
      75                 :    5661830 :     sal_uInt16 const k = ((sal_uInt16)(r));
      76 [ +  - ][ +  + ]:    5661830 :     if ((k < capacityCount()) && (t.m_aKey < m_pData[k].m_aKey))
                 [ +  + ]
      77                 :    2420288 :         return(k - 1);
      78                 :            :     else
      79                 :    6315338 :         return(k);
      80                 :            : }
      81                 :            : 
      82                 :            : /*
      83                 :            :  * insert.
      84                 :            :  */
      85                 :      94121 : void OStoreBTreeNodeData::insert (sal_uInt16 i, const T& t)
      86                 :            : {
      87                 :      94121 :     sal_uInt16 const n = usageCount();
      88                 :      94121 :     sal_uInt16 const m = capacityCount();
      89 [ +  - ][ +  - ]:      94121 :     if ((n < m) && (i < m))
      90                 :            :     {
      91                 :            :         // shift right.
      92                 :      94121 :         memmove (&(m_pData[i + 1]), &(m_pData[i]), (n - i) * sizeof(T));
      93                 :            : 
      94                 :            :         // insert.
      95                 :      94121 :         m_pData[i] = t;
      96                 :      94121 :         usageCount (n + 1);
      97                 :            :     }
      98                 :      94121 : }
      99                 :            : 
     100                 :            : /*
     101                 :            :  * remove.
     102                 :            :  */
     103                 :         18 : void OStoreBTreeNodeData::remove (sal_uInt16 i)
     104                 :            : {
     105                 :         18 :     sal_uInt16 const n = usageCount();
     106         [ +  - ]:         18 :     if (i < n)
     107                 :            :     {
     108                 :            :         // shift left.
     109                 :         18 :         memmove (&(m_pData[i]), &(m_pData[i + 1]), (n - i - 1) * sizeof(T));
     110                 :            : 
     111                 :            :         // truncate.
     112                 :         18 :         m_pData[n - 1] = T();
     113                 :         18 :         usageCount (n - 1);
     114                 :            :     }
     115                 :         18 : }
     116                 :            : 
     117                 :            : /*
     118                 :            :  * split (left half copied from right half of left page).
     119                 :            :  */
     120                 :       1283 : void OStoreBTreeNodeData::split (const self& rPageL)
     121                 :            : {
     122                 :       1283 :     sal_uInt16 const h = capacityCount() / 2;
     123                 :       1283 :     memcpy (&(m_pData[0]), &(rPageL.m_pData[h]), h * sizeof(T));
     124                 :       1283 :     truncate (h);
     125                 :       1283 : }
     126                 :            : 
     127                 :            : /*
     128                 :            :  * truncate.
     129                 :            :  */
     130                 :       2566 : void OStoreBTreeNodeData::truncate (sal_uInt16 n)
     131                 :            : {
     132                 :       2566 :     sal_uInt16 const m = capacityCount();
     133                 :       2566 :     T const          t;
     134                 :            : 
     135         [ +  + ]:      41056 :     for (sal_uInt16 i = n; i < m; i++)
     136                 :      38490 :         m_pData[i] = t;
     137         [ +  - ]:       2566 :     usageCount (n);
     138                 :       2566 : }
     139                 :            : 
     140                 :            : /*========================================================================
     141                 :            :  *
     142                 :            :  * OStoreBTreeNodeObject implementation.
     143                 :            :  *
     144                 :            :  *======================================================================*/
     145                 :            : /*
     146                 :            :  * guard.
     147                 :            :  */
     148                 :     109261 : storeError OStoreBTreeNodeObject::guard (sal_uInt32 nAddr)
     149                 :            : {
     150                 :     109261 :     return PageHolderObject< page >::guard (m_xPage, nAddr);
     151                 :            : }
     152                 :            : 
     153                 :            : /*
     154                 :            :  * verify.
     155                 :            :  */
     156                 :      94730 : storeError OStoreBTreeNodeObject::verify (sal_uInt32 nAddr) const
     157                 :            : {
     158                 :      94730 :     return PageHolderObject< page >::verify (m_xPage, nAddr);
     159                 :            : }
     160                 :            : 
     161                 :            : /*
     162                 :            :  * split.
     163                 :            :  */
     164                 :       1283 : storeError OStoreBTreeNodeObject::split (
     165                 :            :     sal_uInt16                 nIndexL,
     166                 :            :     PageHolderObject< page > & rxPageL,
     167                 :            :     OStorePageBIOS           & rBIOS)
     168                 :            : {
     169         [ +  - ]:       1283 :     PageHolderObject< page > xPage (m_xPage);
     170         [ -  + ]:       1283 :     if (!xPage.is())
     171                 :          0 :         return store_E_InvalidAccess;
     172                 :            : 
     173                 :            :     // Check left page usage.
     174         [ -  + ]:       1283 :     if (!rxPageL.is())
     175                 :          0 :         return store_E_InvalidAccess;
     176 [ +  - ][ -  + ]:       1283 :     if (!rxPageL->querySplit())
     177                 :          0 :         return store_E_None;
     178                 :            : 
     179                 :            :     // Construct right page.
     180 [ +  - ][ +  - ]:       1283 :     PageHolderObject< page > xPageR;
         [ +  - ][ +  - ]
     181 [ +  - ][ -  + ]:       1283 :     if (!xPageR.construct (rBIOS.allocator()))
     182                 :          0 :         return store_E_OutOfMemory;
     183                 :            : 
     184                 :            :     // Split right page off left page.
     185 [ +  - ][ +  - ]:       1283 :     xPageR->split (*rxPageL);
                 [ +  - ]
     186 [ +  - ][ +  - ]:       1283 :     xPageR->depth (rxPageL->depth());
     187                 :            : 
     188                 :            :     // Allocate right page.
     189         [ +  - ]:       1283 :     self aNodeR (xPageR.get());
     190         [ +  - ]:       1283 :     storeError eErrCode = rBIOS.allocate (aNodeR);
     191         [ -  + ]:       1283 :     if (eErrCode != store_E_None)
     192                 :          0 :         return eErrCode;
     193                 :            : 
     194                 :            :     // Truncate left page.
     195 [ +  - ][ +  - ]:       1283 :     rxPageL->truncate (rxPageL->capacityCount() / 2);
                 [ +  - ]
     196                 :            : 
     197                 :            :     // Save left page.
     198         [ +  - ]:       1283 :     self aNodeL (rxPageL.get());
     199         [ +  - ]:       1283 :     eErrCode = rBIOS.saveObjectAt (aNodeL, aNodeL.location());
     200         [ -  + ]:       1283 :     if (eErrCode != store_E_None)
     201                 :          0 :         return eErrCode;
     202                 :            : 
     203                 :            :     // Insert right page.
     204         [ +  - ]:       1283 :     OStorePageLink aLink (xPageR->location());
     205 [ +  - ][ +  - ]:       1283 :     xPage->insert (nIndexL + 1, T(xPageR->m_pData[0].m_aKey, aLink));
                 [ +  - ]
     206                 :            : 
     207                 :            :     // Save this page and leave.
     208 [ +  - ][ +  - ]:       1283 :     return rBIOS.saveObjectAt (*this, location());
         [ +  - ][ +  - ]
                 [ +  - ]
     209                 :            : }
     210                 :            : 
     211                 :            : /*
     212                 :            :  * remove (down to leaf node, recursive).
     213                 :            :  */
     214                 :         18 : storeError OStoreBTreeNodeObject::remove (
     215                 :            :     sal_uInt16         nIndexL,
     216                 :            :     OStoreBTreeEntry & rEntryL,
     217                 :            :     OStorePageBIOS &   rBIOS)
     218                 :            : {
     219         [ +  - ]:         18 :     PageHolderObject< page > xImpl (m_xPage);
     220         [ +  - ]:         18 :     page & rPage = (*xImpl);
     221                 :            : 
     222                 :            :     // Check depth.
     223                 :         18 :     storeError eErrCode = store_E_None;
     224         [ -  + ]:         18 :     if (rPage.depth())
     225                 :            :     {
     226                 :            :         // Check link entry.
     227                 :          0 :         T const aEntryL (rPage.m_pData[nIndexL]);
     228         [ #  # ]:          0 :         if (!(rEntryL.compare (aEntryL) == T::COMPARE_EQUAL))
     229                 :          0 :             return store_E_InvalidAccess;
     230                 :            : 
     231                 :            :         // Load link node.
     232 [ #  # ][ #  # ]:          0 :         self aNodeL;
         [ #  # ][ #  # ]
     233         [ #  # ]:          0 :         eErrCode = rBIOS.loadObjectAt (aNodeL, aEntryL.m_aLink.location());
     234         [ #  # ]:          0 :         if (eErrCode != store_E_None)
     235                 :          0 :             return eErrCode;
     236                 :            : 
     237                 :            :         // Recurse: remove from link node.
     238         [ #  # ]:          0 :         eErrCode = aNodeL.remove (0, rEntryL, rBIOS);
     239         [ #  # ]:          0 :         if (eErrCode != store_E_None)
     240                 :          0 :             return eErrCode;
     241                 :            : 
     242                 :            :         // Check resulting link node usage.
     243         [ #  # ]:          0 :         PageHolderObject< page > xPageL (aNodeL.get());
     244 [ #  # ][ #  # ]:          0 :         if (xPageL->usageCount() == 0)
     245                 :            :         {
     246                 :            :             // Free empty link node.
     247 [ #  # ][ #  # ]:          0 :             eErrCode = rBIOS.free (xPageL->location());
     248         [ #  # ]:          0 :             if (eErrCode != store_E_None)
     249                 :          0 :                 return eErrCode;
     250                 :            : 
     251                 :            :             // Remove index.
     252         [ #  # ]:          0 :             rPage.remove (nIndexL);
     253                 :          0 :             touch();
     254                 :            :         }
     255                 :            :         else
     256                 :            :         {
     257                 :            : 
     258                 :            :             // Relink.
     259         [ #  # ]:          0 :             rPage.m_pData[nIndexL].m_aKey = xPageL->m_pData[0].m_aKey;
     260                 :          0 :             touch();
     261 [ #  # ][ #  # ]:          0 :         }
         [ #  # ][ #  # ]
     262                 :            :     }
     263                 :            :     else
     264                 :            :     {
     265                 :            :         // Check leaf entry.
     266         [ -  + ]:         18 :         if (!(rEntryL.compare (rPage.m_pData[nIndexL]) == T::COMPARE_EQUAL))
     267                 :          0 :             return store_E_NotExists;
     268                 :            : 
     269                 :            :         // Save leaf entry.
     270                 :         18 :         rEntryL = rPage.m_pData[nIndexL];
     271                 :            : 
     272                 :            :         // Remove leaf index.
     273         [ +  - ]:         18 :         rPage.remove (nIndexL);
     274                 :         18 :         touch();
     275                 :            :     }
     276                 :            : 
     277                 :            :     // Check for modified node.
     278         [ +  - ]:         18 :     if (dirty())
     279                 :            :     {
     280                 :            :         // Save this page.
     281         [ +  - ]:         18 :         eErrCode = rBIOS.saveObjectAt (*this, location());
     282                 :            :     }
     283                 :            : 
     284                 :            :     // Done.
     285         [ +  - ]:         18 :     return eErrCode;
     286                 :            : }
     287                 :            : 
     288                 :            : /*========================================================================
     289                 :            :  *
     290                 :            :  * OStoreBTreeRootObject implementation.
     291                 :            :  *
     292                 :            :  *======================================================================*/
     293                 :            : /*
     294                 :            :  * testInvariant.
     295                 :            :  * Precond: root node page loaded.
     296                 :            :  */
     297                 :    4958050 : bool OStoreBTreeRootObject::testInvariant (char const * message)
     298                 :            : {
     299                 :            :     OSL_PRECOND(m_xPage.get() != 0, "OStoreBTreeRootObject::testInvariant(): Null pointer");
     300                 :    4958050 :     bool result = ((m_xPage->location() - m_xPage->size()) == 0);
     301                 :            :     OSL_POSTCOND(result, message); (void) message;
     302                 :    4958050 :     return result;
     303                 :            : }
     304                 :            : 
     305                 :            : /*
     306                 :            :  * loadOrCreate.
     307                 :            :  */
     308                 :       6380 : storeError OStoreBTreeRootObject::loadOrCreate (
     309                 :            :     sal_uInt32       nAddr,
     310                 :            :     OStorePageBIOS & rBIOS)
     311                 :            : {
     312                 :       6380 :     storeError eErrCode = rBIOS.loadObjectAt (*this, nAddr);
     313         [ +  + ]:       6380 :     if (eErrCode != store_E_NotExists)
     314                 :        129 :         return eErrCode;
     315                 :            : 
     316                 :       6251 :     eErrCode = construct<page>(rBIOS.allocator());
     317         [ -  + ]:       6251 :     if (eErrCode != store_E_None)
     318                 :          0 :         return eErrCode;
     319                 :            : 
     320                 :       6251 :     eErrCode = rBIOS.allocate (*this);
     321         [ -  + ]:       6251 :     if (eErrCode != store_E_None)
     322                 :          0 :         return eErrCode;
     323                 :            : 
     324                 :            :     // Notify caller of the creation.
     325                 :       6251 :     (void) testInvariant("OStoreBTreeRootObject::loadOrCreate(): leave");
     326                 :       6380 :     return store_E_Pending;
     327                 :            : }
     328                 :            : 
     329                 :            : /*
     330                 :            :  * change.
     331                 :            :  */
     332                 :         27 : storeError OStoreBTreeRootObject::change (
     333                 :            :     PageHolderObject< page > & rxPageL,
     334                 :            :     OStorePageBIOS &           rBIOS)
     335                 :            : {
     336         [ +  - ]:         27 :     PageHolderObject< page > xPage (m_xPage);
     337                 :         27 :     (void) testInvariant("OStoreBTreeRootObject::change(): enter");
     338                 :            : 
     339                 :            :     // Save root location.
     340         [ +  - ]:         27 :     sal_uInt32 const nRootAddr = xPage->location();
     341                 :            : 
     342                 :            :     // Construct new root.
     343 [ -  + ][ +  - ]:         27 :     if (!rxPageL.construct (rBIOS.allocator()))
     344                 :          0 :         return store_E_OutOfMemory;
     345                 :            : 
     346                 :            :     // Save this as prev root.
     347         [ +  - ]:         27 :     storeError eErrCode = rBIOS.allocate (*this);
     348         [ -  + ]:         27 :     if (eErrCode != store_E_None)
     349                 :          0 :         return store_E_OutOfMemory;
     350                 :            : 
     351                 :            :     // Setup new root.
     352 [ +  - ][ +  - ]:         27 :     rxPageL->depth (xPage->depth() + 1);
     353 [ +  - ][ +  - ]:         27 :     rxPageL->m_pData[0] = xPage->m_pData[0];
     354 [ +  - ][ +  - ]:         27 :     rxPageL->m_pData[0].m_aLink = xPage->location();
     355 [ +  - ][ +  - ]:         27 :     rxPageL->usageCount(1);
     356                 :            : 
     357                 :            :     // Change root.
     358         [ +  - ]:         27 :     rxPageL.swap (xPage);
     359                 :            :     {
     360         [ +  - ]:         27 :         PageHolder tmp (xPage.get());
     361 [ +  - ][ +  - ]:         27 :         tmp.swap (m_xPage);
     362                 :            :     }
     363                 :            : 
     364                 :            :     // Save this as new root and finish.
     365         [ +  - ]:         27 :     eErrCode = rBIOS.saveObjectAt (*this, nRootAddr);
     366                 :         27 :     (void) testInvariant("OStoreBTreeRootObject::change(): leave");
     367         [ +  - ]:         27 :     return eErrCode;
     368                 :            : }
     369                 :            : 
     370                 :            : /*
     371                 :            :  * find_lookup (w/o split()).
     372                 :            :  * Precond: root node page loaded.
     373                 :            :  */
     374                 :    2386160 : storeError OStoreBTreeRootObject::find_lookup (
     375                 :            :     OStoreBTreeNodeObject & rNode,  // [out]
     376                 :            :     sal_uInt16 &            rIndex, // [out]
     377                 :            :     OStorePageKey const &   rKey,
     378                 :            :     OStorePageBIOS &        rBIOS)
     379                 :            : {
     380                 :            :     // Init node w/ root page.
     381                 :    2386160 :     (void) testInvariant("OStoreBTreeRootObject::find_lookup(): enter");
     382                 :            :     {
     383         [ +  - ]:    2386160 :         PageHolder tmp (m_xPage);
     384 [ +  - ][ +  - ]:    2386160 :         tmp.swap (rNode.get());
     385                 :            :     }
     386                 :            : 
     387                 :            :     // Setup BTree entry.
     388                 :    2386160 :     T const entry (rKey);
     389                 :            : 
     390                 :            :     // Check current page.
     391         [ +  - ]:    2386160 :     PageHolderObject< page > xPage (rNode.get());
     392 [ +  - ][ +  - ]:    6179546 :     for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
         [ +  - ][ +  - ]
                 [ +  + ]
     393                 :            :     {
     394                 :            :         // Find next page.
     395         [ +  - ]:    3793386 :         page const & rPage = (*xPage);
     396                 :    3793386 :         sal_uInt16 const i = rPage.find(entry);
     397                 :    3793386 :         sal_uInt16 const n = rPage.usageCount();
     398         [ -  + ]:    3793386 :         if (!(i < n))
     399                 :            :         {
     400                 :            :             // Path to entry not exists (Must not happen(?)).
     401                 :          0 :             return store_E_NotExists;
     402                 :            :         }
     403                 :            : 
     404                 :            :         // Check address.
     405                 :    3793386 :         sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
     406         [ -  + ]:    3793386 :         if (nAddr == STORE_PAGE_NULL)
     407                 :            :         {
     408                 :            :             // Path to entry not exists (Must not happen(?)).
     409                 :          0 :             return store_E_NotExists;
     410                 :            :         }
     411                 :            : 
     412                 :            :         // Load next page.
     413         [ +  - ]:    3793386 :         storeError eErrCode = rBIOS.loadObjectAt (rNode, nAddr);
     414         [ -  + ]:    3793386 :         if (eErrCode != store_E_None)
     415                 :          0 :             return eErrCode;
     416                 :            :     }
     417                 :            : 
     418                 :            :     // Find index.
     419         [ +  - ]:    2386160 :     page const & rPage = (*xPage);
     420                 :    2386160 :     rIndex = rPage.find(entry);
     421         [ -  + ]:    2386160 :     if (!(rIndex < rPage.usageCount()))
     422                 :          0 :         return store_E_NotExists;
     423                 :            : 
     424                 :            :     // Compare entry.
     425                 :    2386160 :     T::CompareResult eResult = entry.compare(rPage.m_pData[rIndex]);
     426                 :            :     OSL_POSTCOND(eResult != T::COMPARE_LESS, "store::BTreeRoot::find_lookup(): sort error");
     427         [ -  + ]:    2386160 :     if (eResult == T::COMPARE_LESS)
     428                 :          0 :         return store_E_Unknown;
     429                 :            : 
     430                 :            :     // Greater or Equal.
     431                 :    2386160 :     (void) testInvariant("OStoreBTreeRootObject::find_lookup(): leave");
     432         [ +  - ]:    2386160 :     return store_E_None;
     433                 :            : }
     434                 :            : 
     435                 :            : /*
     436                 :            :  * find_insert (possibly with split()).
     437                 :            :  * Precond: root node page loaded.
     438                 :            :  */
     439                 :      92838 : storeError OStoreBTreeRootObject::find_insert (
     440                 :            :     OStoreBTreeNodeObject & rNode,  // [out]
     441                 :            :     sal_uInt16 &            rIndex, // [out]
     442                 :            :     OStorePageKey const &   rKey,
     443                 :            :     OStorePageBIOS &        rBIOS)
     444                 :            : {
     445                 :      92838 :     (void) testInvariant("OStoreBTreeRootObject::find_insert(): enter");
     446                 :            : 
     447                 :            :     // Check for RootNode split.
     448         [ +  - ]:      92838 :     PageHolderObject< page > xRoot (m_xPage);
     449 [ +  - ][ +  + ]:      92838 :     if (xRoot->querySplit())
     450                 :            :     {
     451 [ +  - ][ +  - ]:         27 :         PageHolderObject< page > xPageL;
         [ +  - ][ +  - ]
     452                 :            : 
     453                 :            :         // Change root.
     454         [ +  - ]:         27 :         storeError eErrCode = change (xPageL, rBIOS);
     455         [ -  + ]:         27 :         if (eErrCode != store_E_None)
     456                 :          0 :             return eErrCode;
     457                 :            : 
     458                 :            :         // Split left page (prev root).
     459         [ +  - ]:         27 :         eErrCode = split (0, xPageL, rBIOS);
     460         [ -  + ]:         27 :         if (eErrCode != store_E_None)
     461 [ +  - ][ +  - ]:         27 :             return eErrCode;
     462                 :            :     }
     463                 :            : 
     464                 :            :     // Init node w/ root page.
     465                 :            :     {
     466         [ +  - ]:      92838 :         PageHolder tmp (m_xPage);
     467 [ +  - ][ +  - ]:      92838 :         tmp.swap (rNode.get());
     468                 :            :     }
     469                 :            : 
     470                 :            :     // Setup BTree entry.
     471                 :      92838 :     T const entry (rKey);
     472                 :            : 
     473                 :            :     // Check current Page.
     474         [ +  - ]:      92838 :     PageHolderObject< page > xPage (rNode.get());
     475 [ +  - ][ +  - ]:     135774 :     for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
         [ +  - ][ +  - ]
                 [ +  + ]
     476                 :            :     {
     477                 :            :         // Find next page.
     478         [ +  - ]:      42936 :         page const & rPage = (*xPage);
     479                 :      42936 :         sal_uInt16 const i = rPage.find (entry);
     480                 :      42936 :         sal_uInt16 const n = rPage.usageCount();
     481         [ -  + ]:      42936 :         if (!(i < n))
     482                 :            :         {
     483                 :            :             // Path to entry not exists (Must not happen(?)).
     484                 :          0 :             return store_E_NotExists;
     485                 :            :         }
     486                 :            : 
     487                 :            :         // Check address.
     488                 :      42936 :         sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
     489         [ -  + ]:      42936 :         if (nAddr == STORE_PAGE_NULL)
     490                 :            :         {
     491                 :            :             // Path to entry not exists (Must not happen(?)).
     492                 :          0 :             return store_E_NotExists;
     493                 :            :         }
     494                 :            : 
     495                 :            :         // Load next page.
     496 [ +  - ][ +  - ]:      42936 :         OStoreBTreeNodeObject aNext;
         [ +  - ][ +  - ]
     497         [ +  - ]:      42936 :         storeError eErrCode = rBIOS.loadObjectAt (aNext, nAddr);
     498         [ -  + ]:      42936 :         if (eErrCode != store_E_None)
     499                 :          0 :             return eErrCode;
     500                 :            : 
     501                 :            :         // Check for next node split.
     502         [ +  - ]:      42936 :         PageHolderObject< page > xNext (aNext.get());
     503 [ +  - ][ +  + ]:      42936 :         if (xNext->querySplit())
     504                 :            :         {
     505                 :            :             // Split next node.
     506         [ +  - ]:       1256 :             eErrCode = rNode.split (i, xNext, rBIOS);
     507         [ -  + ]:       1256 :             if (eErrCode != store_E_None)
     508                 :          0 :                 return eErrCode;
     509                 :            : 
     510                 :            :             // Restart.
     511                 :       1256 :             continue;
     512                 :            :         }
     513                 :            : 
     514                 :            :         // Let next page be current.
     515         [ +  - ]:      41680 :         PageHolder tmp (aNext.get());
     516         [ +  - ]:      41680 :         tmp.swap (rNode.get());
     517 [ +  - ][ +  - ]:      42936 :     }
              [ -  +  + ]
                 [ +  - ]
              [ +  -  + ]
     518                 :            : 
     519                 :            :     // Find index.
     520         [ +  - ]:      92838 :     page const & rPage = (*xPage);
     521                 :      92838 :     rIndex = rPage.find(entry);
     522         [ +  - ]:      92838 :     if (rIndex < rPage.usageCount())
     523                 :            :     {
     524                 :            :         // Compare entry.
     525                 :      92838 :         T::CompareResult result = entry.compare (rPage.m_pData[rIndex]);
     526                 :            :         OSL_POSTCOND(result != T::COMPARE_LESS, "store::BTreeRoot::find_insert(): sort error");
     527         [ -  + ]:      92838 :         if (result == T::COMPARE_LESS)
     528                 :          0 :             return store_E_Unknown;
     529                 :            : 
     530         [ +  + ]:      92838 :         if (result == T::COMPARE_EQUAL)
     531                 :       6251 :             return store_E_AlreadyExists;
     532                 :            :     }
     533                 :            : 
     534                 :            :     // Greater or not (yet) existing.
     535                 :      86587 :     (void) testInvariant("OStoreBTreeRootObject::find_insert(): leave");
     536 [ +  - ][ +  - ]:      92838 :     return store_E_None;
     537                 :            : }
     538                 :            : 
     539                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10