LCOV - code coverage report
Current view: top level - backends/honey - honey_values.h (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core eba1a2e3082b Lines: 53 57 93.0 %
Date: 2019-06-13 13:35:36 Functions: 15 15 100.0 %
Branches: 38 74 51.4 %

           Branch data     Line data    Source code
       1                 :            : /** @file honey_values.h
       2                 :            :  * @brief HoneyValueManager class
       3                 :            :  */
       4                 :            : /* Copyright (C) 2008,2009,2011,2018 Olly Betts
       5                 :            :  * Copyright (C) 2008 Lemur Consulting Ltd
       6                 :            :  *
       7                 :            :  * This program is free software; you can redistribute it and/or modify
       8                 :            :  * it under the terms of the GNU General Public License as published by
       9                 :            :  * the Free Software Foundation; either version 2 of the License, or
      10                 :            :  * (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This program is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            :  * GNU General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU General Public License
      18                 :            :  * along with this program; if not, write to the Free Software
      19                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #ifndef XAPIAN_INCLUDED_HONEY_VALUES_H
      23                 :            : #define XAPIAN_INCLUDED_HONEY_VALUES_H
      24                 :            : 
      25                 :            : #include "honey_cursor.h"
      26                 :            : #include "backends/valuestats.h"
      27                 :            : #include "pack.h"
      28                 :            : #include "xapian/error.h"
      29                 :            : #include "xapian/types.h"
      30                 :            : 
      31                 :            : #include <map>
      32                 :            : #include <memory>
      33                 :            : #include <string>
      34                 :            : 
      35                 :            : namespace Honey {
      36                 :            : 
      37                 :            : /** Generate a key for a value stream chunk. */
      38                 :            : inline std::string
      39                 :      49106 : make_valuechunk_key(Xapian::valueno slot, Xapian::docid last_did)
      40                 :            : {
      41         [ +  - ]:      49106 :     std::string key(1, '\0');
      42         [ +  + ]:      49106 :     if (slot < (Honey::KEY_VALUE_CHUNK_HI - Honey::KEY_VALUE_CHUNK) >> 3) {
      43         [ +  - ]:      49092 :         key += char(Honey::KEY_VALUE_CHUNK + slot);
      44                 :            :     } else {
      45         [ +  - ]:         14 :         key += char(Honey::KEY_VALUE_CHUNK_HI);
      46         [ +  - ]:         14 :         pack_uint_preserving_sort(key, slot);
      47                 :            :     }
      48         [ +  - ]:      49106 :     pack_uint_preserving_sort(key, last_did);
      49                 :      49106 :     return key;
      50                 :            : }
      51                 :            : 
      52                 :            : inline Xapian::docid
      53                 :      39501 : docid_from_key(Xapian::valueno required_slot, const std::string & key)
      54                 :            : {
      55                 :      39501 :     const char* p = key.data();
      56                 :      39501 :     const char* end = p + key.length();
      57 [ +  - ][ -  + ]:      39501 :     if (end - p < 3 || *p++ != '\0') {
                 [ -  + ]
      58                 :            :         // Not a value chunk key.
      59                 :          0 :         return 0;
      60                 :            :     }
      61                 :      39501 :     unsigned char code = *p++;
      62 [ +  - ][ +  + ]:      39501 :     if (code < Honey::KEY_VALUE_CHUNK || code > Honey::KEY_VALUE_CHUNK_HI) {
      63                 :            :         // Also not a value chunk key.
      64                 :         37 :         return 0;
      65                 :            :     }
      66                 :            : 
      67                 :            :     Xapian::valueno slot;
      68         [ +  - ]:      39464 :     if (code < Honey::KEY_VALUE_CHUNK_HI) {
      69                 :      39464 :         slot = code - Honey::KEY_VALUE_CHUNK;
      70                 :            :     } else {
      71         [ #  # ]:          0 :         if (!unpack_uint_preserving_sort(&p, end, &slot))
      72 [ #  # ][ #  # ]:          0 :             throw Xapian::DatabaseCorruptError("Bad value key");
                 [ #  # ]
      73                 :            :     }
      74                 :            :     // Fail if for a different slot.
      75         [ +  + ]:      39464 :     if (slot != required_slot) return 0;
      76                 :            :     Xapian::docid did;
      77         [ -  + ]:      39130 :     if (!unpack_uint_preserving_sort(&p, end, &did))
      78 [ #  # ][ #  # ]:          0 :         throw Xapian::DatabaseCorruptError("Bad value key");
                 [ #  # ]
      79                 :      39501 :     return did;
      80                 :            : }
      81                 :            : 
      82                 :            : inline std::string
      83                 :       3991 : make_valuestats_key(Xapian::valueno slot)
      84                 :            : {
      85         [ +  - ]:       3991 :     std::string key(1, '\0');
      86         [ +  + ]:       3991 :     if (slot <= 7) {
      87         [ +  - ]:       2284 :         key += char(Honey::KEY_VALUE_STATS + slot);
      88                 :            :     } else {
      89         [ +  - ]:       1707 :         key += char(Honey::KEY_VALUE_STATS + 7);
      90         [ +  - ]:       1707 :         pack_uint_preserving_sort(key, slot);
      91                 :            :     }
      92                 :       3991 :     return key;
      93                 :            : }
      94                 :            : 
      95                 :            : inline static std::string
      96                 :       4043 : encode_valuestats(Xapian::doccount freq,
      97                 :            :                   const std::string& lbound,
      98                 :            :                   const std::string& ubound)
      99                 :            : {
     100                 :       4043 :     std::string value;
     101         [ +  - ]:       4043 :     pack_uint(value, freq);
     102         [ +  - ]:       4043 :     pack_string(value, lbound);
     103                 :            :     // We don't store or count empty values, so neither of the bounds
     104                 :            :     // can be empty.  So we can safely store an empty upper bound when
     105                 :            :     // the bounds are equal.
     106 [ +  - ][ +  + ]:       4043 :     if (lbound != ubound) value += ubound;
                 [ +  - ]
     107                 :       4043 :     return value;
     108                 :            : }
     109                 :            : 
     110                 :            : }
     111                 :            : 
     112                 :            : namespace Xapian {
     113                 :            :     class Document;
     114                 :            : }
     115                 :            : 
     116                 :            : class HoneyPostListTable;
     117                 :            : class HoneyTermListTable;
     118                 :            : struct ValueStats;
     119                 :            : 
     120                 :        610 : class HoneyValueManager {
     121                 :            :     /** The value number for the most recently used value statistics.
     122                 :            :      *
     123                 :            :      *  Set to Xapian::BAD_VALUENO if no value statistics are currently
     124                 :            :      *  cached.
     125                 :            :      */
     126                 :            :     mutable Xapian::valueno mru_slot;
     127                 :            : 
     128                 :            :     /** The most recently used value statistics. */
     129                 :            :     mutable ValueStats mru_valstats;
     130                 :            : 
     131                 :            :     HoneyPostListTable& postlist_table;
     132                 :            : 
     133                 :            :     HoneyTermListTable& termlist_table;
     134                 :            : 
     135                 :            :     std::map<Xapian::docid, std::string> slots;
     136                 :            : 
     137                 :            :     std::map<Xapian::valueno, std::map<Xapian::docid, std::string>> changes;
     138                 :            : 
     139                 :            :     mutable std::unique_ptr<HoneyCursor> cursor;
     140                 :            : 
     141                 :            :     void add_value(Xapian::docid did, Xapian::valueno slot,
     142                 :            :                    const std::string & val);
     143                 :            : 
     144                 :            :     void remove_value(Xapian::docid did, Xapian::valueno slot);
     145                 :            : 
     146                 :            :     /** Move the cursor to the chunk containing did.
     147                 :            :      *
     148                 :            :      *  @return The last docid in the chunk, or 0 if off the end of the stream.
     149                 :            :      */
     150                 :            :     Xapian::docid get_chunk_containing_did(Xapian::valueno slot,
     151                 :            :                                            Xapian::docid did,
     152                 :            :                                            std::string &chunk) const;
     153                 :            : 
     154                 :            :     /** Get the statistics for value slot @a slot. */
     155                 :            :     void get_value_stats(Xapian::valueno slot) const;
     156                 :            : 
     157                 :            :     void get_value_stats(Xapian::valueno slot, ValueStats & stats) const;
     158                 :            : 
     159                 :            :   public:
     160                 :            :     /** Create a new HoneyValueManager object. */
     161                 :        305 :     HoneyValueManager(HoneyPostListTable& postlist_table_,
     162                 :            :                       HoneyTermListTable& termlist_table_)
     163                 :            :         : mru_slot(Xapian::BAD_VALUENO),
     164                 :            :           postlist_table(postlist_table_),
     165 [ +  - ][ +  - ]:        305 :           termlist_table(termlist_table_) { }
     166                 :            : 
     167                 :            :     // Merge in batched-up changes.
     168                 :            :     void merge_changes();
     169                 :            : 
     170                 :            :     std::string add_document(Xapian::docid did, const Xapian::Document& doc,
     171                 :            :                              std::map<Xapian::valueno, ValueStats>& val_stats);
     172                 :            : 
     173                 :            :     void delete_document(Xapian::docid did,
     174                 :            :                          std::map<Xapian::valueno, ValueStats>& val_stats);
     175                 :            : 
     176                 :            :     std::string replace_document(Xapian::docid did,
     177                 :            :                                  const Xapian::Document& doc,
     178                 :            :                                  std::map<Xapian::valueno, ValueStats>& val_stats);
     179                 :            : 
     180                 :            :     std::string get_value(Xapian::docid did, Xapian::valueno slot) const;
     181                 :            : 
     182                 :            :     void get_all_values(std::map<Xapian::valueno, std::string> & values,
     183                 :            :                         Xapian::docid did) const;
     184                 :            : 
     185                 :        239 :     Xapian::doccount get_value_freq(Xapian::valueno slot) const {
     186         [ +  + ]:        239 :         if (mru_slot != slot) get_value_stats(slot);
     187                 :        239 :         return mru_valstats.freq;
     188                 :            :     }
     189                 :            : 
     190                 :        335 :     std::string get_value_lower_bound(Xapian::valueno slot) const {
     191         [ +  + ]:        335 :         if (mru_slot != slot) get_value_stats(slot);
     192                 :        335 :         return mru_valstats.lower_bound;
     193                 :            :     }
     194                 :            : 
     195                 :        351 :     std::string get_value_upper_bound(Xapian::valueno slot) const {
     196         [ +  + ]:        351 :         if (mru_slot != slot) get_value_stats(slot);
     197                 :        351 :         return mru_valstats.upper_bound;
     198                 :            :     }
     199                 :            : 
     200                 :            :     /** Write the updated statistics to the table.
     201                 :            :      *
     202                 :            :      *  If the @a freq member of the statistics for a particular slot is 0, the
     203                 :            :      *  statistics for that slot will be cleared.
     204                 :            :      *
     205                 :            :      *  @param val_stats The statistics to set.
     206                 :            :      */
     207                 :            :     void set_value_stats(std::map<Xapian::valueno, ValueStats>& val_stats);
     208                 :            : 
     209                 :            :     void reset() {
     210                 :            :         /// Ignore any old cached valuestats.
     211                 :            :         mru_slot = Xapian::BAD_VALUENO;
     212                 :            :     }
     213                 :            : 
     214                 :            :     bool is_modified() const {
     215                 :            :         return !changes.empty();
     216                 :            :     }
     217                 :            : 
     218                 :            :     void cancel() {
     219                 :            :         // Discard batched-up changes.
     220                 :            :         slots.clear();
     221                 :            :         changes.clear();
     222                 :            :     }
     223                 :            : };
     224                 :            : 
     225                 :            : namespace Honey {
     226                 :            : 
     227                 :      73072 : class ValueChunkReader {
     228                 :            :     const char *p;
     229                 :            :     const char *end;
     230                 :            : 
     231                 :            :     Xapian::docid did;
     232                 :            : 
     233                 :            :     std::string value;
     234                 :            : 
     235                 :            :   public:
     236                 :            :     /// Create a ValueChunkReader which is already at_end().
     237                 :       6090 :     ValueChunkReader() : p(NULL) { }
     238                 :            : 
     239                 :      66982 :     ValueChunkReader(const char * p_, size_t len, Xapian::docid last_did) {
     240         [ +  - ]:      33491 :         assign(p_, len, last_did);
     241                 :      33491 :     }
     242                 :            : 
     243                 :            :     void assign(const char * p_, size_t len, Xapian::docid last_did);
     244                 :            : 
     245                 :     230142 :     bool at_end() const { return p == NULL; }
     246                 :            : 
     247                 :     146170 :     Xapian::docid get_docid() const { return did; }
     248                 :            : 
     249                 :     142110 :     const std::string & get_value() const { return value; }
     250                 :            : 
     251                 :            :     void next();
     252                 :            : 
     253                 :            :     void skip_to(Xapian::docid target);
     254                 :            : };
     255                 :            : 
     256                 :            : }
     257                 :            : 
     258                 :            : #endif // XAPIAN_INCLUDED_HONEY_VALUES_H

Generated by: LCOV version 1.11