Ticket #711: 711-remote_protocol_msg_readaccess_select.diff
File 711-remote_protocol_msg_readaccess_select.diff, 26.2 KB (added by , 9 years ago) |
---|
-
xapian-core/backends/dbfactory_remote.cc
commit 6fe691aabd7133073585197112ee3ac8fdbaa905 Author: German M. Bravo <german.mb@deipi.com> Date: Wed Apr 1 09:39:06 2015 -0600 Remote protocol with support for selection of database directory. If the user requests to open a remote database server, it can optionally require the remote backend to tell the server what database it wants to open, if the remote server is configured as a server without a default directory (xapian-tcpsrv remains to always have a default directory at the moment). The binary protocol was changed in the way that a new command can be sent to the server (MSG_READACCESS) in case the server tells the client no default directory is selected, the server then reacts to this command by opening and selecting the requested database as the active database. diff --git a/xapian-core/backends/dbfactory_remote.cc b/xapian-core/backends/dbfactory_remote.cc index 5eaab61..6747d8a 100644
a b namespace Xapian { 33 33 34 34 Database 35 35 Remote::open(const string &host, unsigned int port, useconds_t timeout_, 36 useconds_t connect_timeout )36 useconds_t connect_timeout, int flags, const string &dir) 37 37 { 38 LOGCALL_STATIC(API, Database, "Remote::open", host | port | timeout_ | connect_timeout );38 LOGCALL_STATIC(API, Database, "Remote::open", host | port | timeout_ | connect_timeout | flags | dir); 39 39 RETURN(Database(new RemoteTcpClient(host, port, timeout_ * 1e-3, 40 connect_timeout * 1e-3, false, 0)));40 connect_timeout * 1e-3, false, flags, dir))); 41 41 } 42 42 43 43 WritableDatabase 44 44 Remote::open_writable(const string &host, unsigned int port, 45 45 useconds_t timeout_, useconds_t connect_timeout, 46 int flags )46 int flags, const string &dir) 47 47 { 48 LOGCALL_STATIC(API, WritableDatabase, "Remote::open_writable", host | port | timeout_ | connect_timeout | flags );48 LOGCALL_STATIC(API, WritableDatabase, "Remote::open_writable", host | port | timeout_ | connect_timeout | flags | dir); 49 49 RETURN(WritableDatabase(new RemoteTcpClient(host, port, timeout_ * 1e-3, 50 50 connect_timeout * 1e-3, true, 51 flags )));51 flags, dir))); 52 52 } 53 53 54 54 Database 55 55 Remote::open(const string &program, const string &args, 56 useconds_t timeout_ )56 useconds_t timeout_, int flags, const string &dir) 57 57 { 58 LOGCALL_STATIC(API, Database, "Remote::open", program | args | timeout_ );59 RETURN(Database(new ProgClient(program, args, timeout_ * 1e-3, false, 0)));58 LOGCALL_STATIC(API, Database, "Remote::open", program | args | timeout_ | flags | dir); 59 RETURN(Database(new ProgClient(program, args, timeout_ * 1e-3, false, flags, dir))); 60 60 } 61 61 62 62 WritableDatabase 63 63 Remote::open_writable(const string &program, const string &args, 64 useconds_t timeout_, int flags )64 useconds_t timeout_, int flags, const string &dir) 65 65 { 66 LOGCALL_STATIC(API, WritableDatabase, "Remote::open_writable", program | args | timeout_ | flags );66 LOGCALL_STATIC(API, WritableDatabase, "Remote::open_writable", program | args | timeout_ | flags | dir); 67 67 RETURN(WritableDatabase(new ProgClient(program, args, 68 timeout_ * 1e-3, true, flags )));68 timeout_ * 1e-3, true, flags, dir))); 69 69 } 70 70 71 71 } -
xapian-core/backends/remote/remote-database.cc
diff --git a/xapian-core/backends/remote/remote-database.cc b/xapian-core/backends/remote/remote-database.cc index 37609c1..89911f4 100644
a b throw_connection_closed_unexpectedly() 68 68 } 69 69 70 70 RemoteDatabase::RemoteDatabase(int fd, double timeout_, 71 const string & context_, bool writable, 72 int flags) 73 : link(fd, fd, context_), 71 const string & context_, bool writable_, 72 int flags_, const string & dir) 73 : db_dir(dir), 74 writable(writable_), 75 flags(flags_), 76 link(fd, fd, context_), 74 77 context(context_), 75 78 cached_stats_valid(), 76 79 mru_valstats(), … … RemoteDatabase::RemoteDatabase(int fd, double timeout_, 95 98 } 96 99 97 100 update_stats(MSG_MAX); 98 99 if (writable) {100 if (flags & Xapian::DB_RETRY_LOCK) {101 const string & body = encode_length(flags & Xapian::DB_RETRY_LOCK);102 update_stats(MSG_WRITEACCESS, body);103 } else {104 update_stats(MSG_WRITEACCESS);105 }106 }107 101 } 108 102 109 103 void … … RemoteDatabase::update_stats(message_type msg_code, const string & body) const 339 333 340 334 string message; 341 335 reply_type type = get_message(message); 342 if (type != REPLY_UPDATE || message.size() < 3) {336 if (type != REPLY_UPDATE || message.size() < 2) { 343 337 if (type == REPLY_DONE) { 344 338 // The database was already open at the latest revision. 345 339 return false; … … RemoteDatabase::update_stats(message_type msg_code, const string & body) const 373 367 throw Xapian::NetworkError(errmsg, context); 374 368 } 375 369 370 if (p == p_end) { 371 message = encode_length(flags); 372 message += encode_length(db_dir.size()); 373 message += db_dir; 374 375 if (writable) { 376 send_message(MSG_WRITEACCESS, message); 377 } else { 378 send_message(MSG_READACCESS, message); 379 } 380 381 get_message(message, REPLY_UPDATE); 382 if (message.size() < 3) { 383 throw Xapian::NetworkError("Database was not selected", context); 384 } 385 386 p = message.c_str(); 387 p_end = p + message.size(); 388 389 // The protocol versions where already checked. 390 p += 2; 391 } else if (writable) { 392 if (flags) { 393 send_message(MSG_WRITEACCESS, encode_length(flags)); 394 } else { 395 send_message(MSG_WRITEACCESS, string()); 396 } 397 398 get_message(message, REPLY_UPDATE); 399 if (message.size() < 3) { 400 throw Xapian::NetworkError("Database was not selected", context); 401 } 402 403 p = message.c_str(); 404 p_end = p + message.size(); 405 406 // The protocol versions where already checked. 407 p += 2; 408 } 409 376 410 decode_length(&p, p_end, doccount); 377 411 decode_length(&p, p_end, lastdocid); 378 412 lastdocid += doccount; … … RemoteDatabase::do_close() 597 631 // In the constructor, we set transaction_state to 598 632 // TRANSACTION_UNIMPLEMENTED if we aren't writable so that we can check 599 633 // it here. 600 bool writable = (transaction_state != TRANSACTION_UNIMPLEMENTED);634 bool writable_ = (transaction_state != TRANSACTION_UNIMPLEMENTED); 601 635 602 636 // Only call dtor_called() if we're writable. 603 if (writable ) dtor_called();637 if (writable_) dtor_called(); 604 638 605 639 // If we're writable, wait for a confirmation of the close, so we know that 606 640 // changes have been written and flushed, and the database write lock 607 641 // released. For the non-writable case, there's no need to wait, so don't 608 642 // slow down searching by waiting here. 609 link.do_close(writable );643 link.do_close(writable_); 610 644 } 611 645 612 646 void -
xapian-core/backends/remote/remote-database.h
diff --git a/xapian-core/backends/remote/remote-database.h b/xapian-core/backends/remote/remote-database.h index b275c52..e593eec 100644
a b class RemoteDatabase : public Xapian::Database::Internal { 49 49 /// Don't allow copying. 50 50 RemoteDatabase(const RemoteDatabase &); 51 51 52 // Directory to store databases in. 53 const std::string db_dir; 54 55 // The database is writable. 56 const bool writable; 57 58 // Bitwise-or of Xapian::DB_* flags. 59 const int flags; 60 52 61 /// The object which does the I/O. 53 62 mutable RemoteConnection link; 54 63 … … class RemoteDatabase : public Xapian::Database::Internal { 103 112 * operations will never timeout. 104 113 * @param context_ The context to return with any error messages. 105 114 * @param writable Is this a WritableDatabase? 106 * @param flags Xapian::DB_RETRY_LOCK or 0. 115 * @param flags Bitwise-or of Xapian::DB_* constants. 116 * @param dir Database directory index to open. 107 117 */ 108 118 RemoteDatabase(int fd, double timeout_, const string & context_, 109 bool writable, int flags );119 bool writable, int flags, const string & dir); 110 120 111 121 /// Receive a message from the server. 112 122 reply_type get_message(string & message, reply_type required_type = REPLY_MAX) const; -
xapian-core/bin/xapian-tcpsrv.cc
diff --git a/xapian-core/bin/xapian-tcpsrv.cc b/xapian-core/bin/xapian-tcpsrv.cc index 25743da..f7f23a4 100644
a b static const struct option long_opts[] = { 72 72 }; 73 73 74 74 static void show_usage() { 75 cout << "Usage: " PROG_NAME " [OPTIONS] DATABASE_DIRECTORY...\n\n"75 cout << "Usage: " PROG_NAME " [OPTIONS] [DATABASE_DIRECTORY] ...\n\n" 76 76 "Options:\n" 77 77 " --port PORTNUM listen on port PORTNUM for connections (no default)\n" 78 78 " --interface ADDRESS listen on the interface associated with name or\n" … … int main(int argc, char **argv) { 143 143 } 144 144 } 145 145 146 if (syntax_error || argv[optind] == NULL) {146 if (syntax_error) { 147 147 show_usage(); 148 148 exit(1); 149 149 } -
xapian-core/common/remoteprotocol.h
diff --git a/xapian-core/common/remoteprotocol.h b/xapian-core/common/remoteprotocol.h index fcaa1ec..03adba7 100644
a b enum message_type { 89 89 MSG_METADATAKEYLIST, // Iterator for metadata keys 90 90 MSG_FREQS, // Get termfreq and collfreq 91 91 MSG_UNIQUETERMS, // Get number of unique terms in doc 92 MSG_READACCESS, // Select currenty active read access database 92 93 MSG_MAX 93 94 }; 94 95 -
xapian-core/include/xapian/dbfactory.h
diff --git a/xapian-core/include/xapian/dbfactory.h b/xapian-core/include/xapian/dbfactory.h index 3e29786..1fd1489 100644
a b namespace Remote { 171 171 * Xapian::NetworkTimeoutError is thrown. A 172 172 * timeout of 0 means don't timeout. (Default is 173 173 * 10000ms, which is 10 seconds). 174 */ 174 * @param flags bitwise-or of Xapian::DB_* constants. 175 * @param dir database directory index to open. 176 */ 175 177 XAPIAN_VISIBILITY_DEFAULT 176 Database open(const std::string &host, unsigned int port, useconds_t timeout = 10000, useconds_t connect_timeout = 10000 );178 Database open(const std::string &host, unsigned int port, useconds_t timeout = 10000, useconds_t connect_timeout = 10000, int flags = 0, const std::string &dir = std::string()); 177 179 178 180 /** Construct a WritableDatabase object for update access to a remote database 179 181 * accessed via a TCP connection. … … Database open(const std::string &host, unsigned int port, useconds_t timeout = 1 192 194 * Xapian::NetworkTimeoutError is thrown. A 193 195 * timeout of 0 means don't timeout. (Default is 194 196 * 10000ms, which is 10 seconds). 197 * @param flags bitwise-or of Xapian::DB_* constants. 198 * @param dir database directory index to open. 195 199 */ 196 200 XAPIAN_VISIBILITY_DEFAULT 197 WritableDatabase open_writable(const std::string &host, unsigned int port, useconds_t timeout = 0, useconds_t connect_timeout = 10000, int flags = 0 );201 WritableDatabase open_writable(const std::string &host, unsigned int port, useconds_t timeout = 0, useconds_t connect_timeout = 10000, int flags = 0, const std::string &dir = std::string()); 198 202 199 203 /** Construct a Database object for read-only access to a remote database 200 204 * accessed via a program. … … WritableDatabase open_writable(const std::string &host, unsigned int port, useco 209 213 * then Xapian::NetworkTimeoutError is thrown. A timeout 210 214 * of 0 means don't timeout. (Default is 10000ms, which 211 215 * is 10 seconds). 212 * @param flags Xapian::DB_RETRY_LOCK or 0. 216 * @param flags bitwise-or of Xapian::DB_* constants. 217 * @param dir database directory index to open. 213 218 */ 214 219 XAPIAN_VISIBILITY_DEFAULT 215 Database open(const std::string &program, const std::string &args, useconds_t timeout = 10000 );220 Database open(const std::string &program, const std::string &args, useconds_t timeout = 10000, int flags = 0, const std::string &dir = std::string()); 216 221 217 222 /** Construct a WritableDatabase object for update access to a remote database 218 223 * accessed via a program. … … Database open(const std::string &program, const std::string &args, useconds_t ti 226 231 * for any individual operation on the remote database 227 232 * then Xapian::NetworkTimeoutError is thrown. (Default 228 233 * is 0, which means don't timeout). 229 * @param flags Xapian::DB_RETRY_LOCK or 0. 234 * @param flags bitwise-or of Xapian::DB_* constants. 235 * @param dir database directory index to open. 230 236 */ 231 237 XAPIAN_VISIBILITY_DEFAULT 232 WritableDatabase open_writable(const std::string &program, const std::string &args, useconds_t timeout = 0, int flags = 0 );238 WritableDatabase open_writable(const std::string &program, const std::string &args, useconds_t timeout = 0, int flags = 0, const std::string &dir = std::string()); 233 239 234 240 } 235 241 #endif -
xapian-core/net/progclient.cc
diff --git a/xapian-core/net/progclient.cc b/xapian-core/net/progclient.cc index bf10cf2..b928e2d 100644
a b split_words(const string &text, vector<string> &words, char ws = ' ') 64 64 #endif 65 65 66 66 ProgClient::ProgClient(const string &progname, const string &args, 67 double timeout_, bool writable, int flags )67 double timeout_, bool writable, int flags, const string & dir) 68 68 : RemoteDatabase(run_program(progname, args 69 69 #ifndef __WIN32__ 70 70 , pid 71 71 #endif 72 72 ), 73 73 timeout_, get_progcontext(progname, args), writable, 74 flags )74 flags, dir) 75 75 { 76 LOGCALL_CTOR(DB, "ProgClient", progname | args | timeout_ | writable | flags );76 LOGCALL_CTOR(DB, "ProgClient", progname | args | timeout_ | writable | flags | dir); 77 77 } 78 78 79 79 string -
xapian-core/net/progclient.h
diff --git a/xapian-core/net/progclient.h b/xapian-core/net/progclient.h index 5567e55..9ebcde9 100644
a b class ProgClient : public RemoteDatabase { 88 88 const std::string &arg, 89 89 double msecs_timeout, 90 90 bool writable, 91 int flags); 91 int flags, 92 const std::string & dir); 92 93 93 94 /** Destructor. */ 94 95 ~ProgClient(); -
xapian-core/net/remoteserver.cc
diff --git a/xapian-core/net/remoteserver.cc b/xapian-core/net/remoteserver.cc index 9b467b1..b8ad018 100644
a b throw_read_only() 54 54 throw Xapian::InvalidOperationError("Server is read-only"); 55 55 } 56 56 57 XAPIAN_NORETURN(static void throw_no_db()); 58 static void 59 throw_no_db() 60 { 61 throw Xapian::InvalidOperationError("Server has no open database"); 62 } 63 57 64 /// Class to throw when we receive the connection closing message. 58 65 struct ConnectionClosed { }; 59 66 60 RemoteServer::RemoteServer(const std::vector<std::string> &dbpaths ,67 RemoteServer::RemoteServer(const std::vector<std::string> &dbpaths_, 61 68 int fdin_, int fdout_, 62 69 double active_timeout_, double idle_timeout_, 63 70 bool writable_) … … RemoteServer::RemoteServer(const std::vector<std::string> &dbpaths, 67 74 { 68 75 // Catch errors opening the database and propagate them to the client. 69 76 try { 70 Assert(!dbpaths.empty()); 71 // We always open the database read-only to start with. If we're 72 // writable, the client can ask to be upgraded to write access once 73 // connected if it wants it. 74 db = new Xapian::Database(dbpaths[0]); 75 // Build a better description than Database::get_description() gives 76 // in the variable context. FIXME: improve Database::get_description() 77 // and then just use that instead. 78 context = dbpaths[0]; 79 80 if (!writable) { 81 vector<std::string>::const_iterator i(dbpaths.begin()); 82 for (++i; i != dbpaths.end(); ++i) { 83 db->add_database(Xapian::Database(*i)); 84 context += ' '; 85 context += *i; 86 } 87 } else { 88 AssertEq(dbpaths.size(), 1); // Expecting exactly one database. 77 if (!dbpaths_.empty()) { 78 // We always open the database read-only to start with. If we're 79 // writable, the client can ask to be upgraded to write access once 80 // connected if it wants it. 81 select_db(dbpaths_, false, Xapian::DB_OPEN); 89 82 } 90 83 } catch (const Xapian::Error &err) { 91 84 // Propagate the exception to the client. … … RemoteServer::run() 192 185 &RemoteServer::msg_openmetadatakeylist, 193 186 &RemoteServer::msg_freqs, 194 187 &RemoteServer::msg_uniqueterms, 188 &RemoteServer::msg_readaccess, 195 189 }; 196 190 197 191 string message; … … RemoteServer::run() 239 233 void 240 234 RemoteServer::msg_allterms(const string &message) 241 235 { 236 if (!db) 237 throw_no_db(); 238 242 239 string prev = message; 243 240 string reply; 244 241 … … RemoteServer::msg_allterms(const string &message) 262 259 void 263 260 RemoteServer::msg_termlist(const string &message) 264 261 { 262 if (!db) 263 throw_no_db(); 264 265 265 const char *p = message.data(); 266 266 const char *p_end = p + message.size(); 267 267 Xapian::docid did; … … RemoteServer::msg_termlist(const string &message) 289 289 void 290 290 RemoteServer::msg_positionlist(const string &message) 291 291 { 292 if (!db) 293 throw_no_db(); 294 292 295 const char *p = message.data(); 293 296 const char *p_end = p + message.size(); 294 297 Xapian::docid did; … … RemoteServer::msg_positionlist(const string &message) 310 313 void 311 314 RemoteServer::msg_postlist(const string &message) 312 315 { 316 if (!db) 317 throw_no_db(); 318 313 319 const string & term = message; 314 320 315 321 Xapian::doccount termfreq = db->get_termfreq(term); … … RemoteServer::msg_postlist(const string &message) 333 339 } 334 340 335 341 void 336 RemoteServer::msg_ writeaccess(const string & msg)342 RemoteServer::msg_readaccess(const string &message) 337 343 { 338 if (!writable) 344 int flags = Xapian::DB_OPEN; 345 const char *p = message.c_str(); 346 const char *p_end = p + message.size(); 347 if (p != p_end) { 348 unsigned flag_bits; 349 decode_length(&p, p_end, flag_bits); 350 flags |= flag_bits &~ Xapian::DB_ACTION_MASK_; 351 } 352 353 if (p != p_end) { 354 std::vector<string> dbpaths_; 355 while (p != p_end) { 356 size_t len; 357 decode_length_and_check(&p, p_end, len); 358 string dbpath(p, len); 359 dbpaths_.push_back(dbpath); 360 p += len; 361 } 362 select_db(dbpaths_, false, flags); 363 } else { 364 select_db(dbpaths, false, flags); 365 } 366 367 msg_update(message); 368 } 369 370 371 void 372 RemoteServer::msg_writeaccess(const string & message) 373 { 374 if (!writable) 339 375 throw_read_only(); 340 376 341 377 int flags = Xapian::DB_OPEN; 342 const char *p = m sg.c_str();343 const char *p_end = p + m sg.size();378 const char *p = message.c_str(); 379 const char *p_end = p + message.size(); 344 380 if (p != p_end) { 345 381 unsigned flag_bits; 346 382 decode_length(&p, p_end, flag_bits); 347 383 flags |= flag_bits &~ Xapian::DB_ACTION_MASK_; 384 } 385 386 if (p != p_end) { 387 std::vector<string> dbpaths_; 388 size_t len; 389 decode_length_and_check(&p, p_end, len); 390 string dbpath(p, len); 391 dbpaths_.push_back(dbpath); 392 p += len; 348 393 if (p != p_end) { 349 throw Xapian::NetworkError(" Junk at end of MSG_WRITEACCESS");394 throw Xapian::NetworkError("only one database directory allowed on writable databases"); 350 395 } 396 select_db(dbpaths_, true, flags); 397 } else { 398 select_db(dbpaths, true, flags); 351 399 } 352 400 353 wdb = new Xapian::WritableDatabase(context, flags); 354 delete db; 355 db = wdb; 356 msg_update(msg); 401 msg_update(message); 357 402 } 358 403 359 404 void 360 405 RemoteServer::msg_reopen(const string & msg) 361 406 { 407 if (!db) 408 throw_no_db(); 409 362 410 if (!db->reopen()) { 363 411 send_message(REPLY_DONE, string()); 364 412 return; … … RemoteServer::msg_update(const string &) 373 421 char(XAPIAN_REMOTE_PROTOCOL_MAJOR_VERSION), 374 422 char(XAPIAN_REMOTE_PROTOCOL_MINOR_VERSION) 375 423 }; 424 376 425 string message(protocol, 2); 377 Xapian::doccount num_docs = db->get_doccount(); 378 message += encode_length(num_docs); 379 message += encode_length(db->get_lastdocid() - num_docs); 380 Xapian::termcount doclen_lb = db->get_doclength_lower_bound(); 381 message += encode_length(doclen_lb); 382 message += encode_length(db->get_doclength_upper_bound() - doclen_lb); 383 message += (db->has_positions() ? '1' : '0'); 384 // FIXME: clumsy to reverse calculate total_len like this: 385 totlen_t total_len = totlen_t(db->get_avlength() * db->get_doccount() + .5); 386 message += encode_length(total_len); 387 //message += encode_length(db->get_total_length()); 388 string uuid = db->get_uuid(); 389 message += uuid; 426 427 if (db) { 428 Xapian::doccount num_docs = db->get_doccount(); 429 message += encode_length(num_docs); 430 message += encode_length(db->get_lastdocid() - num_docs); 431 Xapian::termcount doclen_lb = db->get_doclength_lower_bound(); 432 message += encode_length(doclen_lb); 433 message += encode_length(db->get_doclength_upper_bound() - doclen_lb); 434 message += (db->has_positions() ? '1' : '0'); 435 // FIXME: clumsy to reverse calculate total_len like this: 436 totlen_t total_len = totlen_t(db->get_avlength() * db->get_doccount() + .5); 437 message += encode_length(total_len); 438 //message += encode_length(db->get_total_length()); 439 string uuid = db->get_uuid(); 440 message += uuid; 441 } 442 390 443 send_message(REPLY_UPDATE, message); 391 444 } 392 445 … … RemoteServer::msg_query(const string &message_in) 485 538 p += len; 486 539 } 487 540 541 if (!db) 542 throw_no_db(); 543 488 544 Xapian::Weight::Internal local_stats; 489 545 MultiMatch match(*db, query, qlen, &rset, collapse_max, collapse_key, 490 546 percent_cutoff, weight_cutoff, order, … … RemoteServer::msg_query(const string &message_in) 528 584 void 529 585 RemoteServer::msg_document(const string &message) 530 586 { 587 if (!db) 588 throw_no_db(); 589 531 590 const char *p = message.data(); 532 591 const char *p_end = p + message.size(); 533 592 Xapian::docid did; … … RemoteServer::msg_document(const string &message) 549 608 void 550 609 RemoteServer::msg_keepalive(const string &) 551 610 { 611 if (!db) 612 throw_no_db(); 613 552 614 // Ensure *our* database stays alive, as it may contain remote databases! 553 615 db->keep_alive(); 554 616 send_message(REPLY_DONE, string()); … … RemoteServer::msg_keepalive(const string &) 557 619 void 558 620 RemoteServer::msg_termexists(const string &term) 559 621 { 622 if (!db) 623 throw_no_db(); 624 560 625 send_message((db->term_exists(term) ? REPLY_TERMEXISTS : REPLY_TERMDOESNTEXIST), string()); 561 626 } 562 627 563 628 void 564 629 RemoteServer::msg_collfreq(const string &term) 565 630 { 631 if (!db) 632 throw_no_db(); 633 566 634 send_message(REPLY_COLLFREQ, encode_length(db->get_collection_freq(term))); 567 635 } 568 636 569 637 void 570 638 RemoteServer::msg_termfreq(const string &term) 571 639 { 640 if (!db) 641 throw_no_db(); 642 572 643 send_message(REPLY_TERMFREQ, encode_length(db->get_termfreq(term))); 573 644 } 574 645 575 646 void 576 647 RemoteServer::msg_freqs(const string &term) 577 648 { 649 if (!db) 650 throw_no_db(); 651 578 652 string msg = encode_length(db->get_termfreq(term)); 579 653 msg += encode_length(db->get_collection_freq(term)); 580 654 send_message(REPLY_FREQS, msg); … … RemoteServer::msg_freqs(const string &term) 583 657 void 584 658 RemoteServer::msg_valuestats(const string & message) 585 659 { 660 if (!db) 661 throw_no_db(); 662 586 663 const char *p = message.data(); 587 664 const char *p_end = p + message.size(); 588 665 while (p != p_end) { … … RemoteServer::msg_valuestats(const string & message) 604 681 void 605 682 RemoteServer::msg_doclength(const string &message) 606 683 { 684 if (!db) 685 throw_no_db(); 686 607 687 const char *p = message.data(); 608 688 const char *p_end = p + message.size(); 609 689 Xapian::docid did; … … RemoteServer::msg_doclength(const string &message) 614 694 void 615 695 RemoteServer::msg_uniqueterms(const string &message) 616 696 { 697 if (!db) 698 throw_no_db(); 699 617 700 const char *p = message.data(); 618 701 const char *p_end = p + message.size(); 619 702 Xapian::docid did; … … RemoteServer::msg_replacedocumentterm(const string & message) 715 798 void 716 799 RemoteServer::msg_getmetadata(const string & message) 717 800 { 801 if (!db) 802 throw_no_db(); 803 718 804 send_message(REPLY_METADATA, db->get_metadata(message)); 719 805 } 720 806 721 807 void 722 808 RemoteServer::msg_openmetadatakeylist(const string & message) 723 809 { 810 if (!db) 811 throw_no_db(); 812 724 813 string prev = message; 725 814 string reply; 726 815 … … RemoteServer::msg_removespelling(const string & message) 778 867 decode_length(&p, p_end, freqdec); 779 868 wdb->remove_spelling(string(p, p_end - p), freqdec); 780 869 } 870 871 void 872 RemoteServer::select_db(const std::vector<std::string> &dbpaths_, bool writable_, int flags) { 873 if (writable_) { 874 AssertEq(dbpaths_.size(), 1); // Expecting exactly one database. 875 Xapian::WritableDatabase * wdb_ = new Xapian::WritableDatabase(dbpaths_[0], flags); 876 context = dbpaths_[0]; 877 delete db; 878 db = wdb_; 879 wdb = wdb_; 880 } else { 881 Assert(!dbpaths_.empty()); // Expecting at least one database. 882 Xapian::Database * db_; 883 if (dbpaths_.size() == 1) { 884 db_ = new Xapian::Database(dbpaths_[0], flags); 885 context = dbpaths_[0]; 886 } else { 887 db_ = new Xapian::Database(); 888 // Build a better description than Database::get_description() gives 889 // in the variable context. FIXME: improve Database::get_description() 890 // and then just use that instead. 891 context = ""; 892 for (auto& path : dbpaths_) { 893 db->add_database(Xapian::Database(path, flags)); 894 context += ' '; 895 context += path; 896 } 897 } 898 delete db; 899 db = db_; 900 wdb = NULL; 901 } 902 dbpaths = dbpaths_; 903 } -
xapian-core/net/remoteserver.h
diff --git a/xapian-core/net/remoteserver.h b/xapian-core/net/remoteserver.h index 857d791..37c0dab 100644
a b class XAPIAN_VISIBILITY_DEFAULT RemoteServer : private RemoteConnection { 69 69 /// The registry, which allows unserialisation of user subclasses. 70 70 Xapian::Registry reg; 71 71 72 std::vector<std::string> dbpaths; 73 72 74 /// Accept a message from the client. 73 75 message_type get_message(double timeout, std::string & result, 74 76 message_type required_type = MSG_MAX); … … class XAPIAN_VISIBILITY_DEFAULT RemoteServer : private RemoteConnection { 170 172 // get number of unique terms 171 173 void msg_uniqueterms(const std::string & message); 172 174 175 // select an active database for read access 176 void msg_readaccess(const std::string & message); 177 178 void select_db(const std::vector<std::string> &dbpaths_, bool writable_, int flags); 179 173 180 public: 174 181 /** Construct a RemoteServer. 175 182 * -
xapian-core/net/remotetcpclient.h
diff --git a/xapian-core/net/remotetcpclient.h b/xapian-core/net/remotetcpclient.h index 9da59a8..da46e71 100644
a b class RemoteTcpClient : SOCKET_INITIALIZER_MIXIN public RemoteDatabase { 75 75 */ 76 76 RemoteTcpClient(const std::string & hostname, int port, 77 77 double timeout_, double timeout_connect, bool writable, 78 int flags )78 int flags, const std::string & dir) 79 79 : RemoteDatabase(open_socket(hostname, port, timeout_connect), 80 80 timeout_, get_tcpcontext(hostname, port), 81 writable, flags ) { }81 writable, flags, dir) { } 82 82 83 83 /** Destructor. */ 84 84 ~RemoteTcpClient();