Ticket #38: xapian-remote-postlist.patch

File xapian-remote-postlist.patch, 10.1 kB (added by richard, 21 months ago)

Basic implementation of remote database postlists

  • net/remoteserver.cc

     
    139139{ 
    140140    while (true) { 
    141141        try { 
     142            /* This list needs to be kept in the same order as the list of 
     143             * message types in "remoteprotocol.h". Note that messages at the 
     144             * end of the list in "remoteprotocol.h" can be omitted if they 
     145             * don't correspond to dispatch actions. 
     146             */ 
    142147            static const dispatch_func dispatch[] = { 
    143148                &RemoteServer::msg_allterms, 
    144149                &RemoteServer::msg_collfreq, 
     
    150155                &RemoteServer::msg_query, 
    151156                &RemoteServer::msg_termlist, 
    152157                &RemoteServer::msg_positionlist, 
     158                &RemoteServer::msg_postlist, 
    153159                &RemoteServer::msg_reopen, 
    154160                &RemoteServer::msg_update, 
    155161                &RemoteServer::msg_adddocument, 
     
    223229    Xapian::docid did = decode_length(&p, p_end, false); 
    224230    string term(p, p_end - p); 
    225231 
    226     int N = 0; 
    227232    Xapian::termpos lastpos = static_cast<Xapian::termpos>(-1); 
    228233    const Xapian::PositionIterator end = db->positionlist_end(did, term); 
    229234    for (Xapian::PositionIterator i = db->positionlist_begin(did, term); 
     
    231236        Xapian::termpos pos = *i; 
    232237        send_message(REPLY_POSITIONLIST, encode_length(pos - lastpos - 1)); 
    233238        lastpos = pos; 
    234         ++N; 
    235239    } 
    236240 
    237241    send_message(REPLY_DONE, ""); 
    238242} 
    239243 
    240244void 
     245RemoteServer::msg_postlist(const string &message) 
     246{ 
     247    const char *p = message.data(); 
     248    const char *p_end = p + message.size(); 
     249    string term(p, p_end - p); 
     250 
     251    Xapian::doccount termfreq = db->get_termfreq(term); 
     252    send_message(REPLY_POSTLISTSTART, encode_length(termfreq)); 
     253 
     254    Xapian::docid lastdocid = static_cast<Xapian::termpos>(0); 
     255    const Xapian::PostingIterator end = db->postlist_end(term); 
     256    for (Xapian::PostingIterator i = db->postlist_begin(term); 
     257         i != end; ++i) { 
     258 
     259        Xapian::docid newdocid = *i; 
     260        string reply = encode_length(newdocid - lastdocid - 1); 
     261        reply += encode_length(i.get_wdf()); 
     262        // FIXME: get_doclength should always return an integer, but 
     263        // Xapian::doclength is a double... 
     264        reply += serialise_double(i.get_doclength()); 
     265 
     266        send_message(REPLY_POSTLISTITEM, reply); 
     267        lastdocid = newdocid; 
     268    } 
     269 
     270    send_message(REPLY_DONE, ""); 
     271} 
     272 
     273void 
    241274RemoteServer::msg_reopen(const string & msg) 
    242275{ 
    243276    db->reopen(); 
  • common/remote-database.h

     
    3333} 
    3434 
    3535class Stats; 
     36class NetworkPostList; 
    3637 
    3738/** RemoteDatabase is the baseclass for remote database implementations. 
    3839 * 
     
    161162 
    162163    LeafPostList * do_open_post_list(const string & tname) const; 
    163164 
     165    void read_post_list(const string &term, NetworkPostList & pl) const; 
     166 
    164167    PositionList * open_position_list(Xapian::docid did, 
    165168                                      const string & tname) const; 
    166169 
  • common/remoteprotocol.h

     
    2828// 24: Support for OP_VALUE_RANGE in query serialisation 
    2929// 25: Support for delete_document and replace_document with unique term 
    3030// 26: Tweak delete_document with unique term; delta encode rset and termpos 
    31 #define XAPIAN_REMOTE_PROTOCOL_VERSION 26 
     31// 27: Support for postlists (always passes the whole list across) 
     32#define XAPIAN_REMOTE_PROTOCOL_VERSION 27 
    3233 
    3334/// Message types (client -> server). 
    3435enum message_type { 
     
    4243    MSG_QUERY,                  // Run Query 
    4344    MSG_TERMLIST,               // Get TermList 
    4445    MSG_POSITIONLIST,           // Get PositionList 
     46    MSG_POSTLIST,               // Get PostList 
    4547    MSG_REOPEN,                 // Reopen 
    4648    MSG_UPDATE,                 // Get Updated DocCount and AvLength 
    4749    MSG_ADDDOCUMENT,            // Add Document 
     
    7274    REPLY_STATS,                // Stats 
    7375    REPLY_TERMLIST,             // Get Termlist 
    7476    REPLY_POSITIONLIST,         // Get PositionList 
     77    REPLY_POSTLISTSTART,        // Start of a postlist 
     78    REPLY_POSTLISTITEM,         // Item in body of a postlist 
    7579    REPLY_UPDATE,               // Get Updated DocCount and AvLength 
    7680    REPLY_VALUE,                // Document Value 
    7781    REPLY_ADDDOCUMENT,          // Add Document 
  • common/remoteserver.h

     
    103103    // get termlist 
    104104    void msg_termlist(const std::string & message); 
    105105 
     106    // get postlist 
     107    void msg_postlist(const std::string & message); 
     108 
    106109    // get positionlist 
    107110    void msg_positionlist(const std::string &message); 
    108111 
  • backends/remote/remote-database.cc

     
    2626#include <xapian/error.h> 
    2727 
    2828#include "inmemory_positionlist.h" 
     29#include "net_postlist.h" 
    2930#include "net_termlist.h" 
    3031#include "net_document.h" 
    3132#include "omassert.h" 
     
    173174} 
    174175 
    175176LeafPostList * 
    176 RemoteDatabase::do_open_post_list(const string &) const 
     177RemoteDatabase::do_open_post_list(const string &term) const 
    177178{ 
    178     throw Xapian::UnimplementedError("RemoteDatabase::do_open_post_list not implemented"); 
     179    AutoPtr<NetworkPostList> plist; 
     180    return new NetworkPostList(Xapian::Internal::RefCntPtr<const RemoteDatabase>(this), term); 
    179181} 
    180182 
     183void 
     184RemoteDatabase::read_post_list(const string &term, NetworkPostList & pl) const 
     185{ 
     186    send_message(MSG_POSTLIST, term); 
     187 
     188    string message; 
     189    char type; 
     190    get_message(message, REPLY_POSTLISTSTART); 
     191 
     192    const char * p = message.data(); 
     193    const char * p_end = p + message.size(); 
     194    pl.initialise(decode_length(&p, p_end, false)); 
     195 
     196    while ((type = get_message(message)) == REPLY_POSTLISTITEM) { 
     197        pl.append_posting(message); 
     198    } 
     199    if (type != REPLY_DONE) { 
     200        throw Xapian::NetworkError("Bad message received", context); 
     201    } 
     202} 
     203 
    181204PositionList * 
    182205RemoteDatabase::open_position_list(Xapian::docid did, const string &term) const 
    183206{ 
  • backends/remote/Makefile.mk

     
    55if BUILD_BACKEND_REMOTE 
    66noinst_HEADERS +=\ 
    77        backends/remote/net_document.h\ 
     8        backends/remote/net_postlist.h\ 
    89        backends/remote/net_termlist.h 
    910 
    1011libxapian_la_SOURCES +=\ 
  • backends/remote/net_postlist.h

     
     1/* net_postlist.h 
     2 * 
     3 * Copyright 2007 Lemur Consulting Ltd 
     4 * 
     5 * This program is free software; you can redistribute it and/or 
     6 * modify it under the terms of the GNU General Public License as 
     7 * published by the Free Software Foundation; either version 2 of the 
     8 * License, or (at your option) any later version. 
     9 * 
     10 * This program is distributed in the hope that it will be useful, 
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     13 * GNU General Public License for more details. 
     14 * 
     15 * You should have received a copy of the GNU General Public License 
     16 * along with this program; if not, write to the Free Software 
     17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 
     18 * USA 
     19 */ 
     20 
     21#ifndef OM_HGUARD_NET_POSTLIST_H 
     22#define OM_HGUARD_NET_POSTLIST_H 
     23 
     24#include <string> 
     25 
     26#include "leafpostlist.h" 
     27#include "remote-database.h" 
     28#include "serialise.h" 
     29#include "serialise-double.h" 
     30 
     31using namespace std; 
     32 
     33/** A postlist in a remote database. 
     34 */ 
     35class NetworkPostList : public LeafPostList { 
     36    private: 
     37    friend class RemoteDatabase; 
     38        Xapian::Internal::RefCntPtr<const RemoteDatabase> db; 
     39        string term; 
     40 
     41        string postings; 
     42        bool started; 
     43        const char * pos; 
     44        const char * pos_end; 
     45 
     46        Xapian::docid lastdocid; 
     47        Xapian::termcount lastwdf; 
     48        Xapian::doclength lastdoclen; 
     49        Xapian::Internal::RefCntPtr<PositionList> lastposlist; 
     50 
     51        Xapian::doccount termfreq; 
     52 
     53        void initialise(Xapian::doccount termfreq_) { 
     54            termfreq = termfreq_; 
     55        } 
     56 
     57        void append_posting(const string & serialised) 
     58        { 
     59            Assert(pos == NULL); 
     60            Assert(!started); 
     61            postings.append(serialised); 
     62        } 
     63 
     64    public: 
     65        NetworkPostList(Xapian::Internal::RefCntPtr<const RemoteDatabase> db_, 
     66                        const string & term_) 
     67                : db(db_), 
     68                  term(term_), 
     69                  started(false), 
     70                  pos(NULL), 
     71                  pos_end(NULL), 
     72                  lastdocid(0), 
     73                  lastwdf(0), 
     74                  lastdoclen(0), 
     75                  termfreq(0) 
     76        { 
     77            db->read_post_list(term, *this); 
     78        } 
     79 
     80        Xapian::doccount get_termfreq() const 
     81        { 
     82            return termfreq; 
     83        } 
     84 
     85        Xapian::docid get_docid() const 
     86        { 
     87            return lastdocid; 
     88        } 
     89 
     90        Xapian::doclength get_doclength() const 
     91        { 
     92            return lastdoclen; 
     93        } 
     94 
     95        Xapian::termcount get_wdf() const 
     96        { 
     97            return lastwdf; 
     98        } 
     99 
     100        PositionList * read_position_list() 
     101        { 
     102            lastposlist = db->open_position_list(lastdocid, term); 
     103            return lastposlist.get(); 
     104        } 
     105 
     106        PositionList * open_position_list() const 
     107        { 
     108            return db->open_position_list(lastdocid, term); 
     109        } 
     110 
     111        PostList * next(Xapian::weight) 
     112        { 
     113            if (!started) { 
     114                started = true; 
     115                pos = postings.data(); 
     116                pos_end = pos + postings.size(); 
     117                lastdocid = 0; 
     118            } 
     119 
     120            if (pos == pos_end) { 
     121                pos = NULL; 
     122            } else { 
     123                lastdocid += decode_length(&pos, pos_end, false) + 1; 
     124                lastwdf = decode_length(&pos, pos_end, false); 
     125                lastdoclen = unserialise_double(&pos, pos_end); 
     126            } 
     127 
     128            return NULL; 
     129        } 
     130 
     131        PostList *skip_to(Xapian::docid did, Xapian::weight weight) 
     132        { 
     133            if (pos == NULL) 
     134                next(weight); 
     135            while (pos != pos_end && lastdocid < did) 
     136                next(weight); 
     137            return NULL; 
     138        } 
     139 
     140        bool at_end() const 
     141        { 
     142            return (pos == NULL && started); 
     143        } 
     144 
     145        string get_description() const 
     146        { 
     147            return "NetworkPostList(" + term + ")"; 
     148        } 
     149}; 
     150 
     151#endif /* OM_HGUARD_NET_POSTLIST_H */