Ticket #3: db-error.diff

File db-error.diff, 18.5 KB (added by Dan, 12 years ago)
  • xapian-core/api/editdistance.h

    diff --git a/xapian-core/api/editdistance.h b/xapian-core/api/editdistance.h
    index 4ab7824..f049dbe 100644
    a b  
     1
    12/** @file editdistance.h
    23 * @brief Edit distance calculation algorithm.
    34 */
  • xapian-core/api/omdatabase.cc

    diff --git a/xapian-core/api/omdatabase.cc b/xapian-core/api/omdatabase.cc
    index 8953cb6..211ed04 100644
    a b Database::get_uuid() const  
    740740    RETURN(uuid);
    741741}
    742742
     743void
     744Database::set_error_handler(ErrorHandler* error_handler_)
     745{
     746    LOGCALL(API, std::string, "Database::set_error_handler", error_handler_);
     747    vector<intrusive_ptr<Database::Internal> >::const_iterator i;
     748    for (i = internal.begin(); i != internal.end(); ++i) {
     749        (*i)->error_handler = error_handler_;
     750    }
     751}
     752
     753
    743754///////////////////////////////////////////////////////////////////////////
    744755
    745756WritableDatabase::WritableDatabase() : Database()
  • xapian-core/api/omenquire.cc

    diff --git a/xapian-core/api/omenquire.cc b/xapian-core/api/omenquire.cc
    index 33da93b..75264d6 100644
    a b Enquire::Internal::get_mset(Xapian::doccount first, Xapian::doccount maxitems,  
    680680                       collapse_max, collapse_key,
    681681                       percent_cutoff, weight_cutoff,
    682682                       order, sort_key, sort_by, sort_value_forward,
    683                        errorhandler, stats, weight, spies,
     683                       stats, weight, spies,
    684684                       (sorter != NULL),
    685685                       (mdecider != NULL));
    686686    // Run query and put results into supplied Xapian::MSet object.
    Enquire::Internal::get_description() const  
    829829void
    830830Enquire::Internal::request_doc(const Xapian::Internal::MSetItem &item) const
    831831{
    832     try {
    833         unsigned int multiplier = db.internal.size();
     832    unsigned int multiplier = db.internal.size();
    834833
    835         Xapian::docid realdid = (item.did - 1) / multiplier + 1;
    836         Xapian::doccount dbnumber = (item.did - 1) % multiplier;
     834    Xapian::docid realdid = (item.did - 1) / multiplier + 1;
     835    Xapian::doccount dbnumber = (item.did - 1) % multiplier;
    837836
     837    try {
    838838        db.internal[dbnumber]->request_document(realdid);
    839839    } catch (Error & e) {
    840         if (errorhandler) (*errorhandler)(e);
     840        ErrorHandler* error_handler = db.internal[dbnumber]->error_handler;
     841        if (error_handler) (*error_handler)(e);
    841842        throw;
    842843    }
    843844}
    Enquire::Internal::request_doc(const Xapian::Internal::MSetItem &item) const  
    845846Document
    846847Enquire::Internal::read_doc(const Xapian::Internal::MSetItem &item) const
    847848{
    848     try {
    849         unsigned int multiplier = db.internal.size();
     849    unsigned int multiplier = db.internal.size();
    850850
    851         Xapian::docid realdid = (item.did - 1) / multiplier + 1;
    852         Xapian::doccount dbnumber = (item.did - 1) % multiplier;
     851    Xapian::docid realdid = (item.did - 1) / multiplier + 1;
     852    Xapian::doccount dbnumber = (item.did - 1) % multiplier;
    853853
     854    try {
    854855        Xapian::Document::Internal *doc;
    855856        doc = db.internal[dbnumber]->collect_document(realdid);
    856857        return Document(doc);
    857858    } catch (Error & e) {
    858         if (errorhandler) (*errorhandler)(e);
     859        ErrorHandler* error_handler = db.internal[dbnumber]->error_handler;
     860        if (error_handler) (*error_handler)(e);
    859861        throw;
    860862    }
    861863}
    const Query &  
    902904Enquire::get_query() const
    903905{
    904906    LOGCALL(API, const Xapian::Query &, "Xapian::Enquire::get_query", NO_ARGS);
    905     try {
    906         RETURN(internal->get_query());
    907     } catch (Error & e) {
    908         if (internal->errorhandler) (*internal->errorhandler)(e);
    909         throw;
    910     }
     907    RETURN(internal->get_query());
    911908}
    912909
    913910void
  • xapian-core/backends/database.cc

    diff --git a/xapian-core/backends/database.cc b/xapian-core/backends/database.cc
    index 53dc6d74..6c10eeb 100644
    a b Database::Internal::keep_alive()  
    4949    // For the normal case of local databases, nothing needs to be done.
    5050}
    5151
    52 
    5352Xapian::doccount
    5453Database::Internal::get_value_freq(Xapian::valueno) const
    5554{
  • xapian-core/backends/database.h

    diff --git a/xapian-core/backends/database.h b/xapian-core/backends/database.h
    index 3d95921..8595945 100644
    a b  
    3333#include <xapian/types.h>
    3434#include <xapian/database.h>
    3535#include <xapian/document.h>
     36#include <xapian/errorhandler.h>
    3637#include <xapian/positioniterator.h>
    3738#include <xapian/termiterator.h>
    3839#include <xapian/valueiterator.h>
    class Database::Internal : public Xapian::Internal::intrusive_base {  
    7576        bool transaction_active() const { return int(transaction_state) > 0; }
    7677
    7778        /** Create a database - called only by derived classes. */
    78         Internal() : transaction_state(TRANSACTION_NONE) { }
     79        Internal() : transaction_state(TRANSACTION_NONE), error_handler(NULL) { }
    7980
    8081        /** Internal method to perform cleanup when a writable database is
    8182         *  destroyed with uncommitted changes.
    class Database::Internal : public Xapian::Internal::intrusive_base {  
    108109         */
    109110        virtual void keep_alive();
    110111
     112        /** Internal pointer to the database's ErrorHandler
     113         */
     114        ErrorHandler* error_handler;
     115
    111116        //////////////////////////////////////////////////////////////////
    112117        // Database statistics:
    113118        // ====================
  • xapian-core/include/xapian/database.h

    diff --git a/xapian-core/include/xapian/database.h b/xapian-core/include/xapian/database.h
    index 243bf6d..7719577 100644
    a b  
    3030#include <vector>
    3131
    3232#include <xapian/attributes.h>
     33#include <xapian/errorhandler.h>
    3334#include <xapian/intrusive_ptr.h>
    3435#include <xapian/types.h>
    3536#include <xapian/positioniterator.h>
    class XAPIAN_VISIBILITY_DEFAULT Database {  
    508509         *  @param opts Options to use for check
    509510         */
    510511        static size_t check(const std::string & path, int opts);
     512
     513        /** Set an ErrorHandler for database. This will be applied to all
     514         *  databases in internal.
     515         *
     516         *  @param error_handler_ ErrorHandler* to use
     517         */
     518        void set_error_handler(ErrorHandler* error_handler_);
     519
    511520};
    512521
    513522/** This class provides read/write access to a database.
  • xapian-core/include/xapian/enquire.h

    diff --git a/xapian-core/include/xapian/enquire.h b/xapian-core/include/xapian/enquire.h
    index d16d7e2..0f63d8a 100644
    a b class XAPIAN_VISIBILITY_DEFAULT Enquire {  
    711711
    712712        /** Get the query which has been set.
    713713         *  This is only valid after set_query() has been called.
    714          *
    715          *  @exception Xapian::InvalidArgumentError will be thrown if query has
    716          *             not yet been set.
    717714         */
    718715        const Xapian::Query & get_query() const;
    719716
  • xapian-core/matcher/mergepostlist.cc

    diff --git a/xapian-core/matcher/mergepostlist.cc b/xapian-core/matcher/mergepostlist.cc
    index b32f632..7ce3f49 100644
    a b  
    3030#include "debuglog.h"
    3131#include "omassert.h"
    3232#include "valuestreamdocument.h"
    33 #include "xapian/errorhandler.h"
    3433
    3534// NB don't prune - even with one sublist we still translate docids...
    3635
    MergePostList::next(double w_min)  
    5958            if (unsigned(current) >= plists.size()) break;
    6059            vsdoc.new_subdb(current);
    6160        } catch (Xapian::Error & e) {
     61            //TODO: add test coverage
     62            Xapian::ErrorHandler* errorhandler = handlers[current];
    6263            if (errorhandler) {
    6364                LOGLINE(EXCEPTION, "Calling error handler in MergePostList::next().");
    6465                (*errorhandler)(e);
    MergePostList::recalc_maxweight()  
    176177            double w = (*i)->recalc_maxweight();
    177178            if (w > w_max) w_max = w;
    178179        } catch (Xapian::Error & e) {
    179             if (errorhandler) {
     180            //TODO: add test coverage
     181            Xapian::ErrorHandler* errorhandler_ = handlers[current];
     182            if (errorhandler_) {
    180183                LOGLINE(EXCEPTION, "Calling error handler in MergePostList::recalc_maxweight().");
    181                 (*errorhandler)(e);
     184                (*errorhandler_)(e);
    182185
    183186                if (current == i - plists.begin()) {
    184187                    // Fatal error
  • xapian-core/matcher/mergepostlist.h

    diff --git a/xapian-core/matcher/mergepostlist.h b/xapian-core/matcher/mergepostlist.h
    index f222fa2..f520445 100644
    a b  
    2626#define OM_HGUARD_MERGEPOSTLIST_H
    2727
    2828#include "api/postlist.h"
     29#include "xapian/errorhandler.h"
    2930
    3031class MultiMatch;
    3132class ValueStreamDocument;
    class MergePostList : public PostList {  
    5960         */
    6061        ValueStreamDocument & vsdoc;
    6162
    62         Xapian::ErrorHandler * errorhandler;
     63        /**
     64         *
     65         */
     66        std::vector<Xapian::ErrorHandler *> handlers;
     67
    6368    public:
    6469        Xapian::termcount get_wdf() const;
    6570        Xapian::doccount get_termfreq_max() const;
    class MergePostList : public PostList {  
    9095        MergePostList(const std::vector<PostList *> & plists_,
    9196                      MultiMatch *matcher_,
    9297                      ValueStreamDocument & vsdoc_,
    93                       Xapian::ErrorHandler * errorhandler_)
     98                      std::vector<Xapian::ErrorHandler *> & handlers_)
    9499            : plists(plists_), current(-1), matcher(matcher_), vsdoc(vsdoc_),
    95               errorhandler(errorhandler_) { }
     100            handlers(handlers_)
     101            { }
    96102
    97103        ~MergePostList();
    98104};
  • xapian-core/matcher/multimatch.cc

    diff --git a/xapian-core/matcher/multimatch.cc b/xapian-core/matcher/multimatch.cc
    index 654908a..64186ca 100644
    a b split_rset_by_db(const Xapian::RSet * rset,  
    136136 */
    137137static void
    138138prepare_sub_matches(vector<intrusive_ptr<SubMatch> > & leaves,
    139                     Xapian::ErrorHandler * errorhandler,
    140                     Xapian::Weight::Internal & stats)
     139                    Xapian::Weight::Internal & stats,
     140                    const Xapian::Database & db)
    141141{
    142     LOGCALL_STATIC_VOID(MATCH, "prepare_sub_matches", leaves | errorhandler | stats);
     142    LOGCALL_STATIC_VOID(MATCH, "prepare_sub_matches", leaves | stats);
    143143    // We use a vector<bool> to track which SubMatches we're already prepared.
    144144    vector<bool> prepared;
    145145    prepared.resize(leaves.size(), false);
    prepare_sub_matches(vector<intrusive_ptr<SubMatch> > & leaves,  
    155155                    --unprepared;
    156156                }
    157157            } catch (Xapian::Error & e) {
    158                 if (!errorhandler) throw;
     158                //TODO:add test coverage
     159                Xapian::ErrorHandler* errorhandler_ = db.internal[leaf]->error_handler;
     160                if (!errorhandler_) throw;
    159161
    160162                LOGLINE(EXCEPTION, "Calling error handler for prepare_match() on a SubMatch.");
    161                 (*errorhandler)(e);
     163                (*errorhandler_)(e);
    162164                // Continue match without this sub-match.
    163165                leaves[leaf] = NULL;
    164166                prepared[leaf] = true;
    MultiMatch::MultiMatch(const Xapian::Database &db_,  
    211213                       Xapian::valueno sort_key_,
    212214                       Xapian::Enquire::Internal::sort_setting sort_by_,
    213215                       bool sort_value_forward_,
    214                        Xapian::ErrorHandler * errorhandler_,
    215216                       Xapian::Weight::Internal & stats,
    216217                       const Xapian::Weight * weight_,
    217218                       const vector<Xapian::MatchSpy *> & matchspies_,
    MultiMatch::MultiMatch(const Xapian::Database &db_,  
    222223          order(order_),
    223224          sort_key(sort_key_), sort_by(sort_by_),
    224225          sort_value_forward(sort_value_forward_),
    225           errorhandler(errorhandler_), weight(weight_),
     226          weight(weight_),
    226227          is_remote(db.internal.size()),
    227228          matchspies(matchspies_)
    228229{
    229     LOGCALL_CTOR(MATCH, "MultiMatch", db_ | query_ | qlen | omrset | collapse_max_ | collapse_key_ | percent_cutoff_ | weight_cutoff_ | int(order_) | sort_key_ | int(sort_by_) | sort_value_forward_ | errorhandler_ | stats | weight_ | matchspies_ | have_sorter | have_mdecider);
     230    LOGCALL_CTOR(MATCH, "MultiMatch", db_ | query_ | qlen | omrset | collapse_max_ | collapse_key_ | percent_cutoff_ | weight_cutoff_ | int(order_) | sort_key_ | int(sort_by_) | sort_value_forward_ | stats | weight_ | matchspies_ | have_sorter | have_mdecider);
    230231
    231232    if (query.empty()) return;
    232233
    MultiMatch::MultiMatch(const Xapian::Database &db_,  
    267268            smatch = new LocalSubMatch(subdb, query, qlen, subrsets[i], weight);
    268269#endif /* XAPIAN_HAS_REMOTE_BACKEND */
    269270        } catch (Xapian::Error & e) {
    270             if (!errorhandler) throw;
     271            Xapian::ErrorHandler* errorhandler_ = subdb->error_handler;
     272            if (!errorhandler_) throw;
    271273            LOGLINE(EXCEPTION, "Calling error handler for creation of a SubMatch from a database and query.");
    272             (*errorhandler)(e);
     274            (*errorhandler_)(e);
    273275            // Continue match without this sub-postlist.
    274276            smatch = NULL;
    275277        }
    MultiMatch::MultiMatch(const Xapian::Database &db_,  
    277279    }
    278280
    279281    stats.mark_wanted_terms(query);
    280     prepare_sub_matches(leaves, errorhandler, stats);
     282    prepare_sub_matches(leaves, stats, db);
    281283    stats.set_bounds_from_db(db);
    282284}
    283285
    MultiMatch::get_mset(Xapian::doccount first, Xapian::doccount maxitems,  
    333335    // Start matchers.
    334336    {
    335337        vector<intrusive_ptr<SubMatch> >::iterator leaf;
    336         for (leaf = leaves.begin(); leaf != leaves.end(); ++leaf) {
    337             if (!(*leaf).get()) continue;
     338        for (size_t i = 0; i < leaves.size(); ++i) {
     339            if (!(leaves[i]).get()) continue;
    338340            try {
    339                 (*leaf)->start_match(0, first + maxitems,
     341                (leaves[i])->start_match(0, first + maxitems,
    340342                                     first + check_at_least, stats);
    341343            } catch (Xapian::Error & e) {
    342                 if (!errorhandler) throw;
     344                //TODO: add test coverage
     345                Xapian::ErrorHandler* errorhandler_ = db.internal[i]->error_handler;
     346                if (!errorhandler_) throw;
    343347                LOGLINE(EXCEPTION, "Calling error handler for "
    344348                                   "start_match() on a SubMatch.");
    345                 (*errorhandler)(e);
     349                (*errorhandler_)(e);
    346350                // Continue match without this sub-match.
    347                 *leaf = NULL;
     351                leaves[i] = NULL;
    348352            }
    349353        }
    350354    }
    MultiMatch::get_mset(Xapian::doccount first, Xapian::doccount maxitems,  
    364368    for (size_t i = 0; i != leaves.size(); ++i) {
    365369        PostList *pl;
    366370        try {
     371            if (!leaves[i].get()) {
     372                pl = new EmptyPostList;
     373                postlists.push_back(pl);
     374                continue;
     375            }
    367376            pl = leaves[i]->get_postlist_and_term_info(this,
    368377                                                       termfreqandwts_ptr,
    369378                                                       &total_subqs);
    MultiMatch::get_mset(Xapian::doccount first, Xapian::doccount maxitems,  
    380389                }
    381390            }
    382391        } catch (Xapian::Error & e) {
    383             if (!errorhandler) throw;
     392            //TODO: add test coverage
     393            Xapian::ErrorHandler* errorhandler_ = db.internal[i]->error_handler;
     394            if (!errorhandler_) throw;
    384395            LOGLINE(EXCEPTION, "Calling error handler for "
    385396                               "get_term_info() on a SubMatch.");
    386             (*errorhandler)(e);
     397            (*errorhandler_)(e);
    387398            // FIXME: check if *ALL* the remote servers have failed!
    388399            // Continue match without this sub-match.
    389400            leaves[i] = NULL;
    MultiMatch::get_mset(Xapian::doccount first, Xapian::doccount maxitems,  
    396407    ValueStreamDocument vsdoc(db);
    397408    ++vsdoc._refs;
    398409    Xapian::Document doc(&vsdoc);
     410    vector<Xapian::ErrorHandler*>handlers;
    399411
     412    Xapian::doccount number_of_subdbs = db.internal.size();
     413    for (size_t i = 0; i != number_of_subdbs; ++i) {
     414        Xapian::Database::Internal *subdb = db.internal[i].get();
     415        Assert(subdb);
     416        handlers.push_back(subdb->error_handler);
     417    }
    400418    // Get a single combined postlist
    401419    AutoPtr<PostList> pl;
    402420    if (postlists.size() == 1) {
    403421        pl.reset(postlists.front());
    404422    } else {
    405         pl.reset(new MergePostList(postlists, this, vsdoc, errorhandler));
     423        pl.reset(new MergePostList(postlists, this, vsdoc, handlers));
    406424    }
    407425
    408426    LOGLINE(MATCH, "pl = (" << pl->get_description() << ")");
  • xapian-core/matcher/multimatch.h

    diff --git a/xapian-core/matcher/multimatch.h b/xapian-core/matcher/multimatch.h
    index d2ec377..6a9facc 100644
    a b class MultiMatch  
    5757
    5858        bool sort_value_forward;
    5959
    60         /// ErrorHandler
    61         Xapian::ErrorHandler * errorhandler;
    62 
    6360        /// Weighting scheme
    6461        const Xapian::Weight * weight;
    6562
    class MultiMatch  
    9390         *  @param query     The query
    9491         *  @param qlen      The query length
    9592         *  @param omrset    The relevance set (or NULL for no RSet)
    96          *  @param errorhandler Errorhandler object
    9793         *  @param stats     The stats object to add our stats to.
    9894         *  @param wtscheme  Weighting scheme
    9995         *  @param matchspies_ Any the MatchSpy objects in use.
    class MultiMatch  
    112108                   Xapian::valueno sort_key_,
    113109                   Xapian::Enquire::Internal::sort_setting sort_by_,
    114110                   bool sort_value_forward_,
    115                    Xapian::ErrorHandler * errorhandler,
    116111                   Xapian::Weight::Internal & stats,
    117112                   const Xapian::Weight *wtscheme,
    118113                   const vector<Xapian::MatchSpy *> & matchspies_,
  • xapian-core/net/remoteserver.cc

    diff --git a/xapian-core/net/remoteserver.cc b/xapian-core/net/remoteserver.cc
    index b741fc6..f283727 100644
    a b RemoteServer::msg_query(const string &message_in)  
    459459    Xapian::Weight::Internal local_stats;
    460460    MultiMatch match(*db, query, qlen, &rset, collapse_max, collapse_key,
    461461                     percent_cutoff, weight_cutoff, order,
    462                      sort_key, sort_by, sort_value_forward, NULL,
     462                     sort_key, sort_by, sort_value_forward,
    463463                     local_stats, wt.get(), matchspies.spies, false, false);
    464464
    465465    send_message(REPLY_STATS, serialise_stats(local_stats));
  • xapian-core/tests/api_db.cc

    diff --git a/xapian-core/tests/api_db.cc b/xapian-core/tests/api_db.cc
    index 0fd1e70..6993a57 100644
    a b DEFINE_TESTCASE(stubdb6, inmemory) {  
    226226    return true;
    227227}
    228228
    229 #if 0 // the "force error" mechanism is no longer in place...
     229
    230230class MyErrorHandler : public Xapian::ErrorHandler {
    231231    public:
    232232        int count;
    class MyErrorHandler : public Xapian::ErrorHandler {  
    241241        MyErrorHandler() : count (0) {}
    242242};
    243243
     244DEFINE_TESTCASE(errorhandlercalled, remote && !multi) {
     245    MyErrorHandler myhandler;
     246    BackendManagerLocal local_manager;
     247    Xapian::Database dbs;
     248
     249    dbs.add_database(get_remote_database("apitest_simpledata", 5000));
     250    dbs.add_database(local_manager.get_database("apitest_simpledata"));
     251
     252    dbs.set_error_handler(&myhandler);
     253    Xapian::Enquire enquire(dbs);
     254
     255    enquire.set_query(Xapian::Query("word"));
     256    Xapian::MultiValueKeyMaker sorter;
     257
     258    enquire.set_sort_by_key_then_relevance(&sorter, true);
     259    Xapian::MSet mset = enquire.get_mset(0, 25);
     260    TEST_EQUAL(myhandler.count, 1);
     261    TEST_EQUAL(mset.size(), 2);
     262    return true;
     263}
     264
     265#if 0 // the "force error" mechanism is no longer in place...
    244266// tests error handler in multimatch().
    245267DEFINE_TESTCASE(multierrhandler1, backend) {
    246268    MyErrorHandler myhandler;
    247269
    248270    Xapian::Database mydb2(get_database("apitest_simpledata"));
    249271    Xapian::Database mydb3(get_database("apitest_simpledata2"));
     272
    250273    int errcount = 1;
    251274    for (int testcount = 0; testcount < 14; testcount ++) {
    252275        tout << "testcount=" << testcount << "\n";
    DEFINE_TESTCASE(multierrhandler1, backend) {  
    332355                break;
    333356        }
    334357        tout << "db=" << dbs << "\n";
    335         Xapian::Enquire enquire(dbs, &myhandler);
     358        dbs.set_error_handler(myhandler);
     359        Xapian::Enquire enquire(dbs);
    336360
    337361        // make a query
    338362        Xapian::Query myquery = query(Xapian::Query::OP_OR, "inmemory", "word");