LCOV - code coverage report
Current view: top level - backends/honey - honey_inverter.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 954b5873a738 Lines: 0 117 0.0 %
Date: 2019-06-30 05:20:33 Functions: 0 12 0.0 %
Branches: 0 144 0.0 %

           Branch data     Line data    Source code
       1                 :            : /** @file honey_inverter.cc
       2                 :            :  * @brief HoneyInverter class which "inverts the file".
       3                 :            :  */
       4                 :            : /* Copyright (C) 2009,2013 Olly Betts
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU General Public License as published by
       8                 :            :  * the Free Software Foundation; either version 2 of the License, or
       9                 :            :  * (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 USA
      19                 :            :  */
      20                 :            : 
      21                 :            : #include <config.h>
      22                 :            : 
      23                 :            : #include "honey_inverter.h"
      24                 :            : 
      25                 :            : #include "honey_positionlist.h"
      26                 :            : #include "honey_postlist.h"
      27                 :            : #include "honey_postlisttable.h"
      28                 :            : 
      29                 :            : #include "api/termlist.h"
      30                 :            : 
      31                 :            : #include <map>
      32                 :            : #include <string>
      33                 :            : 
      34                 :            : using namespace std;
      35                 :            : 
      36                 :            : void
      37                 :          0 : HoneyInverter::store_positions(const HoneyPositionTable& position_table,
      38                 :            :                                Xapian::docid did,
      39                 :            :                                const string& term,
      40                 :            :                                const Xapian::VecCOW<Xapian::termpos>& posvec,
      41                 :            :                                bool modifying)
      42                 :            : {
      43         [ #  # ]:          0 :     string s;
      44         [ #  # ]:          0 :     position_table.pack(s, posvec);
      45         [ #  # ]:          0 :     if (modifying) {
      46         [ #  # ]:          0 :         auto i = pos_changes.find(term);
      47         [ #  # ]:          0 :         if (i != pos_changes.end()) {
      48                 :          0 :             map<Xapian::docid, string>& m = i->second;
      49         [ #  # ]:          0 :             auto j = m.find(did);
      50         [ #  # ]:          0 :             if (j != m.end()) {
      51                 :            :                 // Update existing entry.
      52         [ #  # ]:          0 :                 swap(j->second, s);
      53                 :          0 :                 return;
      54                 :            :             }
      55                 :            :         }
      56         [ #  # ]:          0 :         const string& key = position_table.make_key(did, term);
      57 [ #  # ][ #  # ]:          0 :         string old_tag;
      58 [ #  # ][ #  # ]:          0 :         if (position_table.get_exact_entry(key, old_tag) && s == old_tag) {
         [ #  # ][ #  # ]
                 [ #  # ]
      59                 :            :             // Identical to existing entry on disk.
      60         [ #  # ]:          0 :             return;
      61                 :          0 :         }
      62                 :            :     }
      63 [ #  # ][ #  # ]:          0 :     set_positionlist(did, term, s);
      64                 :            : }
      65                 :            : 
      66                 :            : void
      67                 :          0 : HoneyInverter::set_positionlist(const HoneyPositionTable& position_table,
      68                 :            :                                 Xapian::docid did,
      69                 :            :                                 const string& term,
      70                 :            :                                 const Xapian::TermIterator& term_it,
      71                 :            :                                 bool modifying)
      72                 :            : {
      73                 :          0 :     auto ptr = term_it.internal->get_vec_termpos();
      74         [ #  # ]:          0 :     if (ptr) {
      75         [ #  # ]:          0 :         if (!ptr->empty()) {
      76                 :          0 :             store_positions(position_table, did, term, *ptr, modifying);
      77                 :          0 :             return;
      78                 :            :         }
      79                 :            :     } else {
      80         [ #  # ]:          0 :         Xapian::PositionIterator pos = term_it.positionlist_begin();
      81         [ #  # ]:          0 :         if (pos != term_it.positionlist_end()) {
      82                 :          0 :             Xapian::VecCOW<Xapian::termpos> posvec;
      83 [ #  # ][ #  # ]:          0 :             posvec.reserve(term_it.positionlist_count());
      84         [ #  # ]:          0 :             while (pos != term_it.positionlist_end()) {
      85 [ #  # ][ #  # ]:          0 :                 posvec.push_back(*pos);
      86         [ #  # ]:          0 :                 ++pos;
      87                 :            :             }
      88         [ #  # ]:          0 :             store_positions(position_table, did, term, posvec, modifying);
      89         [ #  # ]:          0 :             return;
      90                 :          0 :         }
      91                 :            :     }
      92                 :            :     // If we get here, the new position list was empty.
      93         [ #  # ]:          0 :     if (modifying)
      94                 :          0 :         delete_positionlist(did, term);
      95                 :            : }
      96                 :            : 
      97                 :            : void
      98                 :          0 : HoneyInverter::set_positionlist(Xapian::docid did,
      99                 :            :                                 const string& term,
     100                 :            :                                 const string& s)
     101                 :            : {
     102         [ #  # ]:          0 :     pos_changes.insert(make_pair(term, map<Xapian::docid, string>()))
     103 [ #  # ][ #  # ]:          0 :         .first->second[did] = s;
                 [ #  # ]
     104                 :          0 : }
     105                 :            : 
     106                 :            : void
     107                 :          0 : HoneyInverter::delete_positionlist(Xapian::docid did,
     108                 :            :                                    const string& term)
     109                 :            : {
     110         [ #  # ]:          0 :     set_positionlist(did, term, string());
     111                 :          0 : }
     112                 :            : 
     113                 :            : bool
     114                 :          0 : HoneyInverter::get_positionlist(Xapian::docid did,
     115                 :            :                                 const string& term,
     116                 :            :                                 string& s) const
     117                 :            : {
     118         [ #  # ]:          0 :     auto i = pos_changes.find(term);
     119         [ #  # ]:          0 :     if (i == pos_changes.end())
     120                 :          0 :         return false;
     121                 :          0 :     const map<Xapian::docid, string>& m = i->second;
     122         [ #  # ]:          0 :     auto j = m.find(did);
     123         [ #  # ]:          0 :     if (j == m.end())
     124                 :          0 :         return false;
     125         [ #  # ]:          0 :     s = j->second;
     126                 :          0 :     return true;
     127                 :            : }
     128                 :            : 
     129                 :            : bool
     130                 :          0 : HoneyInverter::has_positions(const HoneyPositionTable& position_table) const
     131                 :            : {
     132         [ #  # ]:          0 :     if (pos_changes.empty())
     133                 :          0 :         return !position_table.empty();
     134                 :            : 
     135                 :            :     // FIXME: Can we cheaply keep track of some things to make this more
     136                 :            :     // efficient?  E.g. how many sets and deletes we had in total perhaps.
     137                 :          0 :     honey_tablesize_t changes = 0;
     138 [ #  # ][ #  # ]:          0 :     for (auto i : pos_changes) {
     139                 :          0 :         const map<Xapian::docid, string>& m = i.second;
     140 [ #  # ][ #  # ]:          0 :         for (auto j : m) {
                 [ #  # ]
     141                 :          0 :             const string& s = j.second;
     142         [ #  # ]:          0 :             if (!s.empty())
     143                 :          0 :                 return true;
     144         [ #  # ]:          0 :             ++changes;
     145                 :          0 :         }
     146                 :          0 :     }
     147                 :            : 
     148                 :            :     // We have positions unless all the existing entries are removed.
     149                 :          0 :     return changes != position_table.get_entry_count();
     150                 :            : }
     151                 :            : 
     152                 :            : void
     153                 :          0 : HoneyInverter::flush_doclengths(HoneyPostListTable& table)
     154                 :            : {
     155                 :          0 :     table.merge_doclen_changes(doclen_changes);
     156                 :          0 :     doclen_changes.clear();
     157                 :          0 : }
     158                 :            : 
     159                 :            : void
     160                 :          0 : HoneyInverter::flush_post_list(HoneyPostListTable& table, const string& term)
     161                 :            : {
     162                 :          0 :     map<string, PostingChanges>::iterator i;
     163         [ #  # ]:          0 :     i = postlist_changes.find(term);
     164         [ #  # ]:          0 :     if (i == postlist_changes.end()) return;
     165                 :            : 
     166                 :            :     // Flush buffered changes for just this term's postlist.
     167                 :          0 :     table.merge_changes(term, i->second);
     168         [ #  # ]:          0 :     postlist_changes.erase(i);
     169                 :            : }
     170                 :            : 
     171                 :            : void
     172                 :          0 : HoneyInverter::flush_all_post_lists(HoneyPostListTable& table)
     173                 :            : {
     174                 :          0 :     map<string, PostingChanges>::const_iterator i;
     175         [ #  # ]:          0 :     for (i = postlist_changes.begin(); i != postlist_changes.end(); ++i) {
     176                 :          0 :         table.merge_changes(i->first, i->second);
     177                 :            :     }
     178                 :          0 :     postlist_changes.clear();
     179                 :          0 : }
     180                 :            : 
     181                 :            : void
     182                 :          0 : HoneyInverter::flush_post_lists(HoneyPostListTable& table, const string& pfx)
     183                 :            : {
     184         [ #  # ]:          0 :     if (pfx.empty())
     185                 :          0 :         return flush_all_post_lists(table);
     186                 :            : 
     187                 :          0 :     map<string, PostingChanges>::iterator i, begin, end;
     188         [ #  # ]:          0 :     begin = postlist_changes.lower_bound(pfx);
     189         [ #  # ]:          0 :     string pfxinc = pfx;
     190                 :            :     while (true) {
     191 [ #  # ][ #  # ]:          0 :         if (pfxinc.back() != '\xff') {
     192         [ #  # ]:          0 :             ++pfxinc.back();
     193         [ #  # ]:          0 :             end = postlist_changes.lower_bound(pfxinc);
     194                 :          0 :             break;
     195                 :            :         }
     196         [ #  # ]:          0 :         pfxinc.resize(pfxinc.size() - 1);
     197         [ #  # ]:          0 :         if (pfxinc.empty()) {
     198                 :          0 :             end = postlist_changes.end();
     199                 :          0 :             break;
     200                 :            :         }
     201                 :            :     }
     202                 :            : 
     203         [ #  # ]:          0 :     for (i = begin; i != end; ++i) {
     204                 :          0 :         table.merge_changes(i->first, i->second);
     205                 :            :     }
     206                 :            : 
     207                 :            :     // Erase all the entries in one go, as that's:
     208                 :            :     //  O(log(postlist_changes.size()) + O(number of elements removed)
     209         [ #  # ]:          0 :     postlist_changes.erase(begin, end);
     210                 :            : }
     211                 :            : 
     212                 :            : void
     213                 :          0 : HoneyInverter::flush(HoneyPostListTable& table)
     214                 :            : {
     215                 :          0 :     flush_doclengths(table);
     216                 :          0 :     flush_all_post_lists(table);
     217                 :          0 : }
     218                 :            : 
     219                 :            : void
     220                 :          0 : HoneyInverter::flush_pos_lists(HoneyPositionTable& table)
     221                 :            : {
     222 [ #  # ][ #  # ]:          0 :     for (auto i : pos_changes) {
     223                 :          0 :         const string& term = i.first;
     224                 :          0 :         const map<Xapian::docid, string>& m = i.second;
     225 [ #  # ][ #  # ]:          0 :         for (auto j : m) {
     226                 :          0 :             Xapian::docid did = j.first;
     227                 :          0 :             const string& s = j.second;
     228         [ #  # ]:          0 :             if (!s.empty())
     229         [ #  # ]:          0 :                 table.set_positionlist(did, term, s);
     230                 :            :             else
     231         [ #  # ]:          0 :                 table.delete_positionlist(did, term);
     232                 :          0 :         }
     233                 :          0 :     }
     234                 :          0 :     pos_changes.clear();
     235                 :          0 : }

Generated by: LCOV version 1.11