xapian-core  1.4.26
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 #include "safesyssocket.h" // For MSG_NOSIGNAL.
28 
29 #include "autoptr.h"
31 #include "net_postlist.h"
32 #include "net_termlist.h"
33 #include "noreturn.h"
34 #include "remote-document.h"
35 #include "omassert.h"
36 #include "realtime.h"
37 #include "net/length.h"
38 #include "net/serialise.h"
39 #include "net/serialise-error.h"
40 #include "serialise-double.h"
41 #include "str.h"
42 #include "stringutils.h" // For STRINGIZE().
43 #include "weight/weightinternal.h"
44 
45 #include <cerrno>
46 #include <string>
47 #include <vector>
48 
49 #include "xapian/constants.h"
50 #include "xapian/error.h"
51 #include "xapian/matchspy.h"
52 
53 using namespace std;
55 
57 static inline bool
58 is_intermediate_reply(int msg_code, int reply_code)
59 {
60  return reply_code == REPLY_ALLTERMS ||
61  reply_code == REPLY_DOCDATA ||
62  reply_code == REPLY_VALUE ||
63  reply_code == REPLY_TERMLIST ||
64  reply_code == REPLY_POSITIONLIST ||
65  reply_code == REPLY_POSTLISTSTART ||
66  reply_code == REPLY_POSTLISTITEM ||
67  reply_code == REPLY_METADATAKEYLIST ||
68  (msg_code == MSG_TERMLIST && reply_code == REPLY_DOCLENGTH);
69 }
70 
71 XAPIAN_NORETURN(static void throw_handshake_failed(const string & context));
72 static void
74 {
75  throw Xapian::NetworkError("Handshake failed - is this a Xapian server?",
76  context);
77 }
78 
79 XAPIAN_NORETURN(static void throw_connection_closed_unexpectedly());
80 static void
82 {
83  throw Xapian::NetworkError("Connection closed unexpectedly");
84 }
85 
86 RemoteDatabase::RemoteDatabase(int fd, double timeout_,
87  const string & context_, bool writable,
88  int flags)
89  : link(fd, fd, context_),
90  context(context_),
92  mru_valstats(),
94  timeout(timeout_)
95 {
96  if (!writable) {
97  // Transactions only make sense when writing, so flag them as
98  // "unimplemented" so that our destructor doesn't call dtor_called()
99  // since that might try to call commit() which will cause a message to
100  // be sent to the remote server and probably an InvalidOperationError
101  // exception message to be returned.
103  }
104 
106 
107  if (writable) {
108  if (flags & Xapian::DB_RETRY_LOCK) {
109  const string & body = encode_length(flags & Xapian::DB_RETRY_LOCK);
111  } else {
113  }
114  }
115 }
116 
117 void
119 {
120  send_message(MSG_KEEPALIVE, string());
121  string message;
122  get_message(message, REPLY_DONE);
123 }
124 
125 TermList *
126 RemoteDatabase::open_metadata_keylist(const std::string &prefix) const
127 {
128  // Ensure that total_length and doccount are up-to-date.
130 
132 
133  string message;
134  AutoPtr<NetworkTermList> tlist(
135  new NetworkTermList(0, doccount,
137  0));
138  vector<NetworkTermListItem> & items = tlist->items;
139 
140  string term = prefix;
141  while (get_message_or_done(message, REPLY_METADATAKEYLIST)) {
142  NetworkTermListItem item;
143  term.resize(size_t(static_cast<unsigned char>(message[0])));
144  term.append(message, 1, string::npos);
145  item.tname = term;
146  items.push_back(item);
147  }
148 
149  tlist->current_position = tlist->items.begin();
150  return tlist.release();
151 }
152 
153 TermList *
155 {
156  Assert(did);
157 
158  // Ensure that total_length and doccount are up-to-date.
160 
162 
163  string message;
164  get_message(message, REPLY_DOCLENGTH);
165  const char * p = message.c_str();
166  const char * p_end = p + message.size();
167  Xapian::termcount doclen;
168  decode_length(&p, p_end, doclen);
169  if (p != p_end) {
170  throw Xapian::NetworkError("Bad REPLY_DOCLENGTH message received", context);
171  }
172 
173  AutoPtr<NetworkTermList> tlist(
174  new NetworkTermList(doclen, doccount,
176  did));
177  vector<NetworkTermListItem> & items = tlist->items;
178 
179  string term;
180  while (get_message_or_done(message, REPLY_TERMLIST)) {
181  NetworkTermListItem item;
182  p = message.data();
183  p_end = p + message.size();
184  decode_length(&p, p_end, item.wdf);
185  decode_length(&p, p_end, item.termfreq);
186  term.resize(size_t(static_cast<unsigned char>(*p++)));
187  term.append(p, p_end);
188  item.tname = term;
189  items.push_back(item);
190  }
191 
192  tlist->current_position = tlist->items.begin();
193  return tlist.release();
194 }
195 
196 TermList *
197 RemoteDatabase::open_allterms(const string & prefix) const {
198  // Ensure that total_length and doccount are up-to-date.
200 
201  send_message(MSG_ALLTERMS, prefix);
202 
203  AutoPtr<NetworkTermList> tlist(
204  new NetworkTermList(0, doccount,
206  0));
207  vector<NetworkTermListItem> & items = tlist->items;
208 
209  string term = prefix;
210  string message;
211  while (get_message_or_done(message, REPLY_ALLTERMS)) {
212  NetworkTermListItem item;
213  const char * p = message.data();
214  const char * p_end = p + message.size();
215  decode_length(&p, p_end, item.termfreq);
216  term.resize(size_t(static_cast<unsigned char>(*p++)));
217  term.append(p, p_end);
218  item.tname = term;
219  items.push_back(item);
220  }
221 
222  tlist->current_position = tlist->items.begin();
223  return tlist.release();
224 }
225 
226 LeafPostList *
227 RemoteDatabase::open_post_list(const string &term) const
228 {
230 }
231 
233 RemoteDatabase::read_post_list(const string &term, NetworkPostList & pl) const
234 {
235  send_message(MSG_POSTLIST, term);
236 
237  string message;
239 
240  const char * p = message.data();
241  const char * p_end = p + message.size();
242  Xapian::doccount termfreq;
243  decode_length(&p, p_end, termfreq);
244 
245  while (get_message_or_done(message, REPLY_POSTLISTITEM)) {
246  pl.append_posting(message);
247  }
248 
249  return termfreq;
250 }
251 
252 PositionList *
253 RemoteDatabase::open_position_list(Xapian::docid did, const string &term) const
254 {
256 
257  vector<Xapian::termpos> positions;
258 
259  string message;
260  Xapian::termpos lastpos = static_cast<Xapian::termpos>(-1);
261  while (get_message_or_done(message, REPLY_POSITIONLIST)) {
262  const char * p = message.data();
263  const char * p_end = p + message.size();
264  Xapian::termpos inc;
265  decode_length(&p, p_end, inc);
266  lastpos += inc + 1;
267  positions.push_back(lastpos);
268  }
269 
270  return new InMemoryPositionList(positions);
271 }
272 
273 bool
275 {
277  return has_positional_info;
278 }
279 
280 bool
282 {
284  return update_stats(MSG_REOPEN);
285 }
286 
287 void
289 {
290  do_close();
291 }
292 
293 // Currently lazy is used:
294 //
295 // * To implement API flag Xapian::DOC_ASSUME_VALID which can be specified when
296 // calling method Database::get_document()
297 //
298 // * To read values for backends without streamed values in SlowValueList
299 //
300 // * If you call get_data(), values_begin() or values_count() on a Document
301 // object passed to a KeyMaker, MatchDecider, MatchSpy during the match
302 //
303 // The first is relevant to the remote backend, but doesn't happen during
304 // the match.
305 //
306 // SlowValueList is used with the remote backend, but not to read values
307 // during the match.
308 //
309 // KeyMaker and MatchSpy happens on the server with the remote backend, so
310 // they aren't relevant here.
311 //
312 // So the cases which are relevant to the remote backend don't matter during
313 // the match, and so we can ignore the lazy flag here without affecting matcher
314 // performance.
317 {
318  Assert(did);
319 
321  string doc_data;
322  map<Xapian::valueno, string> values;
323  get_message(doc_data, REPLY_DOCDATA);
324 
325  string message;
326  while (get_message_or_done(message, REPLY_VALUE)) {
327  const char * p = message.data();
328  const char * p_end = p + message.size();
329  Xapian::valueno slot;
330  decode_length(&p, p_end, slot);
331  values.insert(make_pair(slot, string(p, p_end)));
332  }
333 
334  return new RemoteDocument(this, did, doc_data, values);
335 }
336 
337 bool
338 RemoteDatabase::update_stats(message_type msg_code, const string & body) const
339 {
340  // MSG_MAX signals that we're handling the opening greeting, which isn't in
341  // response to an explicit message.
342  if (msg_code != MSG_MAX)
343  send_message(msg_code, body);
344 
345  string message;
346  if (!get_message_or_done(message, REPLY_UPDATE)) {
347  // The database was already open at the latest revision.
348  return false;
349  }
350 
351  if (message.size() < 3) {
353  }
354  const char *p = message.c_str();
355  const char *p_end = p + message.size();
356 
357  // The protocol major versions must match. The protocol minor version of
358  // the server must be >= that of the client.
359  int protocol_major = static_cast<unsigned char>(*p++);
360  int protocol_minor = static_cast<unsigned char>(*p++);
361  if (protocol_major != XAPIAN_REMOTE_PROTOCOL_MAJOR_VERSION ||
362  protocol_minor < XAPIAN_REMOTE_PROTOCOL_MINOR_VERSION) {
363  string errmsg("Server supports protocol version");
364  if (protocol_minor) {
365  errmsg += "s ";
366  errmsg += str(protocol_major);
367  errmsg += ".0 to ";
368  } else {
369  errmsg += ' ';
370  }
371  errmsg += str(protocol_major);
372  errmsg += '.';
373  errmsg += str(protocol_minor);
374  errmsg +=
375  " - client is using "
377  "."
379  throw Xapian::NetworkError(errmsg, context);
380  }
381 
382  decode_length(&p, p_end, doccount);
383  decode_length(&p, p_end, lastdocid);
384  lastdocid += doccount;
385  decode_length(&p, p_end, doclen_lbound);
386  decode_length(&p, p_end, doclen_ubound);
388  if (p == p_end) {
389  throw Xapian::NetworkError("Bad stats update message received", context);
390  }
391  has_positional_info = (*p++ == '1');
392  decode_length(&p, p_end, total_length);
393  uuid.assign(p, p_end);
394  cached_stats_valid = true;
395  return true;
396 }
397 
400 {
402  return doccount;
403 }
404 
407 {
409  return lastdocid;
410 }
411 
414 {
416  return total_length;
417 }
418 
419 bool
420 RemoteDatabase::term_exists(const string & tname) const
421 {
422  Assert(!tname.empty());
424  string message;
425  reply_type type = get_message(message,
428  return (type == REPLY_TERMEXISTS);
429 }
430 
431 void
432 RemoteDatabase::get_freqs(const string & term,
433  Xapian::doccount * termfreq_ptr,
434  Xapian::termcount * collfreq_ptr) const
435 {
436  Assert(!term.empty());
437  string message;
438  const char * p;
439  const char * p_end;
440  if (termfreq_ptr) {
441  if (collfreq_ptr) {
442  send_message(MSG_FREQS, term);
443  get_message(message, REPLY_FREQS);
444  } else {
445  send_message(MSG_TERMFREQ, term);
446  get_message(message, REPLY_TERMFREQ);
447  }
448  p = message.data();
449  p_end = p + message.size();
450  decode_length(&p, p_end, *termfreq_ptr);
451  } else if (collfreq_ptr) {
452  send_message(MSG_COLLFREQ, term);
453  get_message(message, REPLY_COLLFREQ);
454  p = message.data();
455  p_end = p + message.size();
456  }
457  if (collfreq_ptr) {
458  decode_length(&p, p_end, *collfreq_ptr);
459  }
460 }
461 
462 void
464 {
465  if (mru_slot != slot) {
467  string message;
468  get_message(message, REPLY_VALUESTATS);
469  const char * p = message.data();
470  const char * p_end = p + message.size();
471  mru_slot = slot;
472  decode_length(&p, p_end, mru_valstats.freq);
473  size_t len;
474  decode_length_and_check(&p, p_end, len);
475  mru_valstats.lower_bound.assign(p, len);
476  p += len;
477  decode_length_and_check(&p, p_end, len);
478  mru_valstats.upper_bound.assign(p, len);
479  p += len;
480  if (p != p_end) {
481  throw Xapian::NetworkError("Bad REPLY_VALUESTATS message received", context);
482  }
483  }
484 }
485 
488 {
489  read_value_stats(slot);
490  return mru_valstats.freq;
491 }
492 
493 std::string
495 {
496  read_value_stats(slot);
497  return mru_valstats.lower_bound;
498 }
499 
500 std::string
502 {
503  read_value_stats(slot);
504  return mru_valstats.upper_bound;
505 }
506 
509 {
510  return doclen_lbound;
511 }
512 
515 {
516  return doclen_ubound;
517 }
518 
521 {
522  // The default implementation returns get_collection_freq(), but we
523  // don't want the overhead of a remote message and reply per query
524  // term, and we can get called in the middle of a remote exchange
525  // too. FIXME: handle this bound in the stats local/remote code...
526  return doclen_ubound;
527 }
528 
531 {
532  Assert(did != 0);
534  string message;
535  get_message(message, REPLY_DOCLENGTH);
536  const char * p = message.c_str();
537  const char * p_end = p + message.size();
538  Xapian::termcount doclen;
539  decode_length(&p, p_end, doclen);
540  if (p != p_end) {
541  throw Xapian::NetworkError("Bad REPLY_DOCLENGTH message received", context);
542  }
543  return doclen;
544 }
545 
548 {
549  Assert(did != 0);
551  string message;
552  get_message(message, REPLY_UNIQUETERMS);
553  const char * p = message.c_str();
554  const char * p_end = p + message.size();
555  Xapian::termcount doclen;
556  decode_length(&p, p_end, doclen);
557  if (p != p_end) {
558  throw Xapian::NetworkError("Bad REPLY_UNIQUETERMS message received", context);
559  }
560  return doclen;
561 }
562 
565  reply_type required_type,
566  reply_type required_type2) const
567 {
569  int type = link.get_message(result, end_time);
570  if (pending_reply >= 0 && !is_intermediate_reply(pending_reply, type)) {
571  pending_reply = -1;
572  }
573  if (type < 0)
575  if (rare(type) >= REPLY_MAX) {
576  if (required_type == REPLY_UPDATE)
578  string errmsg("Invalid reply type ");
579  errmsg += str(type);
580  throw Xapian::NetworkError(errmsg);
581  }
582  if (type == REPLY_EXCEPTION) {
583  unserialise_error(result, "REMOTE:", context);
584  }
585  if (type != required_type && type != required_type2) {
586  string errmsg("Expecting reply type ");
587  errmsg += str(int(required_type));
588  if (required_type2 != required_type) {
589  errmsg += " or ";
590  errmsg += str(int(required_type2));
591  }
592  errmsg += ", got ";
593  errmsg += str(type);
594  throw Xapian::NetworkError(errmsg);
595  }
596 
597  return static_cast<reply_type>(type);
598 }
599 
600 void
601 RemoteDatabase::send_message(message_type type, const string &message) const
602 {
604  while (pending_reply >= 0) {
605  string dummy;
606  int reply_code = link.get_message(dummy, end_time);
607  if (reply_code < 0)
609  if (!is_intermediate_reply(pending_reply, reply_code)) {
610  pending_reply = -1;
611  }
612  }
613  link.send_message(static_cast<unsigned char>(type), message, end_time);
614  if (type == MSG_REMOVESPELLING) {
615  // MSG_REMOVESPELLING is the only message we send which doesn't expect
616  // a reply (except MSG_SHUTDOWN which causes us to exit anyway).
617  pending_reply = -1;
618  } else {
619  pending_reply = int(type);
620  }
621 }
622 
623 void
625 {
626  // In the constructor, we set transaction_state to
627  // TRANSACTION_UNIMPLEMENTED if we aren't writable so that we can check
628  // it here.
629  bool writable = (transaction_state != TRANSACTION_UNIMPLEMENTED);
630 
631  if (writable) {
632  try {
633  if (transaction_active()) {
635  } else {
636  commit();
637  }
638  } catch (...) {
639  try {
640  link.do_close();
641  } catch (...) {
642  }
643  throw;
644  }
645 
646  // If we're writable, send a shutdown message to the server and wait
647  // for it to close its end of the connection so we know that changes
648  // have been written and flushed, and the database write lock released.
649  // For the non-writable case, there's no need to wait - it would just
650  // slow down searching needlessly.
651  link.shutdown();
652  }
653  link.do_close();
654 }
655 
656 void
658  Xapian::termcount qlen,
659  Xapian::doccount collapse_max,
660  Xapian::valueno collapse_key,
662  Xapian::valueno sort_key,
664  bool sort_value_forward,
665  double time_limit,
666  int percent_cutoff, double weight_cutoff,
667  const Xapian::Weight *wtscheme,
668  const Xapian::RSet &omrset,
670 {
671  string tmp = query.serialise();
672  string message = encode_length(tmp.size());
673  message += tmp;
674 
675  // Serialise assorted Enquire settings.
676  message += encode_length(qlen);
677  message += encode_length(collapse_max);
678  if (collapse_max) message += encode_length(collapse_key);
679  message += char('0' + order);
680  message += encode_length(sort_key);
681  message += char('0' + sort_by);
682  message += char('0' + sort_value_forward);
683  message += serialise_double(time_limit);
684  message += char(percent_cutoff);
685  message += serialise_double(weight_cutoff);
686 
687  tmp = wtscheme->name();
688  message += encode_length(tmp.size());
689  message += tmp;
690 
691  tmp = wtscheme->serialise();
692  message += encode_length(tmp.size());
693  message += tmp;
694 
695  tmp = serialise_rset(omrset);
696  message += encode_length(tmp.size());
697  message += tmp;
698 
699  for (auto i : matchspies) {
700  tmp = i->name();
701  if (tmp.empty()) {
702  throw Xapian::UnimplementedError("MatchSpy subclass not suitable for use with remote searches - name() method returned empty string");
703  }
704  message += encode_length(tmp.size());
705  message += tmp;
706 
707  tmp = i->serialise();
708  message += encode_length(tmp.size());
709  message += tmp;
710  }
711 
712  send_message(MSG_QUERY, message);
713 }
714 
715 bool
717 {
718  if (nowait && !link.ready_to_read()) return false;
719 
720  string message;
721  get_message(message, REPLY_STATS);
722  const char* p = message.data();
723  unserialise_stats(p, p + message.size(), out);
724 
725  return true;
726 }
727 
728 void
730  Xapian::doccount maxitems,
731  Xapian::doccount check_at_least,
732  const Xapian::Weight::Internal &stats)
733 {
734  string message = encode_length(first);
735  message += encode_length(maxitems);
736  message += encode_length(check_at_least);
737  message += serialise_stats(stats);
738  send_message(MSG_GETMSET, message);
739 }
740 
741 void
744 {
745  string message;
746  get_message(message, REPLY_RESULTS);
747  const char * p = message.data();
748  const char * p_end = p + message.size();
749 
750  for (auto i : matchspies) {
751  if (p == p_end)
752  throw Xapian::NetworkError("Expected serialised matchspy");
753  size_t len;
754  decode_length_and_check(&p, p_end, len);
755  string spyresults(p, len);
756  p += len;
757  i->merge_results(spyresults);
758  }
759  mset = unserialise_mset(p, p_end);
760 }
761 
762 void
764 {
765  if (!uncommitted_changes) return;
766 
767  send_message(MSG_COMMIT, string());
768 
769  // We need to wait for a response to ensure documents have been committed.
770  string message;
771  get_message(message, REPLY_DONE);
772 
773  uncommitted_changes = false;
774 }
775 
776 void
778 {
779  if (!uncommitted_changes) return;
780 
781  cached_stats_valid = false;
783 
784  send_message(MSG_CANCEL, string());
785  string dummy;
786  get_message(dummy, REPLY_DONE);
787 
788  uncommitted_changes = false;
789 }
790 
793 {
794  cached_stats_valid = false;
796  uncommitted_changes = true;
797 
799 
800  string message;
801  get_message(message, REPLY_ADDDOCUMENT);
802 
803  const char * p = message.data();
804  const char * p_end = p + message.size();
805  Xapian::docid did;
806  decode_length(&p, p_end, did);
807  return did;
808 }
809 
810 void
812 {
813  cached_stats_valid = false;
815  uncommitted_changes = true;
816 
818  string dummy;
819  get_message(dummy, REPLY_DONE);
820 }
821 
822 void
823 RemoteDatabase::delete_document(const std::string & unique_term)
824 {
825  cached_stats_valid = false;
827  uncommitted_changes = true;
828 
829  send_message(MSG_DELETEDOCUMENTTERM, unique_term);
830  string dummy;
831  get_message(dummy, REPLY_DONE);
832 }
833 
834 void
836  const Xapian::Document & doc)
837 {
838  cached_stats_valid = false;
840  uncommitted_changes = true;
841 
842  string message = encode_length(did);
843  message += serialise_document(doc);
844 
846  string dummy;
847  get_message(dummy, REPLY_DONE);
848 }
849 
851 RemoteDatabase::replace_document(const std::string & unique_term,
852  const Xapian::Document & doc)
853 {
854  cached_stats_valid = false;
856  uncommitted_changes = true;
857 
858  string message = encode_length(unique_term.size());
859  message += unique_term;
860  message += serialise_document(doc);
861 
863 
864  get_message(message, REPLY_ADDDOCUMENT);
865 
866  const char * p = message.data();
867  const char * p_end = p + message.size();
868  Xapian::docid did;
869  decode_length(&p, p_end, did);
870  return did;
871 }
872 
873 string
875 {
876  return uuid;
877 }
878 
879 string
880 RemoteDatabase::get_metadata(const string & key) const
881 {
883  string metadata;
884  get_message(metadata, REPLY_METADATA);
885  return metadata;
886 }
887 
888 void
889 RemoteDatabase::set_metadata(const string & key, const string & value)
890 {
891  uncommitted_changes = true;
892 
893  string data = encode_length(key.size());
894  data += key;
895  data += value;
897  string dummy;
898  get_message(dummy, REPLY_DONE);
899 }
900 
901 void
902 RemoteDatabase::add_spelling(const string & word,
903  Xapian::termcount freqinc) const
904 {
905  uncommitted_changes = true;
906 
907  string data = encode_length(freqinc);
908  data += word;
910  string dummy;
911  get_message(dummy, REPLY_DONE);
912 }
913 
914 void
916  Xapian::termcount freqdec) const
917 {
918  uncommitted_changes = true;
919 
920  string data = encode_length(freqdec);
921  data += word;
923 }
924 
925 bool
927 {
928  throw Xapian::UnimplementedError("Database::locked() not implemented for remote backend");
929 }
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:74
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
include <sys/socket.h> with portability workarounds.
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:43
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:39
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:575
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:326
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.