xapian-core  2.0.0
remoteserver.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2006-2024 Olly Betts
5  * Copyright (C) 2006,2007,2009,2010 Lemur Consulting Ltd
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (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, see
19  * <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include "remoteserver.h"
24 
25 #include "xapian/constants.h"
26 #include "xapian/database.h"
27 #include "xapian/enquire.h"
28 #include "xapian/error.h"
29 #include "xapian/matchspy.h"
30 #include "xapian/query.h"
31 #include "xapian/rset.h"
32 #include "xapian/valueiterator.h"
33 
34 #include <signal.h>
35 #include <cerrno>
36 #include <cstdlib>
37 #include <memory>
38 
39 #include "api/msetinternal.h"
40 #include "api/termlist.h"
41 #include "matcher/matcher.h"
42 #include "omassert.h"
43 #include "pack.h"
44 #include "realtime.h"
45 #include "serialise.h"
46 #include "serialise-double.h"
47 #include "serialise-error.h"
48 #include "str.h"
49 #include "stringutils.h"
50 #include "weight/weightinternal.h"
51 
52 using namespace std;
53 
54 [[noreturn]]
55 static void
57 {
58  throw Xapian::InvalidOperationError("Server is read-only");
59 }
60 
62 struct ConnectionClosed { };
63 
64 RemoteServer::RemoteServer(const vector<string>& dbpaths,
65  int fdin_, int fdout_,
66  double active_timeout_, double idle_timeout_,
67  bool writable_)
68  : RemoteConnection(fdin_, fdout_, string()),
69  writable(writable_),
70  active_timeout(active_timeout_), idle_timeout(idle_timeout_)
71 {
72  // Catch errors opening the database and propagate them to the client.
73  try {
74  Assert(!dbpaths.empty());
75  // We always open the database read-only to start with. If we're
76  // writable, the client can ask to be upgraded to write access once
77  // connected if it wants it.
78  db = new Xapian::Database(dbpaths[0]);
79  // Build a better description than Database::get_description() gives
80  // in the variable context. FIXME: improve Database::get_description()
81  // and then just use that instead.
82  context = dbpaths[0];
83 
84  vector<string>::const_iterator i(dbpaths.begin());
85  for (++i; i != dbpaths.end(); ++i) {
87  context += ' ';
88  context += *i;
89  }
90  } catch (const Xapian::Error &err) {
91  // Propagate the exception to the client.
93  // And rethrow it so our caller can log it and close the connection.
94  throw;
95  }
96 
97 #ifndef __WIN32__
98  // It's simplest to just ignore SIGPIPE. We'll still know if the
99  // connection dies because we'll get EPIPE back from write().
100  //
101  // This is OK because RemoteServer subclasses are only used in
102  // specialised programs - if we expose any of them as API classes
103  // then we should use SO_NOSIGPIPE/MSG_NOSIGNAL instead like we do
104  // on the client side.
105  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
106  throw Xapian::NetworkError("Couldn't set SIGPIPE to SIG_IGN", errno);
107 #endif
108 
109  // Send greeting message.
110  msg_update(string());
111 }
112 
114 {
115  delete db;
116  // wdb is either NULL or equal to db, so we shouldn't delete it too!
117 }
118 
120 RemoteServer::get_message(double timeout, string & result,
121  message_type required_type)
122 {
123  double end_time = RealTime::end_time(timeout);
124  int type = RemoteConnection::get_message(result, end_time);
125 
126  // Handle "shutdown connection" message here. Treat EOF here for a read-only
127  // database the same way since a read-only client just closes the
128  // connection when done.
129  if (type == MSG_SHUTDOWN || (type < 0 && wdb == NULL))
130  throw ConnectionClosed();
131  if (type < 0)
132  throw Xapian::NetworkError("Connection closed unexpectedly");
133  if (type >= MSG_MAX) {
134  string errmsg("Invalid message type ");
135  errmsg += str(type);
136  throw Xapian::NetworkError(errmsg);
137  }
138  if (required_type != MSG_MAX && type != int(required_type)) {
139  string errmsg("Expecting message type ");
140  errmsg += str(int(required_type));
141  errmsg += ", got ";
142  errmsg += str(type);
143  throw Xapian::NetworkError(errmsg);
144  }
145  return static_cast<message_type>(type);
146 }
147 
148 void
149 RemoteServer::send_message(reply_type type, string_view message)
150 {
152  unsigned char type_as_char = static_cast<unsigned char>(type);
153  RemoteConnection::send_message(type_as_char, message, end_time);
154 }
155 
156 typedef void (RemoteServer::* dispatch_func)(const string &);
157 
158 void
160 {
161  while (true) {
162  try {
163  string message;
164  size_t type = get_message(idle_timeout, message);
165  switch (type) {
166  case MSG_ALLTERMS:
167  msg_allterms(message);
168  continue;
169  case MSG_COLLFREQ:
170  msg_collfreq(message);
171  continue;
172  case MSG_DOCUMENT:
173  msg_document(message);
174  continue;
175  case MSG_TERMEXISTS:
176  msg_termexists(message);
177  continue;
178  case MSG_TERMFREQ:
179  msg_termfreq(message);
180  continue;
181  case MSG_VALUESTATS:
182  msg_valuestats(message);
183  continue;
184  case MSG_KEEPALIVE:
185  msg_keepalive(message);
186  continue;
187  case MSG_DOCLENGTH:
188  msg_doclength(message);
189  continue;
190  case MSG_QUERY:
191  msg_query(message);
192  continue;
193  case MSG_TERMLIST:
194  msg_termlist(message);
195  continue;
196  case MSG_POSITIONLIST:
197  msg_positionlist(message);
198  continue;
199  case MSG_POSTLIST:
200  msg_postlist(message);
201  continue;
202  case MSG_REOPEN:
203  msg_reopen(message);
204  continue;
205  case MSG_UPDATE:
206  msg_update(message);
207  continue;
208  case MSG_ADDDOCUMENT:
209  msg_adddocument(message);
210  continue;
211  case MSG_CANCEL:
212  msg_cancel(message);
213  continue;
215  msg_deletedocumentterm(message);
216  continue;
217  case MSG_COMMIT:
218  msg_commit(message);
219  continue;
220  case MSG_REPLACEDOCUMENT:
221  msg_replacedocument(message);
222  continue;
224  msg_replacedocumentterm(message);
225  continue;
226  case MSG_DELETEDOCUMENT:
227  msg_deletedocument(message);
228  continue;
229  case MSG_WRITEACCESS:
230  msg_writeaccess(message);
231  continue;
232  case MSG_GETMETADATA:
233  msg_getmetadata(message);
234  continue;
235  case MSG_SETMETADATA:
236  msg_setmetadata(message);
237  continue;
238  case MSG_REQUESTDOCUMENT:
239  msg_requestdocument(message);
240  continue;
241  case MSG_ADDSPELLING:
242  msg_addspelling(message);
243  continue;
244  case MSG_REMOVESPELLING:
245  msg_removespelling(message);
246  continue;
247  case MSG_METADATAKEYLIST:
248  msg_metadatakeylist(message);
249  continue;
250  case MSG_FREQS:
251  msg_freqs(message);
252  continue;
253  case MSG_UNIQUETERMS:
254  msg_uniqueterms(message);
255  continue;
256  case MSG_WDFDOCMAX:
257  msg_wdfdocmax(message);
258  continue;
260  msg_positionlistcount(message);
261  continue;
262  case MSG_RECONSTRUCTTEXT:
263  msg_reconstructtext(message);
264  continue;
265  case MSG_SYNONYMTERMLIST:
266  msg_synonymtermlist(message);
267  continue;
268  case MSG_SYNONYMKEYLIST:
269  msg_synonymkeylist(message);
270  continue;
271  case MSG_ADDSYNONYM:
272  msg_addsynonym(message);
273  continue;
274  case MSG_REMOVESYNONYM:
275  msg_removesynonym(message);
276  continue;
277  case MSG_CLEARSYNONYMS:
278  msg_clearsynonyms(message);
279  continue;
280  default: {
281  // MSG_GETMSET - used during a conversation.
282  // MSG_SHUTDOWN - handled by get_message().
283  string errmsg("Unexpected message type ");
284  errmsg += str(type);
285  throw Xapian::InvalidArgumentError(errmsg);
286  }
287  }
288  } catch (const Xapian::NetworkTimeoutError & e) {
289  try {
290  // We've had a timeout, so the client may not be listening, so
291  // set the end_time to 1 and if we can't send the message right
292  // away, just exit and the client will cope.
294  } catch (...) {
295  }
296  // And rethrow it so our caller can log it and close the
297  // connection.
298  throw;
299  } catch (const Xapian::NetworkError &) {
300  // All other network errors mean we are fatally confused and are
301  // unlikely to be able to communicate further across this
302  // connection. So we don't try to propagate the error to the
303  // client, but instead just rethrow the exception so our caller can
304  // log it and close the connection.
305  throw;
306  } catch (const Xapian::Error &e) {
307  // Propagate the exception to the client, then return to the main
308  // message handling loop.
310  } catch (ConnectionClosed &) {
311  return;
312  } catch (...) {
313  // Propagate an unknown exception to the client.
315  // And rethrow it so our caller can log it and close the
316  // connection.
317  throw;
318  }
319  }
320 }
321 
322 void
323 RemoteServer::msg_allterms(const string& message)
324 {
325  string reply;
326  string prev = message;
327  const string& prefix = message;
328  for (Xapian::TermIterator t = db->allterms_begin(prefix);
329  t != db->allterms_end(prefix);
330  ++t) {
331  const string& term = *t;
332  size_t reuse = common_prefix_length(prev, term, 255);
333  reply.append(1, char(reuse));
334  pack_uint(reply, term.size() - reuse);
335  reply.append(term, reuse, string::npos);
336  pack_uint(reply, t.get_termfreq());
337  prev = term;
338  }
340 }
341 
342 void
343 RemoteServer::msg_termlist(const string &message)
344 {
345  const char *p = message.data();
346  const char *p_end = p + message.size();
347  Xapian::docid did;
348  if (!unpack_uint_last(&p, p_end, &did)) {
349  throw Xapian::NetworkError("Bad MSG_TERMLIST");
350  }
352  Xapian::termcount num_terms = 0;
353  if (t.internal)
354  num_terms = t.internal->get_approx_size();
355  string reply;
356  pack_uint(reply, db->get_doclength(did));
357  pack_uint_last(reply, num_terms);
359 
360  reply.resize(0);
361  string prev;
362  while (t != db->termlist_end(did)) {
363  const string& term = *t;
364  size_t reuse = common_prefix_length(prev, term, 255);
365  reply.append(1, char(reuse));
366  pack_uint(reply, term.size() - reuse);
367  reply.append(term, reuse, string::npos);
368  pack_uint(reply, t.get_wdf());
369  pack_uint(reply, t.get_termfreq());
370  prev = term;
371  ++t;
372  }
374 }
375 
376 void
377 RemoteServer::msg_positionlist(const string &message)
378 {
379  const char *p = message.data();
380  const char *p_end = p + message.size();
381  Xapian::docid did;
382  if (!unpack_uint(&p, p_end, &did)) {
383  throw Xapian::NetworkError("Bad MSG_POSITIONLIST");
384  }
385  string term(p, p_end - p);
386 
387  string reply;
388  Xapian::termpos lastpos = static_cast<Xapian::termpos>(-1);
390  i != db->positionlist_end(did, term);
391  ++i) {
392  Xapian::termpos pos = *i;
393  pack_uint(reply, UNSIGNED_OVERFLOW_OK(pos - lastpos - 1));
394  lastpos = pos;
395  }
397 }
398 
399 void
401 {
402  const char *p = message.data();
403  const char *p_end = p + message.size();
404  Xapian::docid did;
405  if (!unpack_uint(&p, p_end, &did)) {
406  throw Xapian::NetworkError("Bad MSG_POSITIONLISTCOUNT");
407  }
408 
409  // This is kind of clumsy, but what the public API requires.
410  Xapian::termcount result = 0;
411  Xapian::TermIterator termit = db->termlist_begin(did);
412  if (termit != db->termlist_end(did)) {
413  string term(p, p_end - p);
414  termit.skip_to(term);
415  if (termit != db->termlist_end(did) && *termit == term) {
416  result = termit.positionlist_count();
417  }
418  }
419  string reply;
420  pack_uint_last(reply, result);
422 }
423 
424 void
425 RemoteServer::msg_postlist(const string &message)
426 {
427  const string & term = message;
428 
429  Xapian::doccount termfreq = db->get_termfreq(term);
430  string reply;
431  pack_uint_last(reply, termfreq);
433 
434  reply.resize(0);
435  Xapian::docid lastdocid = 0;
437  i != db->postlist_end(term);
438  ++i) {
439  Xapian::docid newdocid = *i;
440  pack_uint(reply, newdocid - lastdocid - 1);
441  pack_uint(reply, i.get_wdf());
442 
443  lastdocid = newdocid;
444  }
445 
447 }
448 
449 void
450 RemoteServer::msg_writeaccess(const string & msg)
451 {
452  if (!writable)
453  throw_read_only();
454 
455  int flags = 0;
456  const char *p = msg.c_str();
457  const char *p_end = p + msg.size();
458  if (p != p_end) {
459  unsigned flag_bits;
460  if (!unpack_uint_last(&p, p_end, &flag_bits)) {
461  throw Xapian::NetworkError("Bad flags in MSG_WRITEACCESS");
462  }
463  flags = flag_bits &~ Xapian::DB_ACTION_MASK_;
464  }
465 
466  wdb = new Xapian::WritableDatabase(db->lock(flags));
467  delete db;
468  db = wdb;
469  msg_update(msg);
470 }
471 
472 void
473 RemoteServer::msg_reopen(const string & msg)
474 {
475  if (!db->reopen()) {
477  return;
478  }
479  msg_update(msg);
480 }
481 
482 void
484 {
485  static const char protocol[2] = {
488  };
489  string message(protocol, 2);
490  Xapian::doccount num_docs = db->get_doccount();
491  pack_uint(message, num_docs);
492  pack_uint(message, db->get_lastdocid() - num_docs);
494  pack_uint(message, doclen_lb);
495  pack_uint(message, db->get_doclength_upper_bound() - doclen_lb);
496  pack_bool(message, db->has_positions());
497  pack_uint(message, db->get_total_length());
498  message += db->get_uuid();
499  send_message(REPLY_UPDATE, message);
500 }
501 
502 void
503 RemoteServer::msg_query(const string &message_in)
504 {
505  const char *p = message_in.c_str();
506  const char *p_end = p + message_in.size();
507 
508  // Unserialise the Query.
509  string serialisation;
510  if (!unpack_string(&p, p_end, serialisation)) {
511  throw Xapian::NetworkError("Bad MSG_QUERY");
512  }
513 
515 
516  // Unserialise assorted Enquire settings.
517  Xapian::termcount qlen;
518  Xapian::valueno collapse_max;
519  if (!unpack_uint(&p, p_end, &qlen) ||
520  !unpack_uint(&p, p_end, &collapse_max)) {
521  throw Xapian::NetworkError("Bad MSG_QUERY");
522  }
523 
524  Xapian::valueno collapse_key = Xapian::BAD_VALUENO;
525  if (collapse_max) {
526  if (!unpack_uint(&p, p_end, &collapse_key)) {
527  throw Xapian::NetworkError("Bad MSG_QUERY");
528  }
529  }
530 
531  if (p_end - p < 4 || static_cast<unsigned char>(*p) > 2) {
532  throw Xapian::NetworkError("bad message (docid_order)");
533  }
535  order = static_cast<Xapian::Enquire::docid_order>(*p++);
536 
537  if (static_cast<unsigned char>(*p) > 3) {
538  throw Xapian::NetworkError("bad message (sort_by)");
539  }
541  sort_by = static_cast<Xapian::Enquire::Internal::sort_setting>(*p++);
542 
544  if (sort_by != Xapian::Enquire::Internal::REL) {
545  if (!unpack_uint(&p, p_end, &sort_key)) {
546  throw Xapian::NetworkError("Bad MSG_QUERY");
547  }
548  }
549 
550  bool sort_value_forward;
551  if (!unpack_bool(&p, p_end, &sort_value_forward)) {
552  throw Xapian::NetworkError("bad message (sort_value_forward)");
553  }
554 
555  double time_limit = unserialise_double(&p, p_end);
556 
557  int percent_threshold = *p++;
558  if (percent_threshold < 0 || percent_threshold > 100) {
559  throw Xapian::NetworkError("bad message (percent_threshold)");
560  }
561 
562  double weight_threshold = unserialise_double(&p, p_end);
563  if (weight_threshold < 0) {
564  throw Xapian::NetworkError("bad message (weight_threshold)");
565  }
566 
567  // Unserialise the Weight object.
568  string wtname;
569  if (!unpack_string(&p, p_end, wtname)) {
570  throw Xapian::NetworkError("Bad MSG_QUERY");
571  }
572 
573  const Xapian::Weight * wttype = reg.get_weighting_scheme(wtname);
574  if (wttype == NULL) {
575  // Note: user weighting schemes should be registered by adding them to
576  // a Registry, and setting the context using
577  // RemoteServer::set_registry().
578  throw Xapian::InvalidArgumentError("Weighting scheme " +
579  wtname + " not registered");
580  }
581 
582  if (!unpack_string(&p, p_end, serialisation)) {
583  throw Xapian::NetworkError("Bad MSG_QUERY");
584  }
585  unique_ptr<Xapian::Weight> wt(wttype->unserialise(serialisation));
586 
587  // Unserialise the RSet object.
588  if (!unpack_string(&p, p_end, serialisation)) {
589  throw Xapian::NetworkError("Bad MSG_QUERY");
590  }
591  Xapian::RSet rset = unserialise_rset(serialisation);
592 
593  // Unserialise any MatchSpy objects.
594  vector<Xapian::Internal::opt_intrusive_ptr<Xapian::MatchSpy>> matchspies;
595  while (p != p_end) {
596  string spytype;
597  if (!unpack_string(&p, p_end, spytype)) {
598  throw Xapian::NetworkError("Bad MSG_QUERY");
599  }
600  const Xapian::MatchSpy * spyclass = reg.get_match_spy(spytype);
601  if (spyclass == NULL) {
602  throw Xapian::InvalidArgumentError("Match spy " + spytype +
603  " not registered");
604  }
605 
606  if (!unpack_string(&p, p_end, serialisation)) {
607  throw Xapian::NetworkError("Bad MSG_QUERY");
608  }
609  matchspies.push_back(spyclass->unserialise(serialisation,
610  reg)->release());
611  }
612 
613  Xapian::Weight::Internal local_stats;
614  Matcher matcher(*db,
615  query, qlen, &rset, local_stats, *wt,
616  false,
617  collapse_key, collapse_max,
618  percent_threshold, weight_threshold,
619  order, sort_key, sort_by, sort_value_forward, time_limit,
620  matchspies);
621 
623 
624  string message;
626  p = message.c_str();
627  p_end = p + message.size();
628 
629  Xapian::termcount first;
630  Xapian::termcount maxitems;
631  Xapian::termcount check_at_least;
632  string sorter_type;
633  if (!unpack_uint(&p, p_end, &first) ||
634  !unpack_uint(&p, p_end, &maxitems) ||
635  !unpack_uint(&p, p_end, &check_at_least) ||
636  !unpack_string(&p, p_end, sorter_type)) {
637  throw Xapian::NetworkError("Bad MSG_GETMSET");
638  }
639  unique_ptr<Xapian::KeyMaker> sorter;
640  if (!sorter_type.empty()) {
641  const Xapian::KeyMaker* sorterclass = reg.get_key_maker(sorter_type);
642  if (sorterclass == NULL) {
643  throw Xapian::InvalidArgumentError("KeyMaker " + sorter_type +
644  " not registered");
645  }
646 
647  string serialised_sorter;
648  if (!unpack_string(&p, p_end, serialised_sorter)) {
649  throw Xapian::NetworkError("Bad MSG_GETMSET");
650  }
651  sorter.reset(sorterclass->unserialise(serialised_sorter, reg));
652  }
653 
654  unique_ptr<Xapian::Weight::Internal> total_stats(new Xapian::Weight::Internal);
655  unserialise_stats(p, p_end, *total_stats);
656 
657  Xapian::MSet mset = matcher.get_mset(first, maxitems, check_at_least,
658  *total_stats, *wt, 0, sorter.get(),
659  collapse_key, collapse_max,
660  percent_threshold, weight_threshold,
661  order,
662  sort_key, sort_by, sort_value_forward,
663  time_limit, matchspies);
664  // FIXME: The local side already has these stats, except for the maxpart
665  // information.
666  mset.internal->set_stats(total_stats.release());
667 
668  message.resize(0);
669  for (auto i : matchspies) {
670  pack_string(message, i->serialise_results());
671  }
672  message += mset.internal->serialise();
673  send_message(REPLY_RESULTS, message);
674 }
675 
676 void
677 RemoteServer::msg_document(const string &message)
678 {
679  const char *p = message.data();
680  const char *p_end = p + message.size();
681  Xapian::docid did;
682  if (!unpack_uint_last(&p, p_end, &did)) {
683  throw Xapian::NetworkError("Bad MSG_DOCUMENT");
684  }
685 
686  Xapian::Document doc = db->get_document(did);
687 
689 
691  for (i = doc.values_begin(); i != doc.values_end(); ++i) {
692  string item;
693  pack_uint(item, i.get_valueno());
694  item += *i;
695  send_message(REPLY_VALUE, item);
696  }
698 }
699 
700 void
702 {
703  // Ensure *our* database stays alive, as it may contain remote databases!
704  db->keep_alive();
706 }
707 
708 void
710 {
712  : REPLY_TERMDOESNTEXIST), {});
713 }
714 
715 void
717 {
718  string reply;
721 }
722 
723 void
725 {
726  string reply;
729 }
730 
731 void
733 {
734  string msg;
735  pack_uint(msg, db->get_termfreq(term));
738 }
739 
740 void
741 RemoteServer::msg_valuestats(const string & message)
742 {
743  const char *p = message.data();
744  const char *p_end = p + message.size();
745  Xapian::valueno slot;
746  if (!unpack_uint_last(&p, p_end, &slot)) {
747  throw Xapian::NetworkError("Bad MSG_VALUESTATS");
748  }
749  string message_out;
750  pack_uint(message_out, db->get_value_freq(slot));
751  pack_string(message_out, db->get_value_lower_bound(slot));
752  message_out += db->get_value_upper_bound(slot);
753 
754  send_message(REPLY_VALUESTATS, message_out);
755 }
756 
757 void
758 RemoteServer::msg_doclength(const string &message)
759 {
760  const char *p = message.data();
761  const char *p_end = p + message.size();
762  Xapian::docid did;
763  if (!unpack_uint_last(&p, p_end, &did)) {
764  throw Xapian::NetworkError("Bad MSG_DOCLENGTH");
765  }
766  string reply;
767  pack_uint_last(reply, db->get_doclength(did));
769 }
770 
771 void
772 RemoteServer::msg_uniqueterms(const string &message)
773 {
774  const char *p = message.data();
775  const char *p_end = p + message.size();
776  Xapian::docid did;
777  if (!unpack_uint_last(&p, p_end, &did)) {
778  throw Xapian::NetworkError("Bad MSG_UNIQUETERMS");
779  }
780  string reply;
781  pack_uint_last(reply, db->get_unique_terms(did));
783 }
784 
785 void
786 RemoteServer::msg_wdfdocmax(const string& message)
787 {
788  const char* p = message.data();
789  const char* p_end = p + message.size();
790  Xapian::docid did;
791  if (!unpack_uint_last(&p, p_end, &did)) {
792  throw Xapian::NetworkError("Bad MSG_WDFDOCMAX");
793  }
794  string reply;
795  pack_uint_last(reply, db->get_wdfdocmax(did));
797 }
798 
799 void
800 RemoteServer::msg_reconstructtext(const string& message)
801 {
802  const char* p = message.data();
803  const char* p_end = p + message.size();
804  Xapian::docid did;
805  size_t length;
806  Xapian::termpos start_pos, end_pos;
807  if (!unpack_uint(&p, p_end, &did) ||
808  !unpack_uint(&p, p_end, &length) ||
809  !unpack_uint(&p, p_end, &start_pos) ||
810  !unpack_uint(&p, p_end, &end_pos)) {
811  throw Xapian::NetworkError("Bad MSG_RECONSTRUCTTEXT");
812  }
814  db->reconstruct_text(did, length, {p, size_t(p_end - p)},
815  start_pos, end_pos));
816 }
817 
818 void
820 {
821  if (!wdb)
822  throw_read_only();
823 
824  wdb->commit();
825 
827 }
828 
829 void
831 {
832  if (!wdb)
833  throw_read_only();
834 
835  // We can't call cancel since that's an internal method, but this
836  // has the same effect with minimal additional overhead.
837  wdb->begin_transaction(false);
839 
841 }
842 
843 void
844 RemoteServer::msg_adddocument(const string & message)
845 {
846  if (!wdb)
847  throw_read_only();
848 
850 
851  string reply;
852  pack_uint_last(reply, did);
854 }
855 
856 void
857 RemoteServer::msg_deletedocument(const string & message)
858 {
859  if (!wdb)
860  throw_read_only();
861 
862  const char *p = message.data();
863  const char *p_end = p + message.size();
864  Xapian::docid did;
865  if (!unpack_uint_last(&p, p_end, &did)) {
866  throw Xapian::NetworkError("Bad MSG_DELETEDOCUMENT");
867  }
868 
869  wdb->delete_document(did);
870 
872 }
873 
874 void
876 {
877  if (!wdb)
878  throw_read_only();
879 
880  wdb->delete_document(message);
881 
883 }
884 
885 void
886 RemoteServer::msg_replacedocument(const string & message)
887 {
888  if (!wdb)
889  throw_read_only();
890 
891  const char *p = message.data();
892  const char *p_end = p + message.size();
893  Xapian::docid did;
894  if (!unpack_uint(&p, p_end, &did)) {
895  throw Xapian::NetworkError("Bad MSG_REPLACEDOCUMENT");
896  }
897 
898  wdb->replace_document(did, unserialise_document(string(p, p_end)));
899 
901 }
902 
903 void
905 {
906  if (!wdb)
907  throw_read_only();
908 
909  const char *p = message.data();
910  const char *p_end = p + message.size();
911  string unique_term;
912  if (!unpack_string(&p, p_end, unique_term)) {
913  throw Xapian::NetworkError("Bad MSG_REPLACEDOCUMENTTERM");
914  }
915  Xapian::docid did = wdb->replace_document(unique_term, unserialise_document(string(p, p_end)));
916 
917  string reply;
918  pack_uint_last(reply, did);
920 }
921 
922 void
923 RemoteServer::msg_getmetadata(const string & message)
924 {
926 }
927 
928 void
929 RemoteServer::msg_metadatakeylist(const string& message)
930 {
931  string reply;
932  string prev = message;
933  const string& prefix = message;
934  for (Xapian::TermIterator t = db->metadata_keys_begin(prefix);
935  t != db->metadata_keys_end(prefix);
936  ++t) {
937  const string& term = *t;
938  size_t reuse = common_prefix_length(prev, term, 255);
939  reply.append(1, char(reuse));
940  pack_uint(reply, term.size() - reuse);
941  reply.append(term, reuse, string::npos);
942  prev = term;
943  }
945 }
946 
947 void
948 RemoteServer::msg_setmetadata(const string & message)
949 {
950  if (!wdb)
951  throw_read_only();
952  const char *p = message.data();
953  const char *p_end = p + message.size();
954  string key;
955  if (!unpack_string(&p, p_end, key)) {
956  throw Xapian::NetworkError("Bad MSG_SETMETADATA");
957  }
958  string val(p, p_end - p);
959  wdb->set_metadata(key, val);
960 
962 }
963 
964 void
965 RemoteServer::msg_requestdocument(const string& message)
966 {
967  const char* p = message.data();
968  const char* p_end = p + message.size();
969  Xapian::docid did;
970  if (!unpack_uint_last(&p, p_end, &did)) {
971  throw Xapian::NetworkError("Bad MSG_REQUESTDOCUMENT");
972  }
973  db->internal->request_document(did);
974 
975  send_message(REPLY_DONE, string());
976 }
977 
978 void
979 RemoteServer::msg_addspelling(const string & message)
980 {
981  if (!wdb)
982  throw_read_only();
983  const char *p = message.data();
984  const char *p_end = p + message.size();
985  Xapian::termcount freqinc;
986  if (!unpack_uint(&p, p_end, &freqinc)) {
987  throw Xapian::NetworkError("Bad MSG_ADDSPELLING");
988  }
989  wdb->add_spelling(string(p, p_end - p), freqinc);
990 
992 }
993 
994 void
995 RemoteServer::msg_removespelling(const string & message)
996 {
997  if (!wdb)
998  throw_read_only();
999  const char *p = message.data();
1000  const char *p_end = p + message.size();
1001  Xapian::termcount freqdec;
1002  if (!unpack_uint(&p, p_end, &freqdec)) {
1003  throw Xapian::NetworkError("Bad MSG_REMOVESPELLING");
1004  }
1005  string reply;
1006  pack_uint_last(reply, wdb->remove_spelling(string(p, p_end - p), freqdec));
1008 }
1009 
1010 void
1012 {
1013  Xapian::TermIterator t = db->synonyms_begin(message);
1014  string reply, prev;
1015  while (t != db->synonyms_end(message)) {
1016  const string& term = *t;
1017  size_t reuse = common_prefix_length(prev, term, 255);
1018  reply.append(1, char(reuse));
1019  pack_uint(reply, term.size() - reuse);
1020  reply.append(term, reuse, string::npos);
1021  prev = term;
1022  ++t;
1023  }
1025 }
1026 
1027 void
1028 RemoteServer::msg_synonymkeylist(const string& message)
1029 {
1031  string reply, prev;
1032  while (t != db->synonym_keys_end(message)) {
1033  const string& term = *t;
1034  size_t reuse = common_prefix_length(prev, term, 255);
1035  reply.append(1, char(reuse));
1036  pack_uint(reply, term.size() - reuse);
1037  reply.append(term, reuse, string::npos);
1038  prev = term;
1039  ++t;
1040  }
1042 }
1043 
1044 void
1045 RemoteServer::msg_addsynonym(const string& message)
1046 {
1047  if (!wdb)
1048  throw_read_only();
1049  const char* p = message.data();
1050  const char* p_end = p + message.size();
1051  // Get the term
1052  string term;
1053  if (!unpack_string(&p, p_end, term)) {
1054  throw Xapian::NetworkError("Bad MSG_ADDSYNONYM");
1055  }
1056  wdb->add_synonym(term, string(p, p_end - p));
1057  send_message(REPLY_DONE, {});
1058 }
1059 
1060 void
1061 RemoteServer::msg_removesynonym(const string& message)
1062 {
1063  if (!wdb)
1064  throw_read_only();
1065  const char* p = message.data();
1066  const char* p_end = p + message.size();
1067  // Get the term
1068  string term;
1069  if (!unpack_string(&p, p_end, term)) {
1070  throw Xapian::NetworkError("Bad MSG_REMOVESYNONYM");
1071  }
1072  wdb->remove_synonym(term, string(p, p_end - p));
1073  send_message(REPLY_DONE, {});
1074 }
1075 
1076 void
1077 RemoteServer::msg_clearsynonyms(const string& message)
1078 {
1079  if (!wdb)
1080  throw_read_only();
1081  wdb->clear_synonyms(message);
1082  send_message(REPLY_DONE, {});
1083 }
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:62
Xapian::MSet get_mset(Xapian::doccount first, Xapian::doccount maxitems, Xapian::doccount check_at_least, Xapian::Weight::Internal &stats, const Xapian::Weight &wtscheme, const Xapian::MatchDecider *mdecider, const Xapian::KeyMaker *sorter, Xapian::valueno collapse_key, Xapian::doccount collapse_max, int percent_threshold, double weight_threshold, Xapian::Enquire::docid_order order, Xapian::valueno sort_key, Xapian::Enquire::Internal::sort_setting sort_by, bool sort_val_reverse, double time_limit, const std::vector< opt_ptr_spy > &matchspies)
Run the match and produce an MSet object.
Definition: matcher.cc:577
A RemoteConnection object provides a bidirectional connection to another RemoteConnection object on a...
void send_message(char type, std::string_view s, double end_time)
Send a message.
int get_message(std::string &result, double end_time)
Read one message from fdin.
std::string context
The context to report with errors.
Remote backend server base class.
Definition: remoteserver.h:36
void msg_reconstructtext(const std::string &message)
void msg_adddocument(const std::string &message)
void msg_removespelling(const std::string &message)
void msg_deletedocument(const std::string &message)
double idle_timeout
Timeout while waiting for a new action from the client.
Definition: remoteserver.h:67
void msg_writeaccess(const std::string &message)
Xapian::Registry reg
The registry, which allows unserialisation of user subclasses.
Definition: remoteserver.h:70
Xapian::Database * db
The database we're using.
Definition: remoteserver.h:47
void msg_update(const std::string &message)
void msg_addsynonym(const std::string &message)
void msg_metadatakeylist(const std::string &message)
double active_timeout
Timeout for actions during a conversation.
Definition: remoteserver.h:60
void msg_setmetadata(const std::string &message)
message_type get_message(double timeout, std::string &result, message_type required_type=MSG_MAX)
Accept a message from the client.
void msg_replacedocument(const std::string &message)
void msg_keepalive(const std::string &message)
void msg_termlist(const std::string &message)
void msg_cancel(const std::string &message)
void msg_addspelling(const std::string &message)
void msg_getmetadata(const std::string &message)
void msg_document(const std::string &message)
void msg_deletedocumentterm(const std::string &message)
void msg_freqs(const std::string &message)
bool writable
Do we support writing?
Definition: remoteserver.h:53
void msg_wdfdocmax(const std::string &message)
Xapian::WritableDatabase * wdb
The WritableDatabase we're using, or NULL if we're read-only.
Definition: remoteserver.h:50
void msg_reopen(const std::string &message)
RemoteServer(const RemoteServer &)
Don't allow copying.
void msg_postlist(const std::string &message)
void msg_synonymkeylist(const std::string &message)
void msg_collfreq(const std::string &message)
void msg_termexists(const std::string &message)
void msg_valuestats(const std::string &message)
void msg_doclength(const std::string &message)
void msg_allterms(const std::string &message)
void msg_commit(const std::string &message)
~RemoteServer()
Destructor.
void msg_query(const std::string &message)
void msg_termfreq(const std::string &message)
void msg_positionlist(const std::string &message)
void msg_uniqueterms(const std::string &message)
void msg_synonymtermlist(const std::string &message)
void run()
Repeatedly accept messages from the client and process them.
void msg_positionlistcount(const std::string &message)
void send_message(reply_type type, std::string_view message)
Send a message to the client.
void msg_requestdocument(const std::string &message)
void msg_removesynonym(const std::string &message)
void msg_replacedocumentterm(const std::string &message)
void msg_clearsynonyms(const std::string &message)
An indexed database of documents.
Definition: database.h:75
Xapian::TermIterator metadata_keys_begin(std::string_view prefix={}) const
An iterator which returns all user-specified metadata keys.
Definition: database.cc:499
Xapian::doccount get_termfreq(std::string_view term) const
Get the number of documents indexed by a specified term.
Definition: database.cc:262
Xapian::TermIterator synonym_keys_begin(std::string_view prefix={}) const
An iterator which returns all terms which have synonyms.
Definition: database.cc:484
Xapian::totallength get_total_length() const
Get the total length of all the documents in the database.
Definition: database.cc:256
PositionIterator positionlist_end(Xapian::docid, std::string_view) const noexcept
End iterator corresponding to positionlist_begin().
Definition: database.h:292
Xapian::WritableDatabase lock(int flags=0)
Lock a read-only database for writing.
Definition: database.cc:517
Xapian::termcount get_doclength_lower_bound() const
Get a lower bound on the length of a document in this DB.
Definition: database.cc:302
PostingIterator postlist_begin(std::string_view term) const
Start iterating the postings of a term.
Definition: database.cc:192
std::string reconstruct_text(Xapian::docid did, size_t length=0, std::string_view prefix={}, Xapian::termpos start_pos=0, Xapian::termpos end_pos=0) const
Reconstruct document text.
Definition: database.cc:533
TermIterator termlist_begin(Xapian::docid did) const
Start iterating the terms in a document.
Definition: database.cc:200
Xapian::termcount get_wdfdocmax(Xapian::docid did) const
Get the maximum wdf value in a specified document.
Definition: database.cc:359
void keep_alive()
Send a keep-alive message.
Definition: database.cc:385
PositionIterator positionlist_begin(Xapian::docid did, std::string_view term) const
Start iterating positions for a term in a document.
Definition: database.cc:221
std::string get_value_upper_bound(Xapian::valueno slot) const
Get an upper bound on the values stored in the given value slot.
Definition: database.cc:296
Xapian::TermIterator synonyms_end(std::string_view) const noexcept
End iterator corresponding to synonyms_begin(term).
Definition: database.h:514
void add_database(const Database &other)
Add shards from another Database.
Definition: database.h:109
Xapian::TermIterator synonym_keys_end(std::string_view={}) const noexcept
End iterator corresponding to synonym_keys_begin(prefix).
Definition: database.h:526
Xapian::termcount get_doclength(Xapian::docid did) const
Get the length of a specified document.
Definition: database.cc:341
Xapian::TermIterator metadata_keys_end(std::string_view={}) const noexcept
End iterator corresponding to metadata_keys_begin().
Definition: database.h:576
bool term_exists(std::string_view term) const
Test is a particular term is present in any document.
Definition: database.cc:378
std::string get_value_lower_bound(Xapian::valueno slot) const
Get a lower bound on the values stored in the given value slot.
Definition: database.cc:290
TermIterator allterms_end(std::string_view={}) const noexcept
End iterator corresponding to allterms_begin(prefix).
Definition: database.h:307
bool has_positions() const
Does this database have any positional information?
Definition: database.cc:215
Xapian::termcount get_collection_freq(std::string_view term) const
Get the total number of occurrences of a specified term.
Definition: database.cc:273
Xapian::doccount get_doccount() const
Get the number of documents in the database.
Definition: database.cc:233
PostingIterator postlist_end(std::string_view) const noexcept
End iterator corresponding to postlist_begin().
Definition: database.h:258
TermIterator termlist_end(Xapian::docid) const noexcept
End iterator corresponding to termlist_begin().
Definition: database.h:271
Xapian::docid get_lastdocid() const
Get the highest document id which has been used in the database.
Definition: database.cc:239
Xapian::doccount get_value_freq(Xapian::valueno slot) const
Return the frequency of a given value slot.
Definition: database.cc:284
TermIterator allterms_begin(std::string_view prefix={}) const
Start iterating all terms in the database with a given prefix.
Definition: database.cc:209
Xapian::TermIterator synonyms_begin(std::string_view term) const
An iterator which returns all the synonyms for a given term.
Definition: database.cc:478
bool reopen()
Reopen the database at the latest available revision.
Definition: database.cc:93
Xapian::termcount get_doclength_upper_bound() const
Get an upper bound on the length of a document in this DB.
Definition: database.cc:308
Xapian::Document get_document(Xapian::docid did, unsigned flags=0) const
Get a document from the database.
Definition: database.cc:368
std::string get_uuid() const
Get the UUID for the database.
Definition: database.cc:505
Xapian::Internal::intrusive_ptr_nonnull< Internal > internal
Definition: database.h:95
std::string get_metadata(std::string_view key) const
Get the user-specified metadata associated with a given key.
Definition: database.cc:490
Xapian::termcount get_unique_terms(Xapian::docid did) const
Get the number of unique terms in a specified document.
Definition: database.cc:350
Class representing a document.
Definition: document.h:64
std::string get_data() const
Get the document data.
Definition: document.cc:75
ValueIterator values_begin() const
Start iterating the values in this document.
Definition: document.cc:208
ValueIterator values_end() const noexcept
End iterator corresponding to values_begin().
Definition: document.h:259
docid_order
Ordering of docids.
Definition: enquire.h:130
All exceptions thrown by Xapian are subclasses of Xapian::Error.
Definition: error.h:41
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:229
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:271
Virtual base class for key making functors.
Definition: keymaker.h:44
virtual KeyMaker * unserialise(const std::string &serialised, const Registry &context) const
Unserialise parameters.
Definition: keymaker.cc:62
Class representing a list of search results.
Definition: mset.h:46
Xapian::Internal::intrusive_ptr_nonnull< Internal > internal
Definition: mset.h:78
Abstract base class for match spies.
Definition: matchspy.h:50
MatchSpy * release()
Start reference counting this object.
Definition: matchspy.h:184
virtual MatchSpy * unserialise(const std::string &serialised, const Registry &context) const
Unserialise parameters.
Definition: matchspy.cc:67
Indicates a problem communicating with a remote database.
Definition: error.h:791
Indicates a timeout expired while communicating with a remote database.
Definition: error.h:833
Class for iterating over term positions.
Class for iterating over a list of terms.
Class representing a query.
Definition: query.h:45
static const Query unserialise(std::string_view serialised, const Registry &reg=Registry())
Unserialise a string and return a Query object.
Definition: query.cc:265
Class representing a set of documents judged as relevant.
Definition: rset.h:39
const Xapian::MatchSpy * get_match_spy(std::string_view name) const
Get a match spy given a name.
Definition: registry.cc:345
const Xapian::Weight * get_weighting_scheme(std::string_view name) const
Get the weighting scheme given a name.
Definition: registry.cc:317
const Xapian::KeyMaker * get_key_maker(std::string_view name) const
Get a KeyMaker given a name.
Definition: registry.cc:373
virtual Xapian::termcount get_approx_size() const =0
Return approximate size of this termlist.
Class for iterating over a list of terms.
Definition: termiterator.h:41
void skip_to(std::string_view term)
Advance the iterator to term term.
Xapian::doccount get_termfreq() const
Return the term frequency for the term at the current position.
Xapian::termcount positionlist_count() const
Return the length of the position list for the current position.
Xapian::termcount get_wdf() const
Return the wdf for the term at the current position.
Class for iterating over document values.
Definition: valueiterator.h:39
Xapian::valueno get_valueno() const
Return the value slot number for the current position.
Class to hold statistics for a given collection.
Abstract base class for weighting schemes.
Definition: weight.h:38
virtual Weight * unserialise(const std::string &serialised) const
Unserialise parameters.
Definition: weight.cc:198
This class provides read/write access to a database.
Definition: database.h:964
void delete_document(Xapian::docid did)
Delete a document from the database.
Definition: database.cc:567
void clear_synonyms(std::string_view term) const
Remove all synonyms for a term.
Definition: database.cc:628
void begin_transaction(bool flushed=true)
Begin a transaction.
Definition: database.cc:549
void add_synonym(std::string_view term, std::string_view synonym) const
Add a synonym for a term.
Definition: database.cc:614
void replace_document(Xapian::docid did, const Xapian::Document &document)
Replace a document in the database.
Definition: database.cc:582
void set_metadata(std::string_view key, std::string_view metadata)
Set the user-specified metadata associated with a given key.
Definition: database.cc:634
void cancel_transaction()
Abort the transaction currently in progress.
Definition: database.h:1206
void add_spelling(std::string_view word, Xapian::termcount freqinc=1) const
Add a word to the spelling dictionary.
Definition: database.cc:600
termcount remove_spelling(std::string_view word, termcount freqdec=1) const
Remove a word from the spelling dictionary.
Definition: database.cc:607
void commit()
Commit pending modifications.
Definition: database.cc:543
Xapian::docid add_document(const Xapian::Document &doc)
Add a document to the database.
Definition: database.cc:561
void remove_synonym(std::string_view term, std::string_view synonym) const
Remove a synonym for a term.
Definition: database.cc:621
#define UNSIGNED_OVERFLOW_OK(X)
Definition: config.h:626
Constants in the Xapian namespace.
An indexed database of documents.
string term
PositionList * p
Xapian::termpos pos
Querying session.
Hierarchy of classes which Xapian can throw as exceptions.
Matcher class.
MatchSpy implementation.
Xapian::MSet internals.
double end_time(double timeout)
Return the end time for a timeout in timeout seconds.
Definition: realtime.h:95
string str(int value)
Convert int to std::string.
Definition: str.cc:91
const valueno BAD_VALUENO
Reserved value to indicate "no valueno".
Definition: types.h:100
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:64
unsigned valueno
The number for a value slot in a document.
Definition: types.h:90
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:37
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:51
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:75
Various assertion macros.
#define Assert(COND)
Definition: omassert.h:122
Pack types into strings and unpack them again.
bool unpack_uint_last(const char **p, const char *end, U *result)
Decode an unsigned integer as the last item in a string.
Definition: pack.h:118
bool unpack_string(const char **p, const char *end, std::string &result)
Decode a std::string from a string.
Definition: pack.h:468
void pack_uint_last(std::string &s, U value)
Append an encoded unsigned integer to a string as the last item.
Definition: pack.h:100
bool unpack_bool(const char **p, const char *end, bool *result)
Decode a bool from a string.
Definition: pack.h:76
void pack_bool(std::string &s, bool value)
Append an encoded bool to a string.
Definition: pack.h:64
bool unpack_uint(const char **p, const char *end, U *result)
Decode an unsigned integer from a string.
Definition: pack.h:346
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
Definition: pack.h:315
void pack_string(std::string &s, std::string_view value)
Append an encoded std::string to a string.
Definition: pack.h:442
Xapian::Query API class.
Functions for handling a time or time interval in a double.
#define XAPIAN_REMOTE_PROTOCOL_MAJOR_VERSION
message_type
Message types (client -> server).
@ MSG_WDFDOCMAX
@ MSG_GETMSET
@ MSG_REOPEN
@ MSG_CANCEL
@ MSG_CLEARSYNONYMS
@ MSG_KEEPALIVE
@ MSG_REMOVESYNONYM
@ MSG_UPDATE
@ MSG_POSITIONLISTCOUNT
@ MSG_DELETEDOCUMENT
@ MSG_QUERY
@ MSG_WRITEACCESS
@ MSG_SHUTDOWN
@ MSG_RECONSTRUCTTEXT
@ MSG_POSITIONLIST
@ MSG_DOCLENGTH
@ MSG_VALUESTATS
@ MSG_SETMETADATA
@ MSG_TERMFREQ
@ MSG_COMMIT
@ MSG_ADDDOCUMENT
@ MSG_COLLFREQ
@ MSG_REQUESTDOCUMENT
@ MSG_FREQS
@ MSG_REPLACEDOCUMENTTERM
@ MSG_REMOVESPELLING
@ MSG_SYNONYMTERMLIST
@ MSG_GETMETADATA
@ MSG_METADATAKEYLIST
@ MSG_ALLTERMS
@ MSG_DELETEDOCUMENTTERM
@ MSG_POSTLIST
@ MSG_DOCUMENT
@ MSG_REPLACEDOCUMENT
@ MSG_TERMLIST
@ MSG_ADDSYNONYM
@ MSG_UNIQUETERMS
@ MSG_TERMEXISTS
@ MSG_SYNONYMKEYLIST
@ MSG_ADDSPELLING
@ MSG_MAX
reply_type
Reply types (server -> client).
@ REPLY_VALUE
@ REPLY_DOCDATA
@ REPLY_EXCEPTION
@ REPLY_RESULTS
@ REPLY_METADATAKEYLIST
@ REPLY_WDFDOCMAX
@ REPLY_POSITIONLISTCOUNT
@ REPLY_DONE
@ REPLY_REMOVESPELLING
@ REPLY_UNIQUETERMS
@ REPLY_SYNONYMKEYLIST
@ REPLY_POSTLIST
@ REPLY_ADDDOCUMENT
@ REPLY_TERMFREQ
@ REPLY_TERMEXISTS
@ REPLY_STATS
@ REPLY_COLLFREQ
@ REPLY_TERMLIST
@ REPLY_TERMDOESNTEXIST
@ REPLY_SYNONYMTERMLIST
@ REPLY_RECONSTRUCTTEXT
@ REPLY_DOCLENGTH
@ REPLY_POSTLISTHEADER
@ REPLY_POSITIONLIST
@ REPLY_TERMLISTHEADER
@ REPLY_FREQS
@ REPLY_UPDATE
@ REPLY_METADATA
@ REPLY_ALLTERMS
@ REPLY_VALUESTATS
#define XAPIAN_REMOTE_PROTOCOL_MINOR_VERSION
static void throw_read_only()
Definition: remoteserver.cc:56
void(RemoteServer::* dispatch_func)(const string &)
Xapian remote backend server base class.
Set of documents judged as relevant.
double unserialise_double(const char **p, const char *end)
Unserialise a double serialised by serialise_double.
functions to serialise and unserialise a double
string serialise_error(const Xapian::Error &e)
Serialise a Xapian::Error object to a string.
functions to convert classes to strings and back
string serialise_stats(const Xapian::Weight::Internal &stats)
Serialise a stats object.
Definition: serialise.cc:42
Xapian::Document unserialise_document(string_view s)
Unserialise a serialised Xapian::Document object.
Definition: serialise.cc:223
Xapian::RSet unserialise_rset(const string &s)
Unserialise a serialised Xapian::RSet object.
Definition: serialise.cc:162
void unserialise_stats(const char *p, const char *p_end, Xapian::Weight::Internal &stat)
Unserialise a serialised stats object.
Definition: serialise.cc:92
functions to convert classes to strings and back
Convert types to std::string.
Various handy string-related helpers.
std::string::size_type common_prefix_length(std::string_view a, std::string_view b)
Definition: stringutils.h:128
Class to throw when we receive the connection closing message.
Definition: remoteserver.cc:62
Abstract base class for termlists.
Class for iterating over document values.
Xapian::Weight::Internal class, holding database and term statistics.