xapian-core  1.4.22
remote-database.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2019,2020 Olly Betts
5  * Copyright (C) 2007,2009,2010 Lemur Consulting Ltd
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <config.h>
23 
24 #include "remote-database.h"
25 
26 #include <signal.h>
27 
28 #include "autoptr.h"
30 #include "net_postlist.h"
31 #include "net_termlist.h"
32 #include "noreturn.h"
33 #include "remote-document.h"
34 #include "omassert.h"
35 #include "realtime.h"
36 #include "net/length.h"
37 #include "net/serialise.h"
38 #include "net/serialise-error.h"
39 #include "serialise-double.h"
40 #include "str.h"
41 #include "stringutils.h" // For STRINGIZE().
42 #include "weight/weightinternal.h"
43 
44 #include <cerrno>
45 #include <string>
46 #include <vector>
47 
48 #include "xapian/constants.h"
49 #include "xapian/error.h"
50 #include "xapian/matchspy.h"
51 
52 using namespace std;
54 
56 static inline bool
57 is_intermediate_reply(int msg_code, int reply_code)
58 {
59  return reply_code == REPLY_ALLTERMS ||
60  reply_code == REPLY_DOCDATA ||
61  reply_code == REPLY_VALUE ||
62  reply_code == REPLY_TERMLIST ||
63  reply_code == REPLY_POSITIONLIST ||
64  reply_code == REPLY_POSTLISTSTART ||
65  reply_code == REPLY_POSTLISTITEM ||
66  reply_code == REPLY_METADATAKEYLIST ||
67  (msg_code == MSG_TERMLIST && reply_code == REPLY_DOCLENGTH);
68 }
69 
70 XAPIAN_NORETURN(static void throw_handshake_failed(const string & context));
71 static void
73 {
74  throw Xapian::NetworkError("Handshake failed - is this a Xapian server?",
75  context);
76 }
77 
78 XAPIAN_NORETURN(static void throw_connection_closed_unexpectedly());
79 static void
81 {
82  throw Xapian::NetworkError("Connection closed unexpectedly");
83 }
84 
85 RemoteDatabase::RemoteDatabase(int fd, double timeout_,
86  const string & context_, bool writable,
87  int flags)
88  : link(fd, fd, context_),
89  context(context_),
91  mru_valstats(),
93  timeout(timeout_)
94 {
95 #ifndef __WIN32__
96  // It's simplest to just ignore SIGPIPE. We'll still know if the
97  // connection dies because we'll get EPIPE back from write().
98  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
99  throw Xapian::NetworkError("Couldn't set SIGPIPE to SIG_IGN", errno);
100  }
101 #endif
102 
103  if (!writable) {
104  // Transactions only make sense when writing, so flag them as
105  // "unimplemented" so that our destructor doesn't call dtor_called()
106  // since that might try to call commit() which will cause a message to
107  // be sent to the remote server and probably an InvalidOperationError
108  // exception message to be returned.
110  }
111 
113 
114  if (writable) {
115  if (flags & Xapian::DB_RETRY_LOCK) {
116  const string & body = encode_length(flags & Xapian::DB_RETRY_LOCK);
118  } else {
120  }
121  }
122 }
123 
124 void
126 {
127  send_message(MSG_KEEPALIVE, string());
128  string message;
129  get_message(message, REPLY_DONE);
130 }
131 
132 TermList *
133 RemoteDatabase::open_metadata_keylist(const std::string &prefix) const
134 {
135  // Ensure that total_length and doccount are up-to-date.
137 
139 
140  string message;
141  AutoPtr<NetworkTermList> tlist(
142  new NetworkTermList(0, doccount,
144  0));
145  vector<NetworkTermListItem> & items = tlist->items;
146 
147  string term = prefix;
148  while (get_message_or_done(message, REPLY_METADATAKEYLIST)) {
149  NetworkTermListItem item;
150  term.resize(size_t(static_cast<unsigned char>(message[0])));
151  term.append(message, 1, string::npos);
152  item.tname = term;
153  items.push_back(item);
154  }
155 
156  tlist->current_position = tlist->items.begin();
157  return tlist.release();
158 }
159 
160 TermList *
162 {
163  Assert(did);
164 
165  // Ensure that total_length and doccount are up-to-date.
167 
169 
170  string message;
171  get_message(message, REPLY_DOCLENGTH);
172  const char * p = message.c_str();
173  const char * p_end = p + message.size();
174  Xapian::termcount doclen;
175  decode_length(&p, p_end, doclen);
176  if (p != p_end) {
177  throw Xapian::NetworkError("Bad REPLY_DOCLENGTH message received", context);
178  }
179 
180  AutoPtr<NetworkTermList> tlist(
181  new NetworkTermList(doclen, doccount,
183  did));
184  vector<NetworkTermListItem> & items = tlist->items;
185 
186  string term;
187  while (get_message_or_done(message, REPLY_TERMLIST)) {
188  NetworkTermListItem item;
189  p = message.data();
190  p_end = p + message.size();
191  decode_length(&p, p_end, item.wdf);
192  decode_length(&p, p_end, item.termfreq);
193  term.resize(size_t(static_cast<unsigned char>(*p++)));
194  term.append(p, p_end);
195  item.tname = term;
196  items.push_back(item);
197  }
198 
199  tlist->current_position = tlist->items.begin();
200  return tlist.release();
201 }
202 
203 TermList *
204 RemoteDatabase::open_allterms(const string & prefix) const {
205  // Ensure that total_length and doccount are up-to-date.
207 
208  send_message(MSG_ALLTERMS, prefix);
209 
210  AutoPtr<NetworkTermList> tlist(
211  new NetworkTermList(0, doccount,
213  0));
214  vector<NetworkTermListItem> & items = tlist->items;
215 
216  string term = prefix;
217  string message;
218  while (get_message_or_done(message, REPLY_ALLTERMS)) {
219  NetworkTermListItem item;
220  const char * p = message.data();
221  const char * p_end = p + message.size();
222  decode_length(&p, p_end, item.termfreq);
223  term.resize(size_t(static_cast<unsigned char>(*p++)));
224  term.append(p, p_end);
225  item.tname = term;
226  items.push_back(item);
227  }
228 
229  tlist->current_position = tlist->items.begin();
230  return tlist.release();
231 }
232 
233 LeafPostList *
234 RemoteDatabase::open_post_list(const string &term) const
235 {
237 }
238 
240 RemoteDatabase::read_post_list(const string &term, NetworkPostList & pl) const
241 {
242  send_message(MSG_POSTLIST, term);
243 
244  string message;
246 
247  const char * p = message.data();
248  const char * p_end = p + message.size();
249  Xapian::doccount termfreq;
250  decode_length(&p, p_end, termfreq);
251 
252  while (get_message_or_done(message, REPLY_POSTLISTITEM)) {
253  pl.append_posting(message);
254  }
255 
256  return termfreq;
257 }
258 
259 PositionList *
260 RemoteDatabase::open_position_list(Xapian::docid did, const string &term) const
261 {
263 
264  vector<Xapian::termpos> positions;
265 
266  string message;
267  Xapian::termpos lastpos = static_cast<Xapian::termpos>(-1);
268  while (get_message_or_done(message, REPLY_POSITIONLIST)) {
269  const char * p = message.data();
270  const char * p_end = p + message.size();
271  Xapian::termpos inc;
272  decode_length(&p, p_end, inc);
273  lastpos += inc + 1;
274  positions.push_back(lastpos);
275  }
276 
277  return new InMemoryPositionList(positions);
278 }
279 
280 bool
282 {
284  return has_positional_info;
285 }
286 
287 bool
289 {
291  return update_stats(MSG_REOPEN);
292 }
293 
294 void
296 {
297  do_close();
298 }
299 
300 // Currently lazy is used:
301 //
302 // * To implement API flag Xapian::DOC_ASSUME_VALID which can be specified when
303 // calling method Database::get_document()
304 //
305 // * To read values for backends without streamed values in SlowValueList
306 //
307 // * If you call get_data(), values_begin() or values_count() on a Document
308 // object passed to a KeyMaker, MatchDecider, MatchSpy during the match
309 //
310 // The first is relevant to the remote backend, but doesn't happen during
311 // the match.
312 //
313 // SlowValueList is used with the remote backend, but not to read values
314 // during the match.
315 //
316 // KeyMaker and MatchSpy happens on the server with the remote backend, so
317 // they aren't relevant here.
318 //
319 // So the cases which are relevant to the remote backend don't matter during
320 // the match, and so we can ignore the lazy flag here without affecting matcher
321 // performance.
324 {
325  Assert(did);
326 
328  string doc_data;
329  map<Xapian::valueno, string> values;
330  get_message(doc_data, REPLY_DOCDATA);
331 
332  string message;
333  while (get_message_or_done(message, REPLY_VALUE)) {
334  const char * p = message.data();
335  const char * p_end = p + message.size();
336  Xapian::valueno slot;
337  decode_length(&p, p_end, slot);
338  values.insert(make_pair(slot, string(p, p_end)));
339  }
340 
341  return new RemoteDocument(this, did, doc_data, values);
342 }
343 
344 bool
345 RemoteDatabase::update_stats(message_type msg_code, const string & body) const
346 {
347  // MSG_MAX signals that we're handling the opening greeting, which isn't in
348  // response to an explicit message.
349  if (msg_code != MSG_MAX)
350  send_message(msg_code, body);
351 
352  string message;
353  if (!get_message_or_done(message, REPLY_UPDATE)) {
354  // The database was already open at the latest revision.
355  return false;
356  }
357 
358  if (message.size() < 3) {
360  }
361  const char *p = message.c_str();
362  const char *p_end = p + message.size();
363 
364  // The protocol major versions must match. The protocol minor version of
365  // the server must be >= that of the client.
366  int protocol_major = static_cast<unsigned char>(*p++);
367  int protocol_minor = static_cast<unsigned char>(*p++);
368  if (protocol_major != XAPIAN_REMOTE_PROTOCOL_MAJOR_VERSION ||
369  protocol_minor < XAPIAN_REMOTE_PROTOCOL_MINOR_VERSION) {
370  string errmsg("Server supports protocol version");
371  if (protocol_minor) {
372  errmsg += "s ";
373  errmsg += str(protocol_major);
374  errmsg += ".0 to ";
375  } else {
376  errmsg += ' ';
377  }
378  errmsg += str(protocol_major);
379  errmsg += '.';
380  errmsg += str(protocol_minor);
381  errmsg +=
382  " - client is using "
384  "."
386  throw Xapian::NetworkError(errmsg, context);
387  }
388 
389  decode_length(&p, p_end, doccount);
390  decode_length(&p, p_end, lastdocid);
391  lastdocid += doccount;
392  decode_length(&p, p_end, doclen_lbound);
393  decode_length(&p, p_end, doclen_ubound);
395  if (p == p_end) {
396  throw Xapian::NetworkError("Bad stats update message received", context);
397  }
398  has_positional_info = (*p++ == '1');
399  decode_length(&p, p_end, total_length);
400  uuid.assign(p, p_end);
401  cached_stats_valid = true;
402  return true;
403 }
404 
407 {
409  return doccount;
410 }
411 
414 {
416  return lastdocid;
417 }
418 
421 {
423  return total_length;
424 }
425 
426 bool
427 RemoteDatabase::term_exists(const string & tname) const
428 {
429  Assert(!tname.empty());
431  string message;
432  reply_type type = get_message(message,
435  return (type == REPLY_TERMEXISTS);
436 }
437 
438 void
439 RemoteDatabase::get_freqs(const string & term,
440  Xapian::doccount * termfreq_ptr,
441  Xapian::termcount * collfreq_ptr) const
442 {
443  Assert(!term.empty());
444  string message;
445  const char * p;
446  const char * p_end;
447  if (termfreq_ptr) {
448  if (collfreq_ptr) {
449  send_message(MSG_FREQS, term);
450  get_message(message, REPLY_FREQS);
451  } else {
452  send_message(MSG_TERMFREQ, term);
453  get_message(message, REPLY_TERMFREQ);
454  }
455  p = message.data();
456  p_end = p + message.size();
457  decode_length(&p, p_end, *termfreq_ptr);
458  } else if (collfreq_ptr) {
459  send_message(MSG_COLLFREQ, term);
460  get_message(message, REPLY_COLLFREQ);
461  p = message.data();
462  p_end = p + message.size();
463  }
464  if (collfreq_ptr) {
465  decode_length(&p, p_end, *collfreq_ptr);
466  }
467 }
468 
469 void
471 {
472  if (mru_slot != slot) {
474  string message;
475  get_message(message, REPLY_VALUESTATS);
476  const char * p = message.data();
477  const char * p_end = p + message.size();
478  mru_slot = slot;
479  decode_length(&p, p_end, mru_valstats.freq);
480  size_t len;
481  decode_length_and_check(&p, p_end, len);
482  mru_valstats.lower_bound.assign(p, len);
483  p += len;
484  decode_length_and_check(&p, p_end, len);
485  mru_valstats.upper_bound.assign(p, len);
486  p += len;
487  if (p != p_end) {
488  throw Xapian::NetworkError("Bad REPLY_VALUESTATS message received", context);
489  }
490  }
491 }
492 
495 {
496  read_value_stats(slot);
497  return mru_valstats.freq;
498 }
499 
500 std::string
502 {
503  read_value_stats(slot);
504  return mru_valstats.lower_bound;
505 }
506 
507 std::string
509 {
510  read_value_stats(slot);
511  return mru_valstats.upper_bound;
512 }
513 
516 {
517  return doclen_lbound;
518 }
519 
522 {
523  return doclen_ubound;
524 }
525 
528 {
529  // The default implementation returns get_collection_freq(), but we
530  // don't want the overhead of a remote message and reply per query
531  // term, and we can get called in the middle of a remote exchange
532  // too. FIXME: handle this bound in the stats local/remote code...
533  return doclen_ubound;
534 }
535 
538 {
539  Assert(did != 0);
541  string message;
542  get_message(message, REPLY_DOCLENGTH);
543  const char * p = message.c_str();
544  const char * p_end = p + message.size();
545  Xapian::termcount doclen;
546  decode_length(&p, p_end, doclen);
547  if (p != p_end) {
548  throw Xapian::NetworkError("Bad REPLY_DOCLENGTH message received", context);
549  }
550  return doclen;
551 }
552 
555 {
556  Assert(did != 0);
558  string message;
559  get_message(message, REPLY_UNIQUETERMS);
560  const char * p = message.c_str();
561  const char * p_end = p + message.size();
562  Xapian::termcount doclen;
563  decode_length(&p, p_end, doclen);
564  if (p != p_end) {
565  throw Xapian::NetworkError("Bad REPLY_UNIQUETERMS message received", context);
566  }
567  return doclen;
568 }
569 
572  reply_type required_type,
573  reply_type required_type2) const
574 {
576  int type = link.get_message(result, end_time);
577  if (pending_reply >= 0 && !is_intermediate_reply(pending_reply, type)) {
578  pending_reply = -1;
579  }
580  if (type < 0)
582  if (rare(type) >= REPLY_MAX) {
583  if (required_type == REPLY_UPDATE)
585  string errmsg("Invalid reply type ");
586  errmsg += str(type);
587  throw Xapian::NetworkError(errmsg);
588  }
589  if (type == REPLY_EXCEPTION) {
590  unserialise_error(result, "REMOTE:", context);
591  }
592  if (type != required_type && type != required_type2) {
593  string errmsg("Expecting reply type ");
594  errmsg += str(int(required_type));
595  if (required_type2 != required_type) {
596  errmsg += " or ";
597  errmsg += str(int(required_type2));
598  }
599  errmsg += ", got ";
600  errmsg += str(type);
601  throw Xapian::NetworkError(errmsg);
602  }
603 
604  return static_cast<reply_type>(type);
605 }
606 
607 void
608 RemoteDatabase::send_message(message_type type, const string &message) const
609 {
611  while (pending_reply >= 0) {
612  string dummy;
613  int reply_code = link.get_message(dummy, end_time);
614  if (reply_code < 0)
616  if (!is_intermediate_reply(pending_reply, reply_code)) {
617  pending_reply = -1;
618  }
619  }
620  link.send_message(static_cast<unsigned char>(type), message, end_time);
621  if (type == MSG_REMOVESPELLING) {
622  // MSG_REMOVESPELLING is the only message we send which doesn't expect
623  // a reply (except MSG_SHUTDOWN which causes us to exit anyway).
624  pending_reply = -1;
625  } else {
626  pending_reply = int(type);
627  }
628 }
629 
630 void
632 {
633  // In the constructor, we set transaction_state to
634  // TRANSACTION_UNIMPLEMENTED if we aren't writable so that we can check
635  // it here.
636  bool writable = (transaction_state != TRANSACTION_UNIMPLEMENTED);
637 
638  if (writable) {
639  try {
640  if (transaction_active()) {
642  } else {
643  commit();
644  }
645  } catch (...) {
646  try {
647  link.do_close();
648  } catch (...) {
649  }
650  throw;
651  }
652 
653  // If we're writable, send a shutdown message to the server and wait
654  // for it to close its end of the connection so we know that changes
655  // have been written and flushed, and the database write lock released.
656  // For the non-writable case, there's no need to wait - it would just
657  // slow down searching needlessly.
658  link.shutdown();
659  }
660  link.do_close();
661 }
662 
663 void
665  Xapian::termcount qlen,
666  Xapian::doccount collapse_max,
667  Xapian::valueno collapse_key,
669  Xapian::valueno sort_key,
671  bool sort_value_forward,
672  double time_limit,
673  int percent_cutoff, double weight_cutoff,
674  const Xapian::Weight *wtscheme,
675  const Xapian::RSet &omrset,
677 {
678  string tmp = query.serialise();
679  string message = encode_length(tmp.size());
680  message += tmp;
681 
682  // Serialise assorted Enquire settings.
683  message += encode_length(qlen);
684  message += encode_length(collapse_max);
685  if (collapse_max) message += encode_length(collapse_key);
686  message += char('0' + order);
687  message += encode_length(sort_key);
688  message += char('0' + sort_by);
689  message += char('0' + sort_value_forward);
690  message += serialise_double(time_limit);
691  message += char(percent_cutoff);
692  message += serialise_double(weight_cutoff);
693 
694  tmp = wtscheme->name();
695  message += encode_length(tmp.size());
696  message += tmp;
697 
698  tmp = wtscheme->serialise();
699  message += encode_length(tmp.size());
700  message += tmp;
701 
702  tmp = serialise_rset(omrset);
703  message += encode_length(tmp.size());
704  message += tmp;
705 
706  for (auto i : matchspies) {
707  tmp = i->name();
708  if (tmp.empty()) {
709  throw Xapian::UnimplementedError("MatchSpy subclass not suitable for use with remote searches - name() method returned empty string");
710  }
711  message += encode_length(tmp.size());
712  message += tmp;
713 
714  tmp = i->serialise();
715  message += encode_length(tmp.size());
716  message += tmp;
717  }
718 
719  send_message(MSG_QUERY, message);
720 }
721 
722 bool
724 {
725  if (nowait && !link.ready_to_read()) return false;
726 
727  string message;
728  get_message(message, REPLY_STATS);
729  const char* p = message.data();
730  unserialise_stats(p, p + message.size(), out);
731 
732  return true;
733 }
734 
735 void
737  Xapian::doccount maxitems,
738  Xapian::doccount check_at_least,
739  const Xapian::Weight::Internal &stats)
740 {
741  string message = encode_length(first);
742  message += encode_length(maxitems);
743  message += encode_length(check_at_least);
744  message += serialise_stats(stats);
745  send_message(MSG_GETMSET, message);
746 }
747 
748 void
751 {
752  string message;
753  get_message(message, REPLY_RESULTS);
754  const char * p = message.data();
755  const char * p_end = p + message.size();
756 
757  for (auto i : matchspies) {
758  if (p == p_end)
759  throw Xapian::NetworkError("Expected serialised matchspy");
760  size_t len;
761  decode_length_and_check(&p, p_end, len);
762  string spyresults(p, len);
763  p += len;
764  i->merge_results(spyresults);
765  }
766  mset = unserialise_mset(p, p_end);
767 }
768 
769 void
771 {
772  if (!uncommitted_changes) return;
773 
774  send_message(MSG_COMMIT, string());
775 
776  // We need to wait for a response to ensure documents have been committed.
777  string message;
778  get_message(message, REPLY_DONE);
779 
780  uncommitted_changes = false;
781 }
782 
783 void
785 {
786  if (!uncommitted_changes) return;
787 
788  cached_stats_valid = false;
790 
791  send_message(MSG_CANCEL, string());
792  string dummy;
793  get_message(dummy, REPLY_DONE);
794 
795  uncommitted_changes = false;
796 }
797 
800 {
801  cached_stats_valid = false;
803  uncommitted_changes = true;
804 
806 
807  string message;
808  get_message(message, REPLY_ADDDOCUMENT);
809 
810  const char * p = message.data();
811  const char * p_end = p + message.size();
812  Xapian::docid did;
813  decode_length(&p, p_end, did);
814  return did;
815 }
816 
817 void
819 {
820  cached_stats_valid = false;
822  uncommitted_changes = true;
823 
825  string dummy;
826  get_message(dummy, REPLY_DONE);
827 }
828 
829 void
830 RemoteDatabase::delete_document(const std::string & unique_term)
831 {
832  cached_stats_valid = false;
834  uncommitted_changes = true;
835 
836  send_message(MSG_DELETEDOCUMENTTERM, unique_term);
837  string dummy;
838  get_message(dummy, REPLY_DONE);
839 }
840 
841 void
843  const Xapian::Document & doc)
844 {
845  cached_stats_valid = false;
847  uncommitted_changes = true;
848 
849  string message = encode_length(did);
850  message += serialise_document(doc);
851 
853  string dummy;
854  get_message(dummy, REPLY_DONE);
855 }
856 
858 RemoteDatabase::replace_document(const std::string & unique_term,
859  const Xapian::Document & doc)
860 {
861  cached_stats_valid = false;
863  uncommitted_changes = true;
864 
865  string message = encode_length(unique_term.size());
866  message += unique_term;
867  message += serialise_document(doc);
868 
870 
871  get_message(message, REPLY_ADDDOCUMENT);
872 
873  const char * p = message.data();
874  const char * p_end = p + message.size();
875  Xapian::docid did;
876  decode_length(&p, p_end, did);
877  return did;
878 }
879 
880 string
882 {
883  return uuid;
884 }
885 
886 string
887 RemoteDatabase::get_metadata(const string & key) const
888 {
890  string metadata;
891  get_message(metadata, REPLY_METADATA);
892  return metadata;
893 }
894 
895 void
896 RemoteDatabase::set_metadata(const string & key, const string & value)
897 {
898  uncommitted_changes = true;
899 
900  string data = encode_length(key.size());
901  data += key;
902  data += value;
904  string dummy;
905  get_message(dummy, REPLY_DONE);
906 }
907 
908 void
909 RemoteDatabase::add_spelling(const string & word,
910  Xapian::termcount freqinc) const
911 {
912  uncommitted_changes = true;
913 
914  string data = encode_length(freqinc);
915  data += word;
917  string dummy;
918  get_message(dummy, REPLY_DONE);
919 }
920 
921 void
923  Xapian::termcount freqdec) const
924 {
925  uncommitted_changes = true;
926 
927  string data = encode_length(freqdec);
928  data += word;
930 }
931 
932 bool
934 {
935  throw Xapian::UnimplementedError("Database::locked() not implemented for remote backend");
936 }
void close()
Close the database.
Xapian::doccount get_value_freq(Xapian::valueno slot) const
Return the frequency of a given value slot.
void get_freqs(const string &term, Xapian::doccount *termfreq_ptr, Xapian::termcount *collfreq_ptr) const
Returns frequencies for a term.
An item in a NetworkTermList.
Definition: net_termlist.h:38
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:80
PositionList from an InMemory DB or a Document object.
#define Assert(COND)
Definition: omassert.h:122
Define the XAPIAN_NORETURN macro.
LeafPostList * open_post_list(const string &tname) const
Open a posting list.
Xapian::termcount get_doclength(Xapian::docid did) const
Get the length of a given document.
Termlist in a remote db.
TermList * open_metadata_keylist(const std::string &prefix) const
Get remote metadata key list.
bool uncommitted_changes
True if there are (or may be) uncommitted changes.
length encoded as a string
int get_message(std::string &result, double end_time)
Read one message from fdin.
Xapian::doccount doccount
The remote document count, given at open.
unsigned timeout
A timeout value in milliseconds.
Definition: types.h:100
static void throw_handshake_failed(const string &context)
virtual std::string name() const
Return the name of this weighting scheme.
Definition: weight.cc:135
bool transaction_active() const
Definition: database.h:73
Xapian::termcount wdf
The within-document-frequency of the term.
Definition: net_termlist.h:55
void read_value_stats(Xapian::valueno slot) const
Read the value statistics for a value from a remote database.
bool has_positional_info
Has positional information?
XAPIAN_TOTALLENGTH_TYPE totallength
The total length of all documents in a database.
Definition: types.h:139
Constants in the Xapian namespace.
Xapian::termcount get_doclength_upper_bound() const
Get an upper bound on the length of a document in this DB.
double end_time(double timeout)
Return the end time for a timeout in timeout seconds.
Definition: realtime.h:95
TermList * open_allterms(const string &prefix) const
Iterate all terms.
reply_type
Reply types (server -> client).
string context
The context to return with any error messages.
A document in the database, possibly plus modifications.
Definition: document.h:41
Class representing a list of search results.
Definition: mset.h:44
#define STRINGIZE(X)
The STRINGIZE macro converts its parameter into a string constant.
Definition: stringutils.h:36
RemoteDatabase is the baseclass for remote database implementations.
Abstract base class for termlists.
Definition: termlist.h:39
STL namespace.
Convert types to std::string.
Xapian::termcount get_wdf_upper_bound(const string &term) const
Get an upper bound on the wdf of term term.
bool has_positions() const
Check whether this database contains any positional information.
std::string upper_bound
An upper bound on the values stored in the given value slot.
Definition: valuestats.h:41
Abstract base class for leaf postlists.
Definition: leafpostlist.h:38
Xapian::Document::Internal * open_document(Xapian::docid did, bool lazy) const
Get a remote document.
virtual std::string serialise() const
Return this object&#39;s parameters serialised as a single string.
Definition: weight.cc:141
std::string encode_length(T len)
Encode a length as a variable-length string.
Definition: length.h:36
Xapian::docid get_lastdocid() const
Get the last used docid.
static bool is_intermediate_reply(int msg_code, int reply_code)
Return true if further replies should be expected.
#define rare(COND)
Definition: config.h:573
Xapian::docid add_document(const Xapian::Document &doc)
Add a new document to the database.
void send_message(message_type type, const string &data) const
Send a message to the server.
double timeout
The timeout value used in network communications, in seconds.
void do_close()
Close the socket.
void delete_document(Xapian::docid did)
Delete a document in the database.
int pending_reply
Are we currently expecting a reply?
Xapian::totallength total_length
The total length of all documents in this database.
Xapian::doccount termfreq
The term frequency.
Definition: net_termlist.h:48
Xapian::doccount freq
The number of documents which have a (non-empty) value stored in the slot.
Definition: valuestats.h:33
ValueStats mru_valstats
The most recently used value statistics.
std::string lower_bound
A lower bound on the values stored in the given value slot.
Definition: valuestats.h:37
enum Xapian::Database::Internal::@2 transaction_state
Transaction state.
Xapian::doccount get_doccount() const
Get the document count.
Xapian::MSet unserialise_mset(const char *p, const char *p_end)
Unserialise a serialised Xapian::MSet object.
Definition: serialise.cc:154
Hierarchy of classes which Xapian can throw as exceptions.
void commit()
Commit pending modifications to the database.
Xapian::docid lastdocid
The remote last docid, given at open.
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:72
void unserialise_error(const string &serialised_error, const string &prefix, const string &new_context)
Unserialise a Xapian::Error object and throw it.
functions to serialise and unserialise a double
string get_metadata(const string &key) const
Get the metadata associated with a given key.
const char * dummy[]
Definition: version_h.cc:7
OwnedRemoteConnection link
The object which does the I/O.
Xapian::termcount doclen_lbound
A lower bound on the smallest document length in this database.
MatchSpy implementation.
Xapian::Weight::Internal class, holding database and term statistics.
void get_mset(Xapian::MSet &mset, const vector< Xapian::Internal::opt_intrusive_ptr< Xapian::MatchSpy >> &matchspies)
Get the MSet from the remote server.
Class to hold statistics for a given collection.
void set_query(const Xapian::Query &query, Xapian::termcount qlen, Xapian::doccount collapse_max, Xapian::valueno collapse_key, Xapian::Enquire::docid_order order, Xapian::valueno sort_key, Xapian::Enquire::Internal::sort_setting sort_by, bool sort_value_forward, double time_limit, int percent_cutoff, double weight_cutoff, const Xapian::Weight *wtscheme, const Xapian::RSet &omrset, const vector< Xapian::Internal::opt_intrusive_ptr< Xapian::MatchSpy >> &matchspies)
Set the query.
string uuid
The UUID of the remote database.
Xapian::valueno mru_slot
The value slot for the most recently used value statistics.
void send_global_stats(Xapian::doccount first, Xapian::doccount maxitems, Xapian::doccount check_at_least, const Xapian::Weight::Internal &stats)
Send the global stats to the remote server.
string str(int value)
Convert int to std::string.
Definition: str.cc:90
A position list in a inmemory database.
bool get_remote_stats(bool nowait, Xapian::Weight::Internal &out)
Get the stats from the remote server.
std::string serialise() const
Serialise this object into a string.
Definition: query.cc:193
bool term_exists(const string &tname) const
Check if term exists.
std::string get_value_lower_bound(Xapian::valueno slot) const
Get a lower bound on the values stored in the given value slot.
Postlists for remote databases.
#define XAPIAN_REMOTE_PROTOCOL_MAJOR_VERSION
void keep_alive()
Send a keep-alive message.
string serialise_stats(const Xapian::Weight::Internal &stats)
Serialise a stats object.
Definition: serialise.cc:42
void replace_document(Xapian::docid did, const Xapian::Document &doc)
Replace a given document in the database.
functions to convert classes to strings and back
string serialise_rset(const Xapian::RSet &rset)
Serialise a Xapian::RSet object.
Definition: serialise.cc:217
#define XAPIAN_REMOTE_PROTOCOL_MINOR_VERSION
static Xapian::Query query(Xapian::Query::op op, const string &t1=string(), const string &t2=string(), const string &t3=string(), const string &t4=string(), const string &t5=string(), const string &t6=string(), const string &t7=string(), const string &t8=string(), const string &t9=string(), const string &t10=string())
Definition: api_anydb.cc:63
string serialise_document(const Xapian::Document &doc)
Serialise a Xapian::Document object.
Definition: serialise.cc:251
bool update_stats(message_type msg_code=MSG_UPDATE, const std::string &body=std::string()) const
void unserialise_stats(const char *p, const char *p_end, Xapian::Weight::Internal &stat)
Unserialise a serialised stats object.
Definition: serialise.cc:71
void set_metadata(const string &key, const string &value)
Set the metadata associated with a given key.
std::string serialise_double(double v)
Serialise a double to a string.
void decode_length_and_check(const char **p, const char *end, unsigned &out)
Decode a length encoded by encode_length.
Definition: length.cc:112
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:38
Xapian::termcount get_unique_terms(Xapian::docid did) const
Get the number of unique term in document.
A document read from a RemoteDatabase.
void shutdown()
Shutdown the connection.
void remove_spelling(const std::string &, Xapian::termcount freqdec) const
Remove a word from the spelling dictionary.
A term list for a database on the other side of a network connection.
Definition: net_termlist.h:62
PositionList * open_position_list(Xapian::docid did, const string &tname) const
Open a position list for the given term in the given document.
bool locked() const
Return true if the database is open for writing.
Indicates a problem communicating with a remote database.
Definition: error.h:803
void add_spelling(const std::string &, Xapian::termcount) const
Add a word to the spelling dictionary.
Xapian::doccount read_post_list(const string &term, NetworkPostList &pl) const
unsigned valueno
The number for a value slot in a document.
Definition: types.h:108
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:83
string tname
The "name" of this term.
Definition: net_termlist.h:42
Various handy helpers which std::string really should provide.
std::string get_value_upper_bound(Xapian::valueno slot) const
Get an upper bound on the values stored in the given value slot.
message_type
Message types (client -> server).
std::string get_uuid() const
Get a UUID for the database.
void send_message(char type, const std::string &s, double end_time)
Send a message.
A document read from a RemoteDatabase.
const int DB_RETRY_LOCK
If the database is already locked, retry the lock.
Definition: constants.h:145
Xapian::totallength get_total_length() const
Return the total length of all documents in this database.
static void throw_connection_closed_unexpectedly()
Various assertion macros.
bool reopen()
Reopen the database to the latest available revision.
Functions for handling a time or time interval in a double.
bool ready_to_read() const
See if there is data available to read.
bool get_message_or_done(std::string &message, reply_type required_type) const
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:52
void cancel()
Cancel pending modifications to the database.
Class representing a query.
Definition: query.h:46
const valueno BAD_VALUENO
Reserved value to indicate "no valueno".
Definition: types.h:125
Abstract base class for iterating term positions in a document.
Definition: positionlist.h:31
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:81
void do_close()
Close the connection.
functions to convert classes to strings and back
reply_type get_message(std::string &message, reply_type required_type, reply_type required_type2) const
Receive a message from the server.
docid_order
Ordering of docids.
Definition: enquire.h:322
void cancel_transaction()
Cancel a transaction.
Definition: database.cc:149
A postlist in a remote database.
Definition: net_postlist.h:36
void decode_length(const char **p, const char *end, unsigned &out)
Decode a length encoded by encode_length.
Definition: length.cc:94
A handle representing a document in a Xapian database.
Definition: document.h:61
Wrapper around standard unique_ptr template.
void append_posting(const string &serialised)
Append a posting to the end of the postlist.
Definition: net_postlist.h:52
A relevance set (R-Set).
Definition: enquire.h:60
UnimplementedError indicates an attempt to use an unimplemented feature.
Definition: error.h:325
Xapian::termcount get_doclength_lower_bound() const
Get a lower bound on the length of a document in this DB.
Abstract base class for weighting schemes.
Definition: weight.h:35
Xapian::termcount doclen_ubound
An upper bound on the greatest document length in this database.
RemoteDatabase(const RemoteDatabase &)
Don&#39;t allow copying.
TermList * open_term_list(Xapian::docid did) const
Get remote termlist.