LCOV - code coverage report
Current view: top level - backends/multi - multi_postlist.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 954b5873a738 Lines: 72 98 73.5 %
Date: 2019-06-30 05:20:33 Functions: 9 14 64.3 %
Branches: 42 76 55.3 %

           Branch data     Line data    Source code
       1                 :            : /** @file multi_postlist.cc
       2                 :            :  * @brief Class for merging PostList objects from subdatabases.
       3                 :            :  */
       4                 :            : /* Copyright (C) 2007,2008,2009,2011,2017,2018 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                 :            :  *
      14                 :            :  * You should have received a copy of the GNU General Public License
      15                 :            :  * along with this program; if not, write to the Free Software
      16                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      17                 :            :  */
      18                 :            : 
      19                 :            : #include <config.h>
      20                 :            : 
      21                 :            : #include "multi_postlist.h"
      22                 :            : 
      23                 :            : #include <xapian/database.h>
      24                 :            : 
      25                 :            : #include "api/leafpostlist.h"
      26                 :            : #include "backends/multi.h"
      27                 :            : #include "heap.h"
      28                 :            : #include "omassert.h"
      29                 :            : 
      30                 :            : #include <algorithm>
      31                 :            : #include <functional>
      32                 :            : 
      33                 :            : using namespace std;
      34                 :            : 
      35                 :        348 : MultiPostList::MultiPostList(size_t n_shards_,
      36                 :            :                              PostList** postlists_)
      37                 :        348 :     : current(0), n_shards(n_shards_), postlists(postlists_), docids_size(0), docids(NULL)
      38                 :            : {
      39                 :            :     try {
      40 [ +  - ][ +  - ]:        348 :         docids = new Xapian::docid[n_shards];
      41                 :          0 :     } catch (...) {
      42         [ #  # ]:          0 :         delete [] postlists;
      43                 :          0 :         throw;
      44                 :            :     }
      45                 :        348 : }
      46                 :            : 
      47                 :       1044 : MultiPostList::~MultiPostList()
      48                 :            : {
      49         [ +  + ]:       1044 :     while (n_shards)
      50         [ +  + ]:        696 :         delete postlists[--n_shards];
      51         [ +  - ]:        348 :     delete [] postlists;
      52         [ +  - ]:        348 :     delete [] docids;
      53         [ -  + ]:        696 : }
      54                 :            : 
      55                 :            : Xapian::doccount
      56                 :          0 : MultiPostList::get_termfreq_min() const
      57                 :            : {
      58                 :            :     // MultiPostList is only used by PostingIterator which should never call
      59                 :            :     // this method.
      60                 :            :     Assert(false);
      61                 :          0 :     return 0;
      62                 :            : }
      63                 :            : 
      64                 :            : Xapian::doccount
      65                 :          0 : MultiPostList::get_termfreq_max() const
      66                 :            : {
      67                 :            :     // MultiPostList is only used by PostingIterator which should never call
      68                 :            :     // this method.
      69                 :            :     Assert(false);
      70                 :          0 :     return 0;
      71                 :            : }
      72                 :            : 
      73                 :            : Xapian::doccount
      74                 :          0 : MultiPostList::get_termfreq_est() const
      75                 :            : {
      76                 :            :     // MultiPostList is only used by PostingIterator which should never call
      77                 :            :     // this method.
      78                 :            :     Assert(false);
      79                 :          0 :     return 0;
      80                 :            : }
      81                 :            : 
      82                 :            : Xapian::docid
      83                 :       6568 : MultiPostList::get_docid() const
      84                 :            : {
      85                 :       6568 :     return docids[0];
      86                 :            : }
      87                 :            : 
      88                 :            : Xapian::termcount
      89                 :        535 : MultiPostList::get_wdf() const
      90                 :            : {
      91                 :        535 :     return postlists[shard_number(docids[0], n_shards)]->get_wdf();
      92                 :            : }
      93                 :            : 
      94                 :            : double
      95                 :          0 : MultiPostList::get_weight(Xapian::termcount,
      96                 :            :                           Xapian::termcount) const
      97                 :            : {
      98                 :            :     // MultiPostList is only used by PostingIterator which should never call
      99                 :            :     // this method.
     100                 :            :     Assert(false);
     101                 :          0 :     return 0;
     102                 :            : }
     103                 :            : 
     104                 :            : bool
     105                 :       3848 : MultiPostList::at_end() const
     106                 :            : {
     107                 :       3848 :     return docids_size == 0;
     108                 :            : }
     109                 :            : 
     110                 :            : double
     111                 :          0 : MultiPostList::recalc_maxweight()
     112                 :            : {
     113                 :            :     // MultiPostList is only used by PostingIterator which should never call
     114                 :            :     // this method.
     115                 :            :     Assert(false);
     116                 :          0 :     return 0;
     117                 :            : }
     118                 :            : 
     119                 :            : PositionList*
     120                 :         55 : MultiPostList::open_position_list() const
     121                 :            : {
     122                 :         55 :     return postlists[current]->open_position_list();
     123                 :            : }
     124                 :            : 
     125                 :            : PostList*
     126                 :       3840 : MultiPostList::next(double w_min)
     127                 :            : {
     128         [ +  + ]:       3840 :     if (docids_size == 0) {
     129                 :            :         // Make a heap of the mapped docids so that the smallest is at the top
     130                 :            :         // of the heap.
     131                 :        348 :         size_t j = 0;
     132         [ +  + ]:       1044 :         for (size_t i = 0; i != n_shards; ++i) {
     133                 :        696 :             PostList* pl = postlists[i];
     134         [ -  + ]:        696 :             if (!pl) continue;
     135                 :        696 :             pl->next(w_min);
     136         [ +  + ]:        696 :             if (pl->at_end()) {
     137         [ +  - ]:        304 :                 delete pl;
     138                 :        304 :                 postlists[i] = NULL;
     139                 :            :             } else {
     140                 :        392 :                 docids[j++] = unshard(pl->get_docid(), i, n_shards);
     141                 :            :             }
     142                 :            :         }
     143                 :        348 :         docids_size = j;
     144                 :            :         Heap::make(docids, docids + docids_size,
     145         [ +  - ]:        348 :                    std::greater<Xapian::docid>());
     146                 :            :     } else {
     147                 :       3492 :         Xapian::docid old_did = docids[0];
     148                 :       3492 :         size_t shard = shard_number(old_did, n_shards);
     149                 :       3492 :         PostList* pl = postlists[shard];
     150                 :       3492 :         pl->next(w_min);
     151         [ +  + ]:       3492 :         if (pl->at_end()) {
     152                 :            :             Heap::pop(docids, docids + docids_size,
     153         [ +  - ]:        367 :                       std::greater<Xapian::docid>());
     154         [ +  - ]:        367 :             delete pl;
     155                 :        367 :             postlists[shard] = NULL;
     156                 :        367 :             --docids_size;
     157                 :            :         } else {
     158                 :       3125 :             docids[0] = unshard(pl->get_docid(), shard, n_shards);
     159                 :            :             Heap::replace(docids, docids + docids_size,
     160         [ +  - ]:       3125 :                           std::greater<Xapian::docid>());
     161                 :            :         }
     162                 :            :     }
     163                 :            : 
     164                 :       3840 :     return NULL;
     165                 :            : }
     166                 :            : 
     167                 :            : PostList*
     168                 :          8 : MultiPostList::skip_to(Xapian::docid did, double w_min)
     169                 :            : {
     170                 :          8 :     size_t j = 0;
     171         [ -  + ]:          8 :     if (docids_size == 0) {
     172                 :            :         // Make a heap of the mapped docids so that the smallest is at the top
     173                 :            :         // of the heap.
     174                 :          0 :         Xapian::docid shard_did = shard_docid(did, n_shards);
     175                 :          0 :         Xapian::doccount shard = shard_number(did, n_shards);
     176         [ #  # ]:          0 :         for (size_t i = 0; i != n_shards; ++i) {
     177                 :          0 :             PostList* pl = postlists[i];
     178         [ #  # ]:          0 :             if (!pl) continue;
     179                 :          0 :             pl->skip_to(shard_did + (i < shard), w_min);
     180         [ #  # ]:          0 :             if (pl->at_end()) {
     181         [ #  # ]:          0 :                 delete pl;
     182                 :          0 :                 postlists[i] = NULL;
     183                 :            :             } else {
     184                 :          0 :                 docids[j++] = unshard(pl->get_docid(), i, n_shards);
     185                 :            :             }
     186                 :            :         }
     187                 :            :     } else {
     188         [ +  + ]:          8 :         if (did <= docids[0])
     189                 :          1 :             return NULL;
     190                 :            :         // For a skip by < n_shards docids, pop/push may be more efficient than
     191                 :            :         // rebuilding the heap.  For now, always just rebuild the heap unless
     192                 :            :         // we're just skipping the next docid, in which case do next() instead.
     193         [ -  + ]:          7 :         if (did == docids[0] + 1)
     194                 :          0 :             return MultiPostList::next(w_min);
     195                 :          7 :         Xapian::docid shard_did = shard_docid(did, n_shards);
     196                 :          7 :         Xapian::doccount shard = shard_number(did, n_shards);
     197         [ +  + ]:         20 :         for (size_t i = 0; i != docids_size; ++i) {
     198                 :         13 :             Xapian::docid old_did = docids[i];
     199         [ +  - ]:         13 :             if (old_did < did) {
     200                 :         13 :                 size_t old_shard = shard_number(old_did, n_shards);
     201                 :         13 :                 PostList* pl = postlists[old_shard];
     202                 :         13 :                 pl->skip_to(shard_did + (old_shard < shard), w_min);
     203         [ +  + ]:         13 :                 if (pl->at_end()) {
     204         [ +  - ]:          3 :                     delete pl;
     205                 :          3 :                     postlists[old_shard] = NULL;
     206                 :            :                 } else {
     207                 :         13 :                     docids[j++] = unshard(pl->get_docid(), old_shard, n_shards);
     208                 :            :                 }
     209                 :            :             } else {
     210                 :          0 :                 docids[j++] = old_did;
     211                 :            :             }
     212                 :            :         }
     213                 :            :     }
     214                 :          7 :     docids_size = j;
     215         [ +  - ]:          7 :     Heap::make(docids, docids + docids_size, std::greater<Xapian::docid>());
     216                 :            : 
     217                 :          8 :     return NULL;
     218                 :            : }
     219                 :            : 
     220                 :            : std::string
     221                 :          3 : MultiPostList::get_description() const
     222                 :            : {
     223         [ +  - ]:          3 :     string desc = "MultiPostList(";
     224         [ +  + ]:          9 :     for (size_t i = 0; i != n_shards; ++i) {
     225         [ +  - ]:          6 :         if (postlists[i]) {
     226 [ +  - ][ +  - ]:          6 :             desc += postlists[i]->get_description();
     227         [ +  - ]:          6 :             desc += ',';
     228                 :            :         } else {
     229         [ #  # ]:          0 :             desc += "NULL,";
     230                 :            :         }
     231                 :            :     }
     232         [ +  - ]:          3 :     desc.back() = ')';
     233                 :          3 :     return desc;
     234                 :            : }

Generated by: LCOV version 1.11