LCOV - code coverage report
Current view: top level - backends/brass - brass_btreebase.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 193 234 82.5 %
Date: 2011-08-21 Functions: 17 21 81.0 %
Branches: 77 118 65.3 %

           Branch data     Line data    Source code
       1                 :            : /* brass_btreebase.cc: Btree base file implementation
       2                 :            :  *
       3                 :            :  * Copyright 1999,2000,2001 BrightStation PLC
       4                 :            :  * Copyright 2002,2003,2004,2006,2008,2009,2011 Olly Betts
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2 of the
       9                 :            :  * License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with this program; if not, write to the Free Software
      18                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      19                 :            :  * USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : 
      24                 :            : #include "safeerrno.h"
      25                 :            : #ifdef __WIN32__
      26                 :            : # include "msvc_posix_wrapper.h"
      27                 :            : #endif
      28                 :            : 
      29                 :            : #include <xapian/error.h>
      30                 :            : 
      31                 :            : #include "brass_btreebase.h"
      32                 :            : #include "io_utils.h"
      33                 :            : #include "omassert.h"
      34                 :            : #include "pack.h"
      35                 :            : #include "str.h"
      36                 :            : #include "utils.h"
      37                 :            : 
      38                 :            : #include <algorithm>
      39                 :            : #include <climits>
      40                 :            : #include <cstring>
      41                 :            : 
      42                 :            : using namespace std;
      43                 :            : 
      44                 :            : /************ Base file parameters ************/
      45                 :            : 
      46                 :            : /** This is the current description of the base file format:
      47                 :            :  *
      48                 :            :  * Numbers are (unless mentioned otherwise) stored in the variable
      49                 :            :  * length format used by pack_uint() - that is 7 bits at a time in
      50                 :            :  * a byte, starting with lower-order bits, and setting the high bit
      51                 :            :  * on all bytes before the last one.
      52                 :            :  *
      53                 :            :  * The format consists of a sequence of numbers in this order:
      54                 :            :  *
      55                 :            :  * REVISION
      56                 :            :  * FORMAT       will be = CURR_FORMAT for the current format.  If this value
      57                 :            :  *              higher then it is a different format which we
      58                 :            :  *              doesn't yet understand, so we bomb out.  If it's lower,
      59                 :            :  *              then it depends if we have backwards-compatibility code
      60                 :            :  *              implemented (we don't for format versions < 5).
      61                 :            :  * BLOCK_SIZE
      62                 :            :  * ROOT
      63                 :            :  * LEVEL
      64                 :            :  * BIT_MAP_SIZE
      65                 :            :  * ITEM_COUNT
      66                 :            :  * LAST_BLOCK
      67                 :            :  * HAVE_FAKEROOT
      68                 :            :  * REVISION2    A second copy of the revision number, for consistency checks.
      69                 :            :  * BITMAP       The bitmap.  This will be BIT_MAP_SIZE raw bytes.
      70                 :            :  * REVISION3    A third copy of the revision number, for consistency checks.
      71                 :            :  */
      72                 :            : #define CURR_FORMAT 5U
      73                 :            : 
      74                 :      32122 : BrassTable_base::BrassTable_base()
      75                 :            :         : revision(0),
      76                 :            :           block_size(0),
      77                 :            :           root(0),
      78                 :            :           level(0),
      79                 :            :           bit_map_size(0),
      80                 :            :           item_count(0),
      81                 :            :           last_block(0),
      82                 :            :           have_fakeroot(false),
      83                 :            :           sequential(false),
      84                 :            :           bit_map_low(0),
      85                 :            :           bit_map0(0),
      86                 :      32122 :           bit_map(0)
      87                 :            : {
      88                 :      32122 : }
      89                 :            : 
      90                 :          0 : BrassTable_base::BrassTable_base(const BrassTable_base &other)
      91                 :            :         : revision(other.revision),
      92                 :            :           block_size(other.block_size),
      93                 :            :           root(other.root),
      94                 :            :           level(other.level),
      95                 :            :           bit_map_size(other.bit_map_size),
      96                 :            :           item_count(other.item_count),
      97                 :            :           last_block(other.last_block),
      98                 :            :           have_fakeroot(other.have_fakeroot),
      99                 :            :           sequential(other.sequential),
     100                 :            :           bit_map_low(other.bit_map_low),
     101                 :            :           bit_map0(0),
     102                 :          0 :           bit_map(0)
     103                 :            : {
     104                 :            :     try {
     105                 :          0 :         bit_map0 = new byte[bit_map_size];
     106                 :          0 :         bit_map = new byte[bit_map_size];
     107                 :            : 
     108                 :          0 :         memcpy(bit_map0, other.bit_map0, bit_map_size);
     109                 :          0 :         memcpy(bit_map, other.bit_map, bit_map_size);
     110                 :          0 :     } catch (...) {
     111 [ #  # ][ #  # ]:          0 :         delete [] bit_map0;
     112 [ #  # ][ #  # ]:          0 :         delete [] bit_map;
     113                 :            :     }
     114                 :          0 : }
     115                 :            : 
     116                 :            : void
     117                 :       8793 : BrassTable_base::swap(BrassTable_base &other)
     118                 :            : {
     119                 :       8793 :     std::swap(revision, other.revision);
     120                 :       8793 :     std::swap(block_size, other.block_size);
     121                 :       8793 :     std::swap(root, other.root);
     122                 :       8793 :     std::swap(level, other.level);
     123                 :       8793 :     std::swap(bit_map_size, other.bit_map_size);
     124                 :       8793 :     std::swap(item_count, other.item_count);
     125                 :       8793 :     std::swap(last_block, other.last_block);
     126                 :       8793 :     std::swap(have_fakeroot, other.have_fakeroot);
     127                 :       8793 :     std::swap(sequential, other.sequential);
     128                 :       8793 :     std::swap(bit_map_low, other.bit_map_low);
     129                 :       8793 :     std::swap(bit_map0, other.bit_map0);
     130                 :       8793 :     std::swap(bit_map, other.bit_map);
     131                 :       8793 : }
     132                 :            : 
     133                 :      32122 : BrassTable_base::~BrassTable_base()
     134                 :            : {
     135 [ +  + ][ #  # ]:      32122 :     delete [] bit_map;
     136                 :      32122 :     bit_map = 0;
     137 [ +  + ][ #  # ]:      32122 :     delete [] bit_map0;
     138                 :      32122 :     bit_map0 = 0;
     139                 :      32122 : }
     140                 :            : 
     141                 :            : /** Do most of the error handling from unpack_uint() */
     142                 :            : static bool
     143                 :     156210 : do_unpack_uint(const char **start, const char *end,
     144                 :            :                uint4 *dest, string &err_msg, 
     145                 :            :                const string &basename,
     146                 :            :                const char *varname)
     147                 :            : {
     148                 :     156210 :     bool result = unpack_uint(start, end, dest);
     149         [ -  + ]:     156210 :     if (rare(!result)) {
     150                 :          0 :         err_msg += "Unable to read ";
     151                 :          0 :         err_msg += varname;
     152                 :          0 :         err_msg += " from ";
     153                 :          0 :         err_msg += basename;
     154                 :          0 :         err_msg += '\n';
     155                 :            :     }
     156                 :     156210 :     return result;
     157                 :            : }
     158                 :            : 
     159                 :            : static bool
     160                 :      15621 : do_unpack_uint(const char **start, const char *end,
     161                 :            :                brass_tablesize_t *dest, string &err_msg, 
     162                 :            :                const string &basename,
     163                 :            :                const char *varname)
     164                 :            : {
     165                 :      15621 :     bool result = unpack_uint(start, end, dest);
     166         [ -  + ]:      15621 :     if (rare(!result)) {
     167                 :          0 :         err_msg += "Unable to read ";
     168                 :          0 :         err_msg += varname;
     169                 :          0 :         err_msg += " from ";
     170                 :          0 :         err_msg += basename;
     171                 :          0 :         err_msg += '\n';
     172                 :            :     }
     173                 :      15621 :     return result;
     174                 :            : }
     175                 :            : 
     176                 :            : #define DO_UNPACK_UINT_ERRCHECK(start, end, var) \
     177                 :            : do { \
     178                 :            :     if (!do_unpack_uint(start, end, &var, err_msg, basename, #var)) { \
     179                 :            :         return false; \
     180                 :            :     } \
     181                 :            : } while(0)
     182                 :            : 
     183                 :            : /* How much of the base file to read at the first go (in bytes).
     184                 :            :  * This must be big enough that the base file without bitmap
     185                 :            :  * will fit in to this size with no problem.  Other than that
     186                 :            :  * it's fairly arbitrary, but shouldn't be big enough to cause
     187                 :            :  * serious memory problems!
     188                 :            :  */
     189                 :            : #define REASONABLE_BASE_SIZE 1024
     190                 :            : 
     191                 :            : bool
     192                 :      18055 : BrassTable_base::read(const string & name, char ch, bool read_bitmap,
     193                 :            :                       string &err_msg)
     194                 :            : {
     195                 :      18055 :     string basename = name + "base" + ch;
     196                 :            : #ifdef __WIN32__
     197                 :            :     int h = msvc_posix_open(basename.c_str(), O_RDONLY | O_BINARY);
     198                 :            : #else
     199                 :      18055 :     int h = open(basename.c_str(), O_RDONLY | O_BINARY);
     200                 :            : #endif
     201                 :            : 
     202         [ +  + ]:      18055 :     if (h == -1) {
     203                 :       2434 :         err_msg += "Couldn't open " + basename + ": " + strerror(errno) + "\n";
     204                 :       2434 :         return false;
     205                 :            :     }
     206                 :      15621 :     fdcloser closefd(h);
     207                 :            : 
     208                 :            :     char buf[REASONABLE_BASE_SIZE];
     209                 :            : 
     210                 :      15621 :     const char *start = buf;
     211                 :      15621 :     const char *end = buf + io_read(h, buf, REASONABLE_BASE_SIZE, 0);
     212                 :            : 
     213         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, revision);
     214                 :            :     uint4 format;
     215         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, format);
     216         [ -  + ]:      15621 :     if (format != CURR_FORMAT) {
     217                 :            :         err_msg += "Bad base file format " + str(format) + " in " +
     218                 :          0 :                     basename + "\n";
     219                 :          0 :         return false;
     220                 :            :     }
     221         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, block_size);
     222         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, root);
     223         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, level);
     224         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, bit_map_size);
     225         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, item_count);
     226         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, last_block);
     227                 :            :     uint4 have_fakeroot_;
     228         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, have_fakeroot_);
     229                 :      15621 :     have_fakeroot = have_fakeroot_;
     230                 :            : 
     231                 :            :     uint4 sequential_;
     232         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, sequential_);
     233                 :      15621 :     sequential = sequential_;
     234                 :            : 
     235 [ +  + ][ -  + ]:      15621 :     if (have_fakeroot && !sequential) {
     236                 :          0 :         sequential = true; // FIXME : work out why we need this...
     237                 :            :         /*
     238                 :            :         err_msg += "Corrupt base file, `" + basename + "':\n"
     239                 :            :                 "sequential must be set whenever have_fakeroot is set.\n" +
     240                 :            :                 "sequential=" + (sequential?"true":"false") +
     241                 :            :                 ", have_fakeroot=" + (have_fakeroot?"true":"false") + "\n";
     242                 :            :         return false;
     243                 :            :         */
     244                 :            :     }
     245                 :            : 
     246                 :            :     uint4 revision2;
     247         [ -  + ]:      15621 :     DO_UNPACK_UINT_ERRCHECK(&start, end, revision2);
     248         [ -  + ]:      15621 :     if (revision != revision2) {
     249                 :            :         err_msg += "Revision number mismatch in " +
     250                 :            :                 basename + ": " +
     251                 :          0 :                 str(revision) + " vs " + str(revision2) + "\n";
     252                 :          0 :         return false;
     253                 :            :     }
     254                 :            : 
     255                 :            :     /* It's ok to delete a zero pointer */
     256         [ +  + ]:      15621 :     delete [] bit_map0;
     257                 :      15621 :     bit_map0 = 0;
     258         [ +  + ]:      15621 :     delete [] bit_map;
     259                 :      15621 :     bit_map = 0;
     260                 :            : 
     261         [ +  + ]:      15621 :     if (!read_bitmap)
     262                 :      12566 :         return true;
     263                 :            : 
     264                 :       3055 :     bit_map0 = new byte[bit_map_size];
     265                 :       3055 :     bit_map = new byte[bit_map_size];
     266                 :            : 
     267                 :       3055 :     size_t n = end - start;
     268         [ -  + ]:       3055 :     if (n < bit_map_size) {
     269                 :          0 :         memcpy(bit_map0, start, n);
     270                 :            :         (void)io_read(h, reinterpret_cast<char *>(bit_map0) + n,
     271                 :          0 :                             bit_map_size - n, bit_map_size - n);
     272                 :          0 :         n = 0;
     273                 :            :     } else {
     274                 :       3055 :         memcpy(bit_map0, start, bit_map_size);
     275                 :       3055 :         n -= bit_map_size;
     276         [ +  - ]:       3055 :         if (n) memmove(buf, start + bit_map_size, n);
     277                 :            :     }
     278                 :       3055 :     memcpy(bit_map, bit_map0, bit_map_size);
     279                 :            : 
     280                 :       3055 :     start = buf;
     281                 :       3055 :     end = buf + n;
     282                 :       3055 :     end += io_read(h, buf + n, REASONABLE_BASE_SIZE - n, 0);
     283                 :            : 
     284                 :            :     uint4 revision3;
     285         [ -  + ]:       3055 :     if (!unpack_uint(&start, end, &revision3)) {
     286                 :            :         err_msg += "Couldn't read revision3 from base file " +
     287                 :          0 :         basename + "\n";
     288                 :          0 :         return false;
     289                 :            :     }
     290                 :            : 
     291         [ -  + ]:       3055 :     if (revision != revision3) {
     292                 :            :         err_msg += "Revision number mismatch in " +
     293                 :            :                 basename + ": " +
     294                 :          0 :                 str(revision) + " vs " + str(revision3) + "\n";
     295                 :          0 :         return false;
     296                 :            :     }
     297                 :            : 
     298         [ -  + ]:       3055 :     if (start != end) {
     299                 :          0 :         err_msg += "Junk at end of base file " + basename + "\n";
     300                 :          0 :         return false;
     301                 :            :     }
     302                 :            : 
     303                 :      18055 :     return true;
     304                 :            : }
     305                 :            : 
     306                 :            : void
     307                 :       2873 : BrassTable_base::write_to_file(const string &filename,
     308                 :            :                                char base_letter,
     309                 :            :                                const string &tablename,
     310                 :            :                                int changes_fd,
     311                 :            :                                const string * changes_tail)
     312                 :            : {
     313                 :       2873 :     calculate_last_block();
     314                 :            : 
     315                 :       2873 :     string buf;
     316                 :       2873 :     pack_uint(buf, revision);
     317                 :       2873 :     pack_uint(buf, CURR_FORMAT);
     318                 :       2873 :     pack_uint(buf, block_size);
     319                 :       2873 :     pack_uint(buf, static_cast<uint4>(root));
     320                 :       2873 :     pack_uint(buf, static_cast<uint4>(level));
     321                 :       2873 :     pack_uint(buf, static_cast<uint4>(bit_map_size));
     322                 :       2873 :     pack_uint(buf, item_count);
     323                 :       2873 :     pack_uint(buf, static_cast<uint4>(last_block));
     324                 :       2873 :     pack_uint(buf, have_fakeroot);
     325                 :       2873 :     pack_uint(buf, sequential);
     326                 :       2873 :     pack_uint(buf, revision);  // REVISION2
     327         [ +  + ]:       2873 :     if (bit_map_size > 0) {
     328                 :       1739 :         buf.append(reinterpret_cast<const char *>(bit_map), bit_map_size);
     329                 :            :     }
     330                 :       2873 :     pack_uint(buf, revision);  // REVISION3
     331                 :            : 
     332                 :            : #ifdef __WIN32__
     333                 :            :     int h = msvc_posix_open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY);
     334                 :            : #else
     335                 :       2873 :     int h = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
     336                 :            : #endif
     337         [ -  + ]:       2873 :     if (h < 0) {
     338                 :            :         string message = string("Couldn't open base ")
     339                 :          0 :                 + filename + " to write: " + strerror(errno);
     340                 :          0 :         throw Xapian::DatabaseOpeningError(message);
     341                 :            :     }
     342                 :       2873 :     fdcloser closefd(h);
     343                 :            : 
     344         [ +  + ]:       2873 :     if (changes_fd >= 0) {
     345                 :        228 :         string changes_buf;
     346                 :        228 :         pack_uint(changes_buf, 1u); // Indicate the item is a base file.
     347                 :        228 :         pack_string(changes_buf, tablename);
     348                 :        228 :         changes_buf += base_letter; // The base file letter.
     349                 :        228 :         pack_uint(changes_buf, buf.size());
     350                 :        228 :         io_write(changes_fd, changes_buf.data(), changes_buf.size());
     351                 :        228 :         io_write(changes_fd, buf.data(), buf.size());
     352         [ +  + ]:        228 :         if (changes_tail != NULL) {
     353                 :         62 :             io_write(changes_fd, changes_tail->data(), changes_tail->size());
     354                 :            :             // changes_tail is only specified for the final table, so sync.
     355                 :         62 :             io_sync(changes_fd);
     356                 :        228 :         }
     357                 :            :     }
     358                 :            : 
     359                 :       2873 :     io_write(h, buf.data(), buf.size());
     360                 :       2873 :     io_sync(h);
     361                 :       2873 : }
     362                 :            : 
     363                 :            : /*
     364                 :            :    block_free_at_start(B, n) is true iff (if and only if) block n was free at
     365                 :            :    the start of the transaction on the B-tree.
     366                 :            : */
     367                 :            : 
     368                 :            : bool
     369                 :     303915 : BrassTable_base::block_free_at_start(uint4 n) const
     370                 :            : {
     371                 :     303915 :     size_t i = n / CHAR_BIT;
     372                 :     303915 :     int bit = 0x1 << n % CHAR_BIT;
     373                 :     303915 :     return (bit_map0[i] & bit) == 0;
     374                 :            : }
     375                 :            : 
     376                 :            : /* free_block(B, n) causes block n to be marked free in the bit map.
     377                 :            :    B->bit_map_low is the lowest byte in the bit map known to have a free bit
     378                 :            :    set. Searching starts from there when looking for a free block.
     379                 :            : */
     380                 :            : 
     381                 :            : void
     382                 :       1915 : BrassTable_base::free_block(uint4 n)
     383                 :            : {
     384                 :       1915 :     uint4 i = n / CHAR_BIT;
     385                 :       1915 :     int bit = 0x1 << n % CHAR_BIT;
     386                 :       1915 :     bit_map[i] &= ~ bit;
     387                 :            : 
     388         [ +  + ]:       1915 :     if (bit_map_low > i)
     389         [ +  + ]:        492 :         if ((bit_map0[i] & bit) == 0) /* free at start */
     390                 :        106 :             bit_map_low = i;
     391                 :       1915 : }
     392                 :            : 
     393                 :            : /* extend(B) increases the size of the two bit maps in an obvious way.
     394                 :            :    The bitmap file grows and shrinks as the DB file grows and shrinks in
     395                 :            :    internal usage. But the DB file itself does not reduce in size, no matter
     396                 :            :    how many blocks are freed.
     397                 :            : */
     398                 :            : 
     399                 :            : #define BIT_MAP_INC 1000
     400                 :            :     /* increase the bit map by this number of bytes if it overflows */
     401                 :            : 
     402                 :            : void
     403                 :       2342 : BrassTable_base::extend_bit_map()
     404                 :            : {
     405                 :       2342 :     int n = bit_map_size + BIT_MAP_INC;
     406                 :       2342 :     byte *new_bit_map0 = 0;
     407                 :       2342 :     byte *new_bit_map = 0;
     408                 :            : 
     409                 :            :     try {
     410                 :       2342 :         new_bit_map0 = new byte[n];
     411                 :       2342 :         new_bit_map = new byte[n];
     412                 :            : 
     413                 :       2342 :         memcpy(new_bit_map0, bit_map0, bit_map_size);
     414                 :       2342 :         memset(new_bit_map0 + bit_map_size, 0, n - bit_map_size);
     415                 :            :         
     416                 :       2342 :         memcpy(new_bit_map, bit_map, bit_map_size);
     417                 :       2342 :         memset(new_bit_map + bit_map_size, 0, n - bit_map_size);
     418                 :          0 :     } catch (...) {
     419         [ #  # ]:          0 :         delete [] new_bit_map0;
     420         [ #  # ]:          0 :         delete [] new_bit_map;
     421                 :          0 :         throw;
     422                 :            :     }
     423         [ +  - ]:       2342 :     delete [] bit_map0;
     424                 :       2342 :     bit_map0 = new_bit_map0;
     425         [ +  - ]:       2342 :     delete [] bit_map;
     426                 :       2342 :     bit_map = new_bit_map;
     427                 :       2342 :     bit_map_size = n;
     428                 :       2342 : }
     429                 :            : 
     430                 :            : /* next_free_block(B) returns the number of the next available free block in
     431                 :            :    the bitmap, marking it as 'in use' before returning. More precisely, we get
     432                 :            :    a block that is both free now (in bit_map) and was free at the beginning of
     433                 :            :    the transaction on the B-tree (in bit_map0).
     434                 :            : 
     435                 :            :    Starting at bit_map_low we go up byte at a time until we find a byte with a
     436                 :            :    free (zero) bit, and then go up that byte bit at a time. If the bit map has
     437                 :            :    no free bits it is extended so that it will have.
     438                 :            : */
     439                 :            : 
     440                 :            : uint4
     441                 :      20806 : BrassTable_base::next_free_block()
     442                 :            : {
     443                 :            :     uint4 i;
     444                 :            :     int x;
     445                 :      23480 :     for (i = bit_map_low;; i++) {
     446         [ +  + ]:      23480 :         if (i >= bit_map_size) {
     447                 :       2342 :             extend_bit_map();
     448                 :            :         }
     449                 :      23480 :         x = bit_map0[i] | bit_map[i];
     450         [ +  + ]:      23480 :         if (x != UCHAR_MAX) break;
     451                 :            :     }
     452                 :      20806 :     uint4 n = i * CHAR_BIT;
     453                 :      20806 :     int d = 0x1;
     454         [ +  + ]:      83599 :     while ((x & d) != 0) { d <<= 1; n++; }
     455                 :      20806 :     bit_map[i] |= d;   /* set as 'in use' */
     456                 :      20806 :     bit_map_low = i;
     457         [ +  + ]:      20806 :     if (n > last_block) {
     458                 :      17634 :         last_block = n;
     459                 :            :     }
     460                 :      20806 :     return n;
     461                 :            : }
     462                 :            : 
     463                 :            : bool
     464                 :        646 : BrassTable_base::find_changed_block(uint4 * n)
     465                 :            : {
     466                 :            :     // Search for a block which was free at the start of the transaction, but
     467                 :            :     // isn't now.
     468         [ +  + ]:       1185 :     while ((*n) <= last_block) {
     469                 :        978 :         size_t offset = (*n) / CHAR_BIT;
     470                 :        978 :         int bit = 0x1 << (*n) % CHAR_BIT;
     471                 :            : 
     472 [ +  + ][ +  + ]:        978 :         if (((bit_map0[offset] & bit) == 0) && ((bit_map[offset] & bit) != 0)) {
     473                 :        439 :             return true;
     474                 :            :         }
     475                 :        539 :         ++(*n);
     476                 :            :     }
     477                 :            :     
     478                 :        646 :     return false;
     479                 :            : }
     480                 :            : 
     481                 :            : bool
     482                 :          3 : BrassTable_base::block_free_now(uint4 n)
     483                 :            : {
     484                 :          3 :     uint4 i = n / CHAR_BIT;
     485                 :          3 :     int bit = 0x1 << n % CHAR_BIT;
     486                 :          3 :     return (bit_map[i] & bit) == 0;
     487                 :            : }
     488                 :            : 
     489                 :            : void
     490                 :       3080 : BrassTable_base::calculate_last_block()
     491                 :            : {
     492         [ +  + ]:       3080 :     if (bit_map_size == 0) {
     493                 :       1134 :         last_block = 0;
     494                 :       1134 :         return;
     495                 :            :     }
     496                 :       1946 :     int i = bit_map_size - 1;
     497 [ +  + ][ +  + ]:    1113839 :     while (bit_map[i] == 0 && i > 0) {
                 [ +  + ]
     498                 :    1111893 :         i--;
     499                 :            :     }
     500                 :       1946 :     bit_map_size = i + 1;
     501                 :            : 
     502                 :       1946 :     int x = bit_map[i];
     503                 :            : 
     504                 :            :     /* Check for when there are no blocks */
     505         [ +  + ]:       1946 :     if (x == 0) {
     506                 :        102 :         last_block = 0;
     507                 :        102 :         return;
     508                 :            :     }
     509                 :       1844 :     uint4 n = (i + 1) * CHAR_BIT - 1;
     510                 :       1844 :     int d = 0x1 << (CHAR_BIT - 1);
     511         [ +  + ]:      12922 :     while ((x & d) == 0) { d >>= 1; n--; }
     512                 :            : 
     513                 :       3080 :     last_block = n;
     514                 :            : }
     515                 :            : 
     516                 :            : bool
     517                 :          3 : BrassTable_base::is_empty() const
     518                 :            : {
     519         [ +  + ]:          9 :     for (uint4 i = 0; i < bit_map_size; i++) {
     520         [ -  + ]:          6 :         if (bit_map[i] != 0) {
     521                 :          0 :             return false;
     522                 :            :         }
     523                 :            :     }
     524                 :          3 :     return true;
     525                 :            : }
     526                 :            : 
     527                 :            : void
     528                 :        102 : BrassTable_base::clear_bit_map()
     529                 :            : {
     530                 :        102 :     memset(bit_map, 0, bit_map_size);
     531                 :        102 : }
     532                 :            : 
     533                 :            : // We've commited, so "bitmap at start" needs to be reset to the current bitmap.
     534                 :            : void
     535                 :       1739 : BrassTable_base::commit()
     536                 :            : {
     537                 :       1739 :     memcpy(bit_map0, bit_map, bit_map_size);
     538                 :       1739 :     bit_map_low = 0;
     539                 :       1739 : }

Generated by: LCOV version 1.8