Ticket #295: remotepostsource2.patch
File remotepostsource2.patch, 29.8 KB (added by , 16 years ago) |
---|
-
xapian-core/matcher/externalpostlist.cc
29 29 30 30 using namespace std; 31 31 32 ExternalPostList::ExternalPostList(Xapian::PostingSource *source_, 32 ExternalPostList::ExternalPostList(const Xapian::Database & db, 33 Xapian::PostingSource *source_, 33 34 double factor_) 34 : source(source_), current(0), factor(factor_)35 : source(source_), source_is_owned(false), current(0), factor(factor_) 35 36 { 36 37 Assert(source); 37 source->reset(); 38 Xapian::PostingSource * newsource = source->clone(); 39 if (newsource != NULL) { 40 source = newsource; 41 source_is_owned = true; 42 } 43 source->reset(db); 38 44 } 39 45 46 ExternalPostList::~ExternalPostList() 47 { 48 if (source_is_owned) { 49 delete source; 50 } 51 } 52 40 53 Xapian::doccount 41 54 ExternalPostList::get_termfreq_min() const 42 55 { -
xapian-core/matcher/queryoptimiser.cc
64 64 65 65 case Xapian::Query::Internal::OP_EXTERNAL_SOURCE: 66 66 Assert(query->external_source); 67 RETURN(new ExternalPostList(query->external_source, factor)); 67 RETURN(new ExternalPostList( 68 Xapian::Database(const_cast<Xapian::Database::Internal *>(&db)), 69 query->external_source, factor)); 68 70 69 71 case Xapian::Query::OP_AND: 70 72 case Xapian::Query::OP_FILTER: -
xapian-core/matcher/externalpostlist.h
29 29 30 30 class ExternalPostList : public PostList { 31 31 Xapian::PostingSource * source; 32 bool source_is_owned; 32 33 33 34 Xapian::docid current; 34 35 … … 43 44 PostList * update_after_advance(); 44 45 45 46 public: 46 ExternalPostList(Xapian::PostingSource *source_, double factor_); 47 ExternalPostList(const Xapian::Database & db, 48 Xapian::PostingSource *source_, 49 double factor_); 50 ~ExternalPostList(); 47 51 48 52 Xapian::doccount get_termfreq_min() const; 49 53 -
xapian-core/tests/internaltest.cc
452 452 Xapian::Query::Internal * qint; 453 453 454 454 s = query->internal->serialise(); 455 qint = Xapian::Query::Internal::unserialise(s); 455 map<string, Xapian::PostingSource *> m; 456 qint = Xapian::Query::Internal::unserialise(s, m); 456 457 457 458 TEST(qint->serialise() == s); 458 459 delete qint; -
xapian-core/tests/api_db.cc
1894 1894 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0) 1895 1895 { } 1896 1896 1897 void reset() { did = 0; } 1897 MyOddPostingSource(Xapian::doccount num_docs_, 1898 Xapian::doccount last_docid_) 1899 : num_docs(num_docs_), last_docid(last_docid_), did(0) 1900 { } 1898 1901 1902 PostingSource * clone() const { return new MyOddPostingSource(num_docs, last_docid); } 1903 1904 void reset(const Xapian::Database &) { did = 0; } 1905 1899 1906 // These bounds could be better, but that's not important here. 1900 1907 Xapian::doccount get_termfreq_min() const { return 0; } 1901 1908 … … 1932 1939 Xapian::Enquire enq(db); 1933 1940 MyOddPostingSource src(db); 1934 1941 1935 // Check that passing NULL is rejected as intended.1936 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query bad(NULL));1937 Xapian::PostingSource * nullsrc = NULL;1938 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query bad(nullsrc));1939 1940 1942 enq.set_query(Xapian::Query(&src)); 1941 1943 1942 1944 Xapian::MSet mset = enq.get_mset(0, 10); … … 1988 1990 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0) 1989 1991 { } 1990 1992 1991 void reset() { did = 0; } 1993 MyOddWeightingPostingSource(Xapian::doccount num_docs_, 1994 Xapian::doccount last_docid_) 1995 : num_docs(num_docs_), last_docid(last_docid_), did(0) 1996 { } 1992 1997 1998 PostingSource * clone() const { return new MyOddWeightingPostingSource(num_docs, last_docid); } 1999 2000 void reset(const Xapian::Database &) { did = 0; } 2001 1993 2002 Xapian::weight get_weight() const { 1994 2003 return (did % 2) ? 1000 : 0.001; 1995 2004 } … … 2085 2094 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0) 2086 2095 { } 2087 2096 2088 void reset() { did = 0; } 2097 MyDontAskWeightPostingSource(Xapian::doccount num_docs_, 2098 Xapian::doccount last_docid_) 2099 : num_docs(num_docs_), last_docid(last_docid_), did(0) 2100 { } 2089 2101 2102 PostingSource * clone() const { return new MyDontAskWeightPostingSource(num_docs, last_docid); } 2103 2104 void reset(const Xapian::Database &) { did = 0; } 2105 2090 2106 Xapian::weight get_weight() const { 2091 2107 FAIL_TEST("MyDontAskWeightPostingSource::get_weight() called"); 2092 2108 } … … 2158 2174 } 2159 2175 2160 2176 // Check that valueweightsource works correctly. 2161 DEFINE_TESTCASE(valueweightsource1, backend && !remote) { 2162 // FIXME: PostingSource doesn't currently work well with multi databases 2163 // but we should try to resolve that issue. 2164 SKIP_TEST_FOR_BACKEND("multi"); 2177 DEFINE_TESTCASE(valueweightsource1, backend) { 2165 2178 Xapian::Database db(get_database("apitest_phrase")); 2166 2179 Xapian::Enquire enq(db); 2167 Xapian::ValueWeightPostingSource src( db,11);2180 Xapian::ValueWeightPostingSource src(11); 2168 2181 2169 2182 // Should be in descending order of length 2170 2183 tout << "RAW" << endl; … … 2196 2209 // Check that valueweightsource gives the correct bounds for those databases 2197 2210 // which support value statistics. 2198 2211 DEFINE_TESTCASE(valueweightsource2, backend && valuestats) { 2199 // FIXME: PostingSource doesn't currently work well with multi databases2200 // but we should try to resolve that issue.2201 SKIP_TEST_FOR_BACKEND("multi");2202 2212 Xapian::Database db(get_database("apitest_phrase")); 2203 Xapian::ValueWeightPostingSource src(db, 11); 2213 Xapian::ValueWeightPostingSource src(11); 2214 src.reset(db); 2204 2215 TEST_EQUAL(src.get_termfreq_min(), 17); 2205 2216 TEST_EQUAL(src.get_termfreq_est(), 17); 2206 2217 TEST_EQUAL(src.get_termfreq_max(), 17); … … 2211 2222 2212 2223 // Check that valueweightsource skip_to() can stay in the same position. 2213 2224 DEFINE_TESTCASE(valueweightsource3, backend && valuestats) { 2214 // FIXME: PostingSource doesn't currently work well with multi databases2215 // but we should try to resolve that issue.2216 SKIP_TEST_FOR_BACKEND("multi");2217 2225 Xapian::Database db(get_database("apitest_phrase")); 2218 Xapian::ValueWeightPostingSource src(db, 11); 2226 Xapian::ValueWeightPostingSource src(11); 2227 src.reset(db); 2219 2228 TEST(!src.at_end()); 2220 2229 src.skip_to(8, 0.0); 2221 2230 TEST(!src.at_end()); -
xapian-core/tests/api_percentages.cc
45 45 : maxwt(0.0), started(false) 46 46 {} 47 47 48 MyPostingSource(const std::vector<std::pair<Xapian::docid, Xapian::weight> > &weights_, 49 Xapian::weight maxwt_) 50 : weights(weights_), maxwt(maxwt_), started(false) 51 {} 52 53 54 PostingSource * clone() const 55 { 56 return new MyPostingSource(weights, maxwt); 57 } 58 48 59 void append_docweight(Xapian::docid did, Xapian::weight wt) 49 60 { 50 61 weights.push_back(make_pair(did, wt)); … … 55 66 if (wt > maxwt) maxwt = wt; 56 67 } 57 68 58 void reset( ) { started = false; }69 void reset(const Xapian::Database &) { started = false; } 59 70 60 71 Xapian::weight get_weight() const { 61 72 return i->second; -
xapian-core/include/xapian/postingsource.h
137 137 /// Return the current docid. 138 138 virtual Xapian::docid get_docid() const = 0; 139 139 140 /** Clone the posting source. 141 * 142 * The clone should inherit the configuration of the parent, but need not 143 * inherit the state. ie, the clone does not need to be in the same 144 * iteration position as the original: the matcher will always call 145 * reset() on the clone before attempting to move the iterator, or read 146 * the information about the current position of the iterator. 147 * 148 * This may return NULL to indicate that cloning is not supported. In 149 * this case, the PostingSource may only be used with a single-database 150 * search. 151 * 152 * The default implementation returns NULL. 153 */ 154 virtual PostingSource * clone() const; 155 156 /** Name of the posting source, for performing remote searches. 157 * 158 * If the subclass is called FooPostingSource, this should return "Foo". 159 * 160 * This should only be implemented if serialise() and unserialise() are 161 * also implemented. 162 * 163 * The default implmenentation returns an empty string, to indicate that 164 * serialise() and unserialise() are not implemented. 165 */ 166 virtual std::string name() const; 167 168 /** Serialise object parameters into a string. 169 * 170 * The serialised parameters should represent the configuration of the 171 * posting source, but need not (indeed, should not) represent the current 172 * iteration state. 173 */ 174 virtual std::string serialise() const; 175 176 /** Create object given string serialisation returned by serialise(). 177 * 178 * @param s A serialised instance of this PostingSource subclass. 179 */ 180 virtual PostingSource * unserialise(const std::string &s) const; 181 140 182 /** Reset this PostingSource to its freshly constructed state. 141 183 * 142 184 * This is called automatically by the matcher prior to each query being 143 185 * processed. 186 * 187 * FIXME - document the db parameter. 144 188 */ 145 virtual void reset( ) = 0;189 virtual void reset(const Database & db) = 0; 146 190 147 191 /** Return a string describing this object. 148 192 * … … 196 240 /// An upper bound on the value returned. 197 241 double max_value; 198 242 243 /// Upper bound on the value returned specified in constructor. 244 double specified_max_value; 245 199 246 public: 200 247 /** Construct a ValueWeightPostingSource. 201 248 * 202 249 * @param db_ The database to read values from. 203 250 * @param valno_ The value slot to read values from. 204 251 */ 205 ValueWeightPostingSource(Xapian:: Database db_, Xapian::valueno valno_);252 ValueWeightPostingSource(Xapian::valueno valno_); 206 253 207 254 /** Construct a ValueWeightPostingSource. 208 255 * … … 214 261 * constructor need only be used if more accurate information is 215 262 * available. 216 263 */ 217 ValueWeightPostingSource(Xapian::Database db_, Xapian::valueno valno_, 218 double max_weight_); 264 ValueWeightPostingSource(Xapian::valueno valno_, double max_weight_); 219 265 220 266 Xapian::doccount get_termfreq_min() const; 221 267 Xapian::doccount get_termfreq_est() const; … … 232 278 233 279 Xapian::docid get_docid() const; 234 280 235 void reset(); 281 ValueWeightPostingSource * clone() const; 282 std::string name() const; 283 std::string serialise() const; 284 PostingSource * unserialise(const std::string &s) const; 236 285 286 void reset(const Database & db_); 287 237 288 std::string get_description() const; 238 289 }; 239 290 -
xapian-core/include/xapian/query.h
25 25 #ifndef XAPIAN_INCLUDED_QUERY_H 26 26 #define XAPIAN_INCLUDED_QUERY_H 27 27 28 #include <map> 28 29 #include <string> 29 30 #include <vector> 30 31 … … 204 205 */ 205 206 Query(Query::op op_, Xapian::valueno valno, const std::string &value); 206 207 207 /// Construct an external source query. 208 /** Construct an external source query. 209 * 210 * The posting source will be cloned immediately, so the source 211 * supplied may be safely deallocated after this call. 212 * 213 * @param external_source The source to use in the query. 214 */ 208 215 explicit Query(Xapian::PostingSource * external_source); 209 216 210 217 /** A query which matches all documents in the database. */ … … 325 332 /// External posting source. 326 333 Xapian::PostingSource * external_source; 327 334 335 /// Flag, indicating whether the external source is owned by the query. 336 bool external_source_owned; 337 328 338 /** swap the contents of this with another Xapian::Query::Internal, 329 339 * in a way which is guaranteed not to throw. This is 330 340 * used with the assignment operator to make it exception … … 400 410 Internal(op_t op_, Xapian::valueno valno, const std::string &value); 401 411 402 412 /// Construct an external source query. 403 explicit Internal(Xapian::PostingSource * external_source_ );413 explicit Internal(Xapian::PostingSource * external_source_, bool owned); 404 414 405 415 /** Destructor. */ 406 416 ~Internal(); 407 417 408 static Xapian::Query::Internal * unserialise(const std::string &s); 418 static Xapian::Query::Internal * unserialise(const std::string &s, 419 const std::map<std::string, Xapian::PostingSource *> &sources); 409 420 410 421 /** Add a subquery. 411 422 */ -
xapian-core/net/remoteserver.cc
114 114 wtschemes[weight->name()] = weight; 115 115 weight = new Xapian::TradWeight; 116 116 wtschemes[weight->name()] = weight; 117 118 Xapian::PostingSource * source; 119 source = new Xapian::ValueWeightPostingSource(0); 120 postingsources[source->name()] = source; 117 121 } 118 122 119 123 RemoteServer::~RemoteServer() … … 121 125 delete db; 122 126 // wdb is either NULL or equal to db, so we shouldn't delete it too! 123 127 124 map<string, Xapian::Weight*>::const_iterator i; 125 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) { 126 delete i->second; 128 { 129 map<string, Xapian::Weight*>::const_iterator i; 130 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) { 131 delete i->second; 132 } 127 133 } 134 135 { 136 map<string, Xapian::PostingSource *>::const_iterator i; 137 for (i = postingsources.begin(); i != postingsources.end(); ++i) { 138 delete i->second; 139 } 140 } 128 141 } 129 142 130 143 message_type … … 365 378 366 379 // Unserialise the Query. 367 380 len = decode_length(&p, p_end, true); 368 AutoPtr<Xapian::Query::Internal> query(Xapian::Query::Internal::unserialise(string(p, len) ));381 AutoPtr<Xapian::Query::Internal> query(Xapian::Query::Internal::unserialise(string(p, len), postingsources)); 369 382 p += len; 370 383 371 384 // Unserialise assorted Enquire settings. … … 610 623 611 624 send_message(REPLY_ADDDOCUMENT, encode_length(did)); 612 625 } 626 627 628 void 629 RemoteServer::register_posting_source(const Xapian::PostingSource &source) 630 { 631 if (source.name().empty()) { 632 throw Xapian::InvalidOperationError("Unable to register posting source - name() method returns empty string."); 633 } 634 Xapian::PostingSource * sourceclone = source.clone(); 635 if (!sourceclone) { 636 throw Xapian::InvalidOperationError("Unable to register posting source - clone() method returns NULL."); 637 } 638 try { 639 postingsources[source.name()] = sourceclone; 640 } catch(...) { 641 delete sourceclone; 642 throw; 643 } 644 } -
xapian-core/common/remoteserver.h
24 24 25 25 #include "xapian/database.h" 26 26 #include "xapian/enquire.h" 27 #include "xapian/postingsource.h" 27 28 #include "xapian/visibility.h" 28 29 29 30 #include "remoteconnection.h" … … 31 32 #include <map> 32 33 #include <string> 33 34 34 // Forward declaration35 namespace Xapian { class Weight; }36 37 35 using namespace std; 38 36 39 37 /** Remote backend server base class. */ … … 70 68 /// Registered weighting schemes. 71 69 map<string, Xapian::Weight *> wtschemes; 72 70 71 /// Registered external posting sources. 72 map<string, Xapian::PostingSource *> postingsources; 73 73 74 /// Accept a message from the client. 74 75 message_type get_message(Xapian::timeout timeout, string & result, 75 76 message_type required_type = MSG_MAX); … … 173 174 void register_weighting_scheme(const Xapian::Weight &wt) { 174 175 wtschemes[wt.name()] = wt.clone(); 175 176 } 177 178 /** Register a user-defined posting source class. 179 */ 180 void register_posting_source(const Xapian::PostingSource &source); 176 181 }; 177 182 178 183 #endif // XAPIAN_INCLUDED_REMOTESERVER_H -
xapian-core/api/omqueryinternal.cc
42 42 #include <cfloat> 43 43 #include <climits> 44 44 #include <cmath> 45 #include <map> 45 46 #include <set> 46 47 #include <vector> 47 48 … … 142 143 result += '['; 143 144 result += encode_length(tname.length()); 144 145 result += tname; 145 if (term_pos != curpos) result += '@' + om_tostring(term_pos); 146 if (wqf != 1) result += '#' + om_tostring(wqf); 146 if (term_pos != curpos) result += '@' + om_tostring(term_pos); // FIXME - should this use encode_length()? 147 if (wqf != 1) result += '#' + om_tostring(wqf); // FIXME - should this use encode_length()? 147 148 ++curpos; 148 149 } else if (op == Xapian::Query::Internal::OP_EXTERNAL_SOURCE) { 149 throw Xapian::UnimplementedError("Remote backend doesn't support PostingSource"); 150 string sourcename = external_source->name(); 151 if (sourcename.empty()) 152 throw Xapian::UnimplementedError("This PostingSource doesn't support remote use."); 153 result += '!'; 154 result += encode_length(sourcename.length()); 155 result += sourcename; 156 string sourcedata = external_source->serialise(); 157 result += encode_length(sourcedata.length()); 158 result += sourcedata; 150 159 } else { 151 160 result += "("; 152 161 for (subquery_list::const_iterator i = subqs.begin(); … … 158 167 case Xapian::Query::Internal::OP_LEAF: 159 168 Assert(false); 160 169 break; 170 case Xapian::Query::Internal::OP_EXTERNAL_SOURCE: 171 Assert(false); 172 break; 161 173 case Xapian::Query::OP_AND: 162 174 result += "&"; 163 175 break; … … 380 392 const char *p; 381 393 const char *end; 382 394 Xapian::termpos curpos; 395 const map<string, Xapian::PostingSource *> & sources; 383 396 384 397 Xapian::Query::Internal * readquery(); 398 Xapian::Query::Internal * readexternal(); 385 399 Xapian::Query::Internal * readcompound(); 386 400 387 401 public: 388 QUnserial(const string & s) : p(s.c_str()), end(p + s.size()), curpos(1) { } 402 QUnserial(const string & s, 403 const map<string, Xapian::PostingSource *> & sources_) 404 : p(s.c_str()), end(p + s.size()), curpos(1), sources(sources_) { } 389 405 Xapian::Query::Internal * decode(); 390 406 }; 391 407 … … 424 440 ++curpos; 425 441 return new Xapian::Query::Internal(tname, wqf, term_pos); 426 442 } 443 case '!': 444 return readexternal(); 427 445 case '(': 428 446 return readcompound(); 429 447 default: … … 432 450 } 433 451 } 434 452 453 Xapian::Query::Internal * 454 QUnserial::readexternal() 455 { 456 if (p == end) 457 throw Xapian::InvalidArgumentError("Bad serialised query"); 458 459 size_t length = decode_length(&p, end, true); 460 string sourcename(p, length); 461 map<string, Xapian::PostingSource *>::const_iterator i; 462 i = sources.find(string(p, length)); 463 if (i == sources.end()) { 464 throw Xapian::InvalidArgumentError("PostingSource " + string(p, length) + " not registered"); 465 } 466 467 p += length; 468 length = decode_length(&p, end, true); 469 string sourcedata(p, length); 470 p += length; 471 472 return new Xapian::Query::Internal(i->second->unserialise(sourcedata), true); 473 } 474 435 475 static Xapian::Query::Internal * 436 476 qint_from_vector(Xapian::Query::op op, 437 477 const vector<Xapian::Query::Internal *> & vec, … … 476 516 --p; 477 517 subqs.push_back(readquery()); 478 518 break; 519 case '!': 520 subqs.push_back(readexternal()); 521 break; 479 522 case '(': { 480 523 subqs.push_back(readcompound()); 481 524 break; … … 563 606 } 564 607 565 608 Xapian::Query::Internal * 566 Xapian::Query::Internal::unserialise(const string &s) 609 Xapian::Query::Internal::unserialise(const string &s, 610 const map<string, Xapian::PostingSource *> & sources) 567 611 { 568 612 Assert(s.length() > 1); 569 QUnserial u(s );613 QUnserial u(s, sources); 570 614 Xapian::Query::Internal * qint = u.decode(); 571 615 AssertEq(s, qint->serialise()); 572 616 return qint; 573 617 } 574 618 #else 575 619 Xapian::Query::Internal * 576 Xapian::Query::Internal::unserialise(const string &) 620 Xapian::Query::Internal::unserialise(const string &, 621 const map<string, Xapian::PostingSource *> & sources) 577 622 { 578 623 throw Xapian::InternalError("query serialisation not compiled in"); 579 624 } … … 597 642 std::swap(term_pos, other.term_pos); 598 643 std::swap(wqf, other.wqf); 599 644 std::swap(external_source, other.external_source); 645 std::swap(external_source_owned, other.external_source_owned); 600 646 } 601 647 602 648 Xapian::Query::Internal::Internal(const Xapian::Query::Internal ©me) … … 608 654 str_parameter(copyme.str_parameter), 609 655 term_pos(copyme.term_pos), 610 656 wqf(copyme.wqf), 611 external_source(copyme.external_source) 657 external_source(NULL), 658 external_source_owned(false) 612 659 { 613 660 for (subquery_list::const_iterator i = copyme.subqs.begin(); 614 661 i != copyme.subqs.end(); 615 662 ++i) { 616 663 subqs.push_back(new Xapian::Query::Internal(**i)); 617 664 } 665 if (copyme.external_source) { 666 external_source = copyme.external_source->clone(); 667 if (external_source == NULL) { 668 external_source = copyme.external_source; 669 external_source_owned = false; 670 } else { 671 external_source_owned = true; 672 } 673 } 618 674 } 619 675 620 676 ////////////////////////////////////////// … … 627 683 parameter(0), 628 684 tname(tname_), 629 685 term_pos(term_pos_), 630 wqf(wqf_) 686 wqf(wqf_), 687 external_source(NULL), 688 external_source_owned(false) 631 689 { 632 690 validate_query(); 633 691 } … … 638 696 parameter(parameter_), 639 697 tname(), 640 698 term_pos(0), 641 wqf(0) 699 wqf(0), 700 external_source(NULL), 701 external_source_owned(false) 642 702 { 643 703 if (parameter != 0 && op != OP_PHRASE && op != OP_NEAR && op != OP_ELITE_SET) 644 704 throw Xapian::InvalidArgumentError("parameter is only meaningful for OP_NEAR, OP_PHRASE, or OP_ELITE_SET"); … … 649 709 : op(op_), 650 710 parameter(Xapian::termcount(valno)), 651 711 tname(begin), 652 str_parameter(end) 712 str_parameter(end), 713 external_source(NULL), 714 external_source_owned(false) 653 715 { 654 716 if (op != OP_VALUE_RANGE) 655 717 throw Xapian::InvalidArgumentError("This constructor is only meaningful for OP_VALUE_RANGE"); … … 660 722 const std::string &value) 661 723 : op(op_), 662 724 parameter(Xapian::termcount(valno)), 663 tname(value) 725 tname(value), 726 external_source(NULL), 727 external_source_owned(false) 664 728 { 665 729 if (op != OP_VALUE_GE && op != OP_VALUE_LE) 666 730 throw Xapian::InvalidArgumentError("This constructor is only meaningful for OP_VALUE_GE or OP_VALUE_LE"); … … 674 738 validate_query(); 675 739 } 676 740 677 Xapian::Query::Internal::Internal(PostingSource * external_source_) 678 : op(OP_EXTERNAL_SOURCE), external_source(external_source_) 741 Xapian::Query::Internal::Internal(PostingSource * external_source_, bool owned) 742 : op(OP_EXTERNAL_SOURCE), external_source(external_source_), 743 external_source_owned(owned) 679 744 { 680 if (!external_source) 681 throw Xapian::InvalidArgumentError("The external_source parameter can not be NULL"); 745 Assert(external_source); 682 746 } 683 747 684 748 Xapian::Query::Internal::~Internal() … … 687 751 for (i = subqs.begin(); i != subqs.end(); i++) { 688 752 delete *i; 689 753 } 754 if (external_source_owned) { 755 delete external_source; 756 } 690 757 } 691 758 692 759 Xapian::Query::Internal * -
xapian-core/api/omquery.cc
30 30 31 31 #include <xapian/error.h> 32 32 #include <xapian/enquire.h> 33 33 #include <xapian/postingsource.h> 34 34 #include <xapian/termiterator.h> 35 35 36 36 #include <vector> … … 162 162 } 163 163 164 164 Query::Query(PostingSource * external_source) 165 : internal( new Query::Internal(external_source))165 : internal(NULL) 166 166 { 167 167 DEBUGAPICALL(void, "Xapian::Query::Query", external_source); 168 PostingSource * clone = external_source->clone(); 169 if (clone) { 170 internal = new Query::Internal(clone, true); 171 } else { 172 internal = new Query::Internal(external_source, false); 173 } 168 174 } 169 175 170 176 // Copy constructor -
xapian-core/api/postingsource.cc
32 32 #include "xapian/queryparser.h" // For sortable_unserialise 33 33 34 34 #include "omassert.h" 35 #include "serialise.h" 36 #include "serialise-double.h" 35 37 #include "utils.h" 36 38 37 39 #include <cfloat> … … 67 69 return true; 68 70 } 69 71 72 PostingSource * 73 PostingSource::clone() const 74 { 75 return NULL; 76 } 77 70 78 std::string 79 PostingSource::name() const 80 { 81 return std::string(); 82 } 83 84 std::string 85 PostingSource::serialise() const 86 { 87 throw Xapian::InvalidOperationError("serialise() not supported for this PostingSource"); 88 } 89 90 PostingSource * 91 PostingSource::unserialise(const std::string &) const 92 { 93 throw Xapian::InvalidOperationError("unserialise() not supported for this PostingSource"); 94 } 95 96 std::string 71 97 PostingSource::get_description() const 72 98 { 73 99 return "Xapian::PostingSource subclass"; 74 100 } 75 101 76 102 77 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::Database db_, 78 Xapian::valueno valno_) 79 : db(db_), 80 valno(valno_), 81 current_docid(0), 82 last_docid(db.get_lastdocid()), 83 current_value(0.0) 103 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::valueno valno_) 104 : valno(valno_), 105 specified_max_value(DBL_MAX) 84 106 { 85 try {86 termfreq_max = db.get_value_freq(valno);87 termfreq_est = termfreq_max;88 termfreq_min = termfreq_max;89 max_value = sortable_unserialise(db.get_value_upper_bound(valno));90 } catch (const Xapian::UnimplementedError &) {91 termfreq_max = db.get_doccount();92 termfreq_est = termfreq_max / 2;93 termfreq_min = 0;94 max_value = DBL_MAX;95 }96 107 } 97 108 98 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::Database db_, 99 Xapian::valueno valno_, 109 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::valueno valno_, 100 110 double max_weight_) 101 : db(db_), 102 valno(valno_), 103 current_docid(0), 104 last_docid(db.get_lastdocid()), 105 current_value(0.0), 106 max_value(max_weight_) 111 : valno(valno_), 112 specified_max_value(max_weight_) 107 113 { 108 try {109 termfreq_max = db.get_value_freq(valno);110 termfreq_est = termfreq_max;111 termfreq_min = termfreq_max;112 max_value = std::min(max_value,113 sortable_unserialise(db.get_value_upper_bound(valno)));114 } catch (const Xapian::UnimplementedError &) {115 termfreq_max = db.get_doccount();116 termfreq_est = termfreq_max / 2;117 termfreq_min = 0;118 }119 114 } 120 115 121 116 Xapian::doccount … … 232 227 return current_docid; 233 228 } 234 229 230 ValueWeightPostingSource * 231 ValueWeightPostingSource::clone() const 232 { 233 return new ValueWeightPostingSource(valno, specified_max_value); 234 } 235 236 std::string 237 ValueWeightPostingSource::name() const 238 { 239 return std::string("ValueWeight"); 240 } 241 242 std::string 243 ValueWeightPostingSource::serialise() const 244 { 245 return encode_length(valno) + serialise_double(specified_max_value); 246 } 247 248 PostingSource * 249 ValueWeightPostingSource::unserialise(const std::string &s) const 250 { 251 const char * p = s.data(); 252 const char * end = p + s.size(); 253 254 Xapian::valueno new_valno = decode_length(&p, end, false); 255 double new_spec_max = unserialise_double(&p, end); 256 257 return new ValueWeightPostingSource(new_valno, new_spec_max); 258 } 259 235 260 void 236 ValueWeightPostingSource::reset( )261 ValueWeightPostingSource::reset(const Database & db_) 237 262 { 263 db = db_; 238 264 current_docid = 0; 265 current_value = 0.0; 266 last_docid = db.get_lastdocid(); 267 try { 268 termfreq_max = db.get_value_freq(valno); 269 termfreq_est = termfreq_max; 270 termfreq_min = termfreq_max; 271 max_value = std::min(specified_max_value, 272 sortable_unserialise(db.get_value_upper_bound(valno))); 273 } catch (const Xapian::UnimplementedError &) { 274 termfreq_max = db.get_doccount(); 275 termfreq_est = termfreq_max / 2; 276 termfreq_min = 0; 277 max_value = specified_max_value; 278 } 239 279 } 240 280 241 281 std::string -
xapian-bindings/python/pythontest2.py
913 913 xapian.PostingSource.__init__(self) 914 914 self.max = max 915 915 916 def reset(self ):916 def reset(self, db): 917 917 self.current = -1 918 918 919 919 def get_termfreq_min(self): return 0 … … 954 954 doc.add_value(1, xapian.sortable_serialise(vals[id])) 955 955 db.add_document(doc) 956 956 957 source = xapian.ValueWeightPostingSource( db,1)957 source = xapian.ValueWeightPostingSource(1) 958 958 query = xapian.Query(source) 959 959 # del source # Check that query keeps a reference to it. 960 960 -
xapian-bindings/python/generate-python-exceptions.in
43 43 get_docid 44 44 get_description 45 45 reset 46 name 47 serialise 46 48 ); 47 49 48 50 open FD, ">except.i" or die $!; -
xapian-bindings/xapian.i
194 194 195 195 #ifdef XAPIAN_SWIG_DIRECTORS 196 196 %feature("director") Xapian::PostingSource; 197 %ignore Xapian::PostingSource::clone; 198 %ignore Xapian::PostingSource::unserialise; 197 199 %include <xapian/postingsource.h> 198 200 #else 199 201 %ignore Xapian::Query(Xapian::PostingSource *);