Ticket #710: remote_protocol_server_on_public_api.2.diff

File remote_protocol_server_on_public_api.2.diff, 9.8 KB (added by German M. Bravo, 9 years ago)
  • xapian-core/api/omenquire.cc

    commit 2ca6c36627cc0ec16e3c1cc78acb23f461c51577
    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..0c31a0c 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
     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
     662{
     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", rset | mdecider);
     671
     672    if (percent_cutoff && (sort_by == VAL || sort_by == VAL_REL)) {
     673        throw Xapian::UnimplementedError("Use of a percentage cutoff while sorting primary by value isn't currently supported");
     674    }
     675
     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
    623686MSet
    624687Enquire::Internal::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
    625688                            Xapian::doccount check_at_least, const RSet *rset,
    Enquire::Internal::get_mset(Xapian::doccount first, Xapian::doccount maxitems,  
    644707        check_at_least = max(check_at_least, maxitems);
    645708    }
    646709
    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     }
     710    try {
     711        if (!stats || !match) {
     712            prepare_mset(rset, mdecider);
     713        }
    662714
    663     Assert(weight->name() != "bool" || retval.get_max_possible() == 0);
     715        // Run query and put results into supplied Xapian::MSet object.
     716        MSet retval;
     717        match->get_mset(first, maxitems, check_at_least, retval,
     718                    *(stats.get()), mdecider, sorter.get());
     719        if (first_orig != first && retval.internal.get()) {
     720            retval.internal->firstitem = first_orig;
     721        }
    664722
    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;
     723        Assert(weight->name() != "bool" || retval.get_max_possible() == 0);
    670724
    671     if (!retval.internal->stats) {
    672         retval.internal->stats = stats.release();
    673     }
     725        // The Xapian::MSet needs to have a pointer to ourselves, so that it can
     726        // retrieve the documents.  This is set here explicitly to avoid having
     727        // to pass it into the matcher, which gets messy particularly in the
     728        // networked case.
     729        retval.internal->enquire = this;
     730
     731        if (!retval.internal->stats) {
     732            retval.internal->stats = stats.release();
     733        } else {
     734            stats.reset();
     735        }
     736
     737        match.reset();
    674738
    675     RETURN(retval);
     739        RETURN(retval);
     740    } catch(...) {
     741        stats.reset();
     742        match.reset();
     743        throw;
     744    }
    676745}
    677746
    678747ESet
    Enquire::set_time_limit(double time_limit)  
    10061075    internal->time_limit = time_limit;
    10071076}
    10081077
     1078void
     1079Enquire::unserialise_stats(const string& serialised)
     1080{
     1081    internal->unserialise_stats(serialised);
     1082}
     1083
     1084const string
     1085Enquire::serialise_stats() const
     1086{
     1087    RETURN(internal->serialise_stats());
     1088}
     1089
     1090void
     1091Enquire::prepare_mset(const RSet *rset,
     1092                      const MatchDecider *mdecider) const
     1093{
     1094    LOGCALL(API, Xapian::MSet, "Xapian::Enquire::prepare_mset", maxitems | rset | mdecider);
     1095
     1096    internal->prepare_mset(rset, mdecider);
     1097}
     1098
    10091099MSet
    10101100Enquire::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
    10111101                  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