Ticket #710: remote_protocol_server_on_public_api.diff

File remote_protocol_server_on_public_api.diff, 10.6 KB (added by German M. Bravo, 8 years ago)

Fixed, it now passes all tests

  • xapian-core/api/omenquire.cc

    commit dc8483f6c6af8d0f38a57f6d8108305e3978b9a7
    Author: German M. Bravo <german.mb@deipi.com>
    Date:   Mon Feb 29 09:54:19 2016 -0600
    
        Public API for allowing custom Remote Protocol Server implementation.
        
        To be able to implement a Remote Protocol Server with only the xapian
        public API, four changes are needed:
        
        * Add Xapian::Enquire::prepare_mset(): prepares an enquire to get a
          MSet. Xapian::Weight::Internal is filled with the statistics and a
          MultiMatch is initialized.
        
        * Add stats serialisation methods: Xapian::Enquire::serialise_stats()
          and Xapian::Enquire::unserialise_stats(). These are used by
          MSG_QUERY and MSG_GETMSET.
        
        * Add Xapian::MSet::serialise() and Xapian::MSet::unserialise().
          Used by MSG_GETMSET.
        
        * Add Xapian::RSet::serialise() and Xapian::RSet::unserialise().
          Used by MSG_QUERY.
    
    diff --git a/xapian-core/api/omenquire.cc b/xapian-core/api/omenquire.cc
    index ad04eff..7b56d7a 100644
    a b  
    4343#include "api/omenquireinternal.h"
    4444#include "str.h"
    4545#include "weight/weightinternal.h"
     46#include "net/serialise.h"
    4647
    4748#include <algorithm>
    4849#include "autoptr.h"
    RSet::Internal::get_description() const  
    133134    return description;
    134135}
    135136
     137std::string
     138RSet::serialise() const
     139{
     140    LOGCALL(API, std::string, "RSet::serialise", NO_ARGS);
     141    RETURN(serialise_rset(*this));
     142}
     143
     144RSet
     145RSet::unserialise(const std::string &s)
     146{
     147    LOGCALL_STATIC(API, RSet, "RSet::unserialise", s);
     148    RETURN(unserialise_rset(s));
     149}
     150
    136151namespace Internal {
    137152
    138153// Methods for Xapian::MSetItem
    MSet::get_description() const  
    321336    return "Xapian::MSet(" + internal->get_description() + ")";
    322337}
    323338
     339std::string
     340MSet::serialise() const
     341{
     342    LOGCALL(API, std::string, "MSet::serialise", NO_ARGS);
     343    RETURN(serialise_mset(*this));
     344}
     345
     346MSet
     347MSet::unserialise(const std::string &s)
     348{
     349    LOGCALL_STATIC(API, MSet, "MSet::unserialise", s);
     350    RETURN(unserialise_mset(s.data(), s.data() + s.size()));
     351}
     352
    324353int
    325354MSet::Internal::convert_to_percent_internal(double wt) const
    326355{
    Enquire::Internal::get_query() const  
    620649    return query;
    621650}
    622651
    623 MSet
    624 Enquire::Internal::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
    625                             Xapian::doccount check_at_least, const RSet *rset,
    626                             const MatchDecider *mdecider) const
     652void
     653Enquire::Internal::unserialise_stats(const string& serialised)
     654{
     655    if (!stats) stats.reset(new Xapian::Weight::Internal);
     656    ::unserialise_stats(serialised, *(stats.get()));
     657    stats->set_bounds_from_db(db);
     658}
     659
     660const string
     661Enquire::Internal::serialise_stats() const
    627662{
    628     LOGCALL(MATCH, MSet, "Enquire::Internal::get_mset", first | maxitems | check_at_least | rset | mdecider);
     663    return ::serialise_stats(*(stats.get()));
     664}
     665
     666void
     667Enquire::Internal::prepare_mset(const RSet *rset,
     668                                const MatchDecider *mdecider) const
     669{
     670    LOGCALL(MATCH, MSet, "Enquire::Internal::prepare_mset", maxitems | rset | mdecider);
    629671
    630672    if (percent_cutoff && (sort_by == VAL || sort_by == VAL_REL)) {
    631673        throw Xapian::UnimplementedError("Use of a percentage cutoff while sorting primary by value isn't currently supported");
    632674    }
    633675
     676    stats.reset(new Xapian::Weight::Internal);
     677    match.reset(new ::MultiMatch(db, query, qlen, rset,
     678                                 collapse_max, collapse_key,
     679                                 percent_cutoff, weight_cutoff,
     680                                 order, sort_key, sort_by, sort_value_forward,
     681                                 time_limit, *(stats.get()), weight, spies,
     682                                 (sorter.get() != NULL),
     683                                 (mdecider != NULL)));
     684}
     685
     686MSet
     687Enquire::Internal::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
     688                            Xapian::doccount check_at_least, const RSet *rset,
     689                            const MatchDecider *mdecider) const
     690{
    634691    if (weight == 0) {
    635692        weight = new BM25Weight;
    636693    }
    637694
    638     Xapian::doccount first_orig = first;
    639     {
    640         Xapian::doccount docs = db.get_doccount();
    641         first = min(first, docs);
    642         maxitems = min(maxitems, docs);
    643         check_at_least = min(check_at_least, docs);
    644         check_at_least = max(check_at_least, maxitems);
     695    if (!stats || !match) {
     696        prepare_mset(rset, mdecider);
    645697    }
    646698
    647     AutoPtr<Xapian::Weight::Internal> stats(new Xapian::Weight::Internal);
    648     ::MultiMatch match(db, query, qlen, rset,
    649                        collapse_max, collapse_key,
    650                        percent_cutoff, weight_cutoff,
    651                        order, sort_key, sort_by, sort_value_forward,
    652                        time_limit, *(stats.get()), weight, spies,
    653                        (sorter.get() != NULL),
    654                        (mdecider != NULL));
    655     // Run query and put results into supplied Xapian::MSet object.
    656     MSet retval;
    657     match.get_mset(first, maxitems, check_at_least, retval,
    658                    *(stats.get()), mdecider, sorter.get());
    659     if (first_orig != first && retval.internal.get()) {
    660         retval.internal->firstitem = first_orig;
    661     }
     699    try {
     700        Xapian::doccount first_orig = first;
     701        {
     702            Xapian::doccount docs = db.get_doccount();
     703            first = min(first, docs);
     704            maxitems = min(maxitems, docs);
     705            check_at_least = min(check_at_least, docs);
     706            check_at_least = max(check_at_least, maxitems);
     707        }
     708
     709        // Run query and put results into supplied Xapian::MSet object.
     710        MSet retval;
     711        match->get_mset(first, maxitems, check_at_least, retval,
     712                    *(stats.get()), mdecider, sorter.get());
     713        if (first_orig != first && retval.internal.get()) {
     714            retval.internal->firstitem = first_orig;
     715        }
    662716
    663     Assert(weight->name() != "bool" || retval.get_max_possible() == 0);
     717        Assert(weight->name() != "bool" || retval.get_max_possible() == 0);
    664718
    665     // The Xapian::MSet needs to have a pointer to ourselves, so that it can
    666     // retrieve the documents.  This is set here explicitly to avoid having
    667     // to pass it into the matcher, which gets messy particularly in the
    668     // networked case.
    669     retval.internal->enquire = this;
     719        // The Xapian::MSet needs to have a pointer to ourselves, so that it can
     720        // retrieve the documents.  This is set here explicitly to avoid having
     721        // to pass it into the matcher, which gets messy particularly in the
     722        // networked case.
     723        retval.internal->enquire = this;
    670724
    671     if (!retval.internal->stats) {
    672         retval.internal->stats = stats.release();
    673     }
     725        if (!retval.internal->stats) {
     726            retval.internal->stats = stats.release();
     727        } else {
     728            stats.reset();
     729        }
     730
     731        match.reset();
    674732
    675     RETURN(retval);
     733        RETURN(retval);
     734    } catch(...) {
     735        stats.reset();
     736        match.reset();
     737        throw;
     738    }
    676739}
    677740
    678741ESet
    Enquire::set_time_limit(double time_limit)  
    10061069    internal->time_limit = time_limit;
    10071070}
    10081071
     1072void
     1073Enquire::unserialise_stats(const string& serialised)
     1074{
     1075    internal->unserialise_stats(serialised);
     1076}
     1077
     1078const string
     1079Enquire::serialise_stats() const
     1080{
     1081    RETURN(internal->serialise_stats());
     1082}
     1083
     1084void
     1085Enquire::prepare_mset(const RSet *rset,
     1086                      const MatchDecider *mdecider) const
     1087{
     1088    LOGCALL(API, Xapian::MSet, "Xapian::Enquire::prepare_mset", maxitems | rset | mdecider);
     1089
     1090    internal->prepare_mset(rset, mdecider);
     1091}
     1092
    10091093MSet
    10101094Enquire::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
    10111095                  Xapian::doccount check_at_least, const RSet *rset,
  • xapian-core/api/omenquireinternal.h

    diff --git a/xapian-core/api/omenquireinternal.h b/xapian-core/api/omenquireinternal.h
    index 4b4c902..f1d7c7e 100644
    a b  
    3737#include <map>
    3838#include <set>
    3939
     40#include "autoptr.h"
    4041#include "weight/weightinternal.h"
    4142
    4243using namespace std;
    class Enquire::Internal : public Xapian::Internal::intrusive_base {  
    151152
    152153        Xapian::Internal::opt_intrusive_ptr<KeyMaker> sorter;
    153154
     155        mutable AutoPtr<Xapian::Weight::Internal> stats;
     156        mutable AutoPtr<::MultiMatch> match;
     157
    154158        double time_limit;
    155159
    156160        /** The weight to use for this query.
    class Enquire::Internal : public Xapian::Internal::intrusive_base {  
    183187
    184188        void set_query(const Query & query_, termcount qlen_);
    185189        const Query & get_query() const;
     190
     191        void unserialise_stats(const string& serialised);
     192        const string serialise_stats() const;
     193
     194        void prepare_mset(const RSet *omrset,
     195                          const MatchDecider *mdecider) const;
     196
    186197        MSet get_mset(Xapian::doccount first, Xapian::doccount maxitems,
    187198                      Xapian::doccount check_at_least,
    188199                      const RSet *omrset,
  • xapian-core/include/xapian/enquire.h

    diff --git a/xapian-core/include/xapian/enquire.h b/xapian-core/include/xapian/enquire.h
    index 09db354..ed7c06b 100644
    a b class XAPIAN_VISIBILITY_DEFAULT RSet {  
    262262
    263263        /// Return a string describing this object.
    264264        std::string get_description() const;
     265
     266        /** Serialise RSet into a string.
     267         *
     268         *  The document representation may change between Xapian releases:
     269         *  even between minor versions.  However, it is guaranteed not to
     270         *  change if the remote database protocol has not changed between
     271         *  releases.
     272         */
     273        std::string serialise() const;
     274
     275        /** Unserialise a document from a string produced by serialise().
     276         */
     277        static RSet unserialise(const std::string &serialised);
     278
    265279};
    266280
    267281/** Base class for matcher decision functor.
    class XAPIAN_VISIBILITY_DEFAULT Enquire {  
    619633         */
    620634        void set_time_limit(double time_limit);
    621635
     636        void unserialise_stats(const std::string& serialised);
     637        const std::string serialise_stats() const;
     638
    622639        /** Get (a portion of) the match set for the current query.
    623640         *
    624641         *  @param first     the first item in the result set to return.
    class XAPIAN_VISIBILITY_DEFAULT Enquire {  
    657674         *
    658675         *  @{
    659676         */
     677        void prepare_mset(const RSet * omrset = 0,
     678                          const MatchDecider * mdecider = 0) const;
    660679        MSet get_mset(Xapian::doccount first, Xapian::doccount maxitems,
    661680                      Xapian::doccount checkatleast = 0,
    662681                      const RSet * omrset = 0,
  • xapian-core/include/xapian/mset.h

    diff --git a/xapian-core/include/xapian/mset.h b/xapian-core/include/xapian/mset.h
    index de6025d..914c535 100644
    a b class XAPIAN_VISIBILITY_DEFAULT MSet {  
    179179    /// Return a string describing this object.
    180180    std::string get_description() const;
    181181
     182    /** Serialise MSet into a string.
     183     *
     184     *  The document representation may change between Xapian releases:
     185     *  even between minor versions.  However, it is guaranteed not to
     186     *  change if the remote database protocol has not changed between
     187     *  releases.
     188     */
     189    std::string serialise() const;
     190
     191    /** Unserialise a document from a string produced by serialise().
     192     */
     193    static MSet unserialise(const std::string &serialised);
     194
    182195    /** @private @internal MSet is what the C++ STL calls a container.
    183196     *
    184197     *  The following typedefs allow the class to be used in templates in the