Ticket #141: multi_writer_lock.patch
File multi_writer_lock.patch, 13.3 KB (added by , 18 years ago) |
---|
-
bin/xapian-tcpsrv.cc
150 150 } 151 151 152 152 try { 153 vector<string> dbnames; 153 154 if (writable) { 154 Xapian::WritableDatabase db(argv[optind], Xapian::DB_CREATE_OR_OPEN); 155 156 if (verbose) { 157 if (host.empty()) 158 cout << "Starting writable server on port "; 159 else 160 cout << "Starting writable server on host " << host << ", port "; 161 cout << port << endl; 155 // Try to open the database just to give the user a 156 // reasonable error now instead of waiting for the first 157 // connection. 158 { // scope to ensure DB is destructed and closed 159 Xapian::WritableDatabase db(argv[optind], Xapian::DB_CREATE_OR_OPEN); 162 160 } 163 164 TcpServer server(db, host, port, msecs_active_timeout, 165 msecs_idle_timeout, verbose); 166 167 if (verbose) 168 cout << "Listening..." << endl; 169 170 register_user_weighting_schemes(server); 171 172 if (one_shot) { 173 server.run_once(); 174 } else { 175 server.run(); 176 } 161 dbnames.push_back(argv[optind]); 177 162 } else { 178 Xapian::Database db; 179 while (argv[optind]) { 180 db.add_database(Xapian::Database(argv[optind++])); 163 { // scope to kill DB we use to test open 164 Xapian::Database db; 165 while (argv[optind]) { 166 dbnames.push_back(argv[optind]); 167 db.add_database(Xapian::Database(argv[optind++])); 168 } 181 169 } 170 } 182 171 183 if (verbose) { 184 if (host.empty()) 185 cout << "Starting server on port "; 186 else 187 cout << "Starting server on host " << host << ", port "; 188 cout << port << endl; 189 } 172 if (verbose) { 173 cout << "Starting"; 174 if (writable) 175 cout << " writable"; 176 cout << " server on"; 177 if (host.empty()) 178 cout << "port "; 179 else 180 cout << "host " << host << ", port "; 181 cout << port << endl; 182 } 190 183 191 TcpServer server(db, host, port, msecs_active_timeout,192 msecs_idle_timeout, verbose);184 TcpServer server(dbnames, host, port, msecs_active_timeout, 185 msecs_idle_timeout, writable, verbose); 193 186 194 195 187 if (verbose) 188 cout << "Listening..." << endl; 196 189 197 190 register_user_weighting_schemes(server); 198 191 199 if (one_shot) { 200 server.run_once(); 201 } else { 202 server.run(); 203 } 192 if (one_shot) { 193 server.run_once(); 194 } else { 195 server.run(); 204 196 } 205 197 } catch (const Xapian::Error &e) { 206 198 cerr << e.get_type() << ": " << e.get_msg(); -
bin/xapian-progsrv.cc
57 57 58 58 int main(int argc, char **argv) { 59 59 /* variables needed in both try/catch blocks */ 60 Xapian::WritableDatabase wdb;61 Xapian::Database dbs;62 60 unsigned int timeout = 60000; 63 61 bool writable = false; 64 62 bool syntax_error = false; … … 94 92 exit(1); 95 93 } 96 94 97 /* Trap exceptions related to setting up the database */ 95 96 vector<string> dbnames; 97 /* Trap exceptions related to setting up the database, which we do 98 just for convenience - each connection itself opens it */ 99 98 100 try { 101 Xapian::WritableDatabase wdb; 102 Xapian::Database dbs; 99 103 if (writable) { 100 104 wdb = Xapian::WritableDatabase(argv[optind], Xapian::DB_CREATE_OR_OPEN); 105 dbnames.push_back(argv[optind]); 101 106 } else { 102 107 while (argv[optind]) { 108 dbnames.push_back(argv[optind]); 103 109 dbs.add_database(Xapian::Database(argv[optind++])); 104 110 } 105 111 } … … 116 122 * on to the remote end, as the RemoteServer will do that itself. 117 123 */ 118 124 try { 119 if (writable) { 120 RemoteServer server(&wdb, 0, 1, timeout, timeout); 121 // If you have defined your own weighting scheme, register it here 122 // like so: 123 // server.register_weighting_scheme(FooWeight()); 125 RemoteServer server(dbnames, 0, 1, timeout, timeout, writable); 126 // If you have defined your own weighting scheme, register it here 127 // like so: 128 // server.register_weighting_scheme(FooWeight()); 124 129 125 server.run(); 126 } else { 127 RemoteServer server(&dbs, 0, 1, timeout, timeout); 128 // If you have defined your own weighting scheme, register it here 129 // like so: 130 // server.register_weighting_scheme(FooWeight()); 131 132 server.run(); 133 } 130 server.run(); 134 131 } catch (...) { 135 132 } 136 133 } -
net/tcpserver.cc
54 54 #endif 55 55 56 56 /// The TcpServer constructor, taking a database and a listening port. 57 TcpServer::TcpServer( Xapian::Database db_, const std::string & host, int port,57 TcpServer::TcpServer(const vector<std::string> &dbpaths_, const std::string & host, int port, 58 58 int msecs_active_timeout_, 59 59 int msecs_idle_timeout_, 60 bool writable_, 60 61 bool verbose_) 61 : writable( false), db(db_), listen_socket(get_listening_socket(host, port)),62 : writable(writable_), listen_socket(get_listening_socket(host, port)), 62 63 msecs_active_timeout(msecs_active_timeout_), 63 64 msecs_idle_timeout(msecs_idle_timeout_), 65 dbpaths(dbpaths_), 64 66 verbose(verbose_) 65 67 { 66 67 68 } 68 69 69 TcpServer::TcpServer(Xapian::WritableDatabase wdb_, const std::string & host, int port,70 int msecs_active_timeout_,71 int msecs_idle_timeout_,72 bool verbose_)73 : writable(true), wdb(wdb_), listen_socket(get_listening_socket(host, port)),74 msecs_active_timeout(msecs_active_timeout_),75 msecs_idle_timeout(msecs_idle_timeout_),76 verbose(verbose_)77 {78 79 }80 81 70 int 82 71 TcpServer::get_listening_socket(const std::string & host, int port) 83 72 { … … 224 213 // child code 225 214 close(listen_socket); 226 215 try { 227 if (writable) { 228 RemoteServer sserv(&wdb, connected_socket, connected_socket, 229 msecs_active_timeout, 230 msecs_idle_timeout); 231 sserv.run(); 232 } else { 233 RemoteServer sserv(&db, connected_socket, connected_socket, 234 msecs_active_timeout, 235 msecs_idle_timeout); 236 sserv.run(); 216 RemoteServer sserv(dbpaths, connected_socket, connected_socket, 217 msecs_active_timeout, 218 msecs_idle_timeout, 219 writable); 237 220 } 238 221 } catch (const Xapian::Error &err) { 239 222 cerr << "Got exception " << err.get_type() … … 291 274 while (true) { 292 275 try { 293 276 run_once(); 294 } catch (const Xapian::DatabaseModifiedError &) {295 cerr << "Database modified - calling db.reopen()" << endl;296 db.reopen();297 277 } catch (const Xapian::Error &err) { 298 278 // FIXME: better error handling. 299 279 cerr << "Caught " << err.get_type() … … 367 347 TcpServer::handle_one_request(int connected_socket) 368 348 { 369 349 try { 370 if (writable) { 371 RemoteServer sserv(&wdb, connected_socket, connected_socket, 372 msecs_active_timeout, 373 msecs_idle_timeout); 374 sserv.run(); 375 } else { 376 RemoteServer sserv(&db, connected_socket, connected_socket, 377 msecs_active_timeout, 378 msecs_idle_timeout); 379 sserv.run(); 380 } 350 RemoteServer sserv(dbpaths, connected_socket, connected_socket, 351 msecs_active_timeout, 352 msecs_idle_timeout, 353 writable); 354 sserv.run(); 381 355 } catch (const Xapian::Error &err) { 382 356 cerr << "Got exception " << err.get_type() 383 357 << ": " << err.get_msg() << endl; … … 441 415 // really matter... 442 416 CloseHandle(hthread); 443 417 444 } catch (const Xapian::DatabaseModifiedError &) {445 cerr << "Database modified - calling db.reopen()" << endl;446 db.reopen();447 418 } catch (const Xapian::Error &err) { 448 419 // FIXME: better error handling. 449 420 cerr << "Caught " << err.get_type() -
net/remoteserver.cc
41 41 /// Class to throw when we receive the connection closing message. 42 42 struct ConnectionClosed { }; 43 43 44 RemoteServer::RemoteServer( Xapian::Database * db_,44 RemoteServer::RemoteServer(const std::vector<std::string> &dbpaths, 45 45 int fdin_, int fdout_, 46 46 Xapian::timeout active_timeout_, 47 Xapian::timeout idle_timeout_) 48 : RemoteConnection(fdin_, fdout_, db_->get_description()), 49 db(db_), wdb(NULL), 47 Xapian::timeout idle_timeout_, 48 bool writable) 49 : RemoteConnection(fdin_, fdout_, dbpaths[0]), 50 db(NULL), wdb(NULL), 50 51 active_timeout(active_timeout_), idle_timeout(idle_timeout_) 51 52 { 53 // Catch errors opening the database and serialize back to other end 54 try { 55 if (writable) { 56 Assert(dbpaths.size()==1); // expecting exactly 1 DB 57 wdb = new Xapian::WritableDatabase(dbpaths[0], Xapian::DB_CREATE_OR_OPEN); 58 db = wdb; 59 } else { 60 db = new Xapian::Database(); 61 vector<std::string>::const_iterator i; 62 for (i = dbpaths.begin(); i != dbpaths.end(); ++i) 63 db->add_database(Xapian::Database(*i)); 64 } 65 } catch (const Xapian::Error &err) { 66 // Propagate the exception across the connection and get out-of-here! 67 send_message(REPLY_EXCEPTION, serialise_error(err)); 68 throw; 69 } 52 70 initialise(); 53 71 } 54 72 55 RemoteServer::RemoteServer(Xapian::WritableDatabase * wdb_,56 int fdin_, int fdout_,57 Xapian::timeout active_timeout_,58 Xapian::timeout idle_timeout_)59 : RemoteConnection(fdin_, fdout_, wdb_->get_description()),60 db(wdb_), wdb(wdb_),61 active_timeout(active_timeout_), idle_timeout(idle_timeout_)62 {63 initialise();64 }65 66 73 void 67 74 RemoteServer::initialise() 68 75 { … … 94 101 95 102 RemoteServer::~RemoteServer() 96 103 { 104 delete db; // wdb is either null or db - so its ok 97 105 map<string, Xapian::Weight*>::const_iterator i; 98 106 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) { 99 107 delete i->second; -
common/tcpserver.h
42 42 /// Don't allow copying. 43 43 TcpServer(const TcpServer &); 44 44 45 // path to the DBs we will open - this should contain exactly 1 46 // entry if writable, and at least one if not. 47 const std::vector<std::string> dbpaths; 48 45 49 /** Is this a WritableDatabase? 46 50 * 47 * If true, the wdb member is used. If false, the db member is.48 51 */ 49 52 bool writable; 50 53 51 /** If writable is false, this is the database we're using. */52 Xapian::Database db;53 54 /** If writable is true, this is the database we're using. */55 Xapian::WritableDatabase wdb;56 57 54 /** The socket we're listening on. */ 58 55 int listen_socket; 59 56 … … 81 78 /** Construct a TcpServer for a Database and start listening for 82 79 * connections. 83 80 * 84 * @param db _ The Database to provide remote access to.81 * @param dbpaths_ The locations of the databases we should open. 85 82 * @param host The hostname or address for the interface to listen on 86 83 * (or "" to listen on all interfaces). 87 84 * @port The TCP port number to listen on. … … 90 87 * (default 10000). 91 88 * @param msecs_idle_timeout Timeout between operations (in 92 89 * milliseconds) (default 60000). 90 * @param writable_ Should we open the DB for writing? (default 91 * false). 93 92 * @param verbose_ Should we produce output when connections are 94 93 * made or lost? (default true). 95 94 */ 96 TcpServer( Xapian::Database db_, const std::string &host, int port,95 TcpServer(const std::vector<std::string> &dbpaths_, const std::string &host, int port, 97 96 int msecs_normal_timeout_ = 10000, 98 97 int msecs_idle_timeout_ = 60000, 98 bool writable_ = false, 99 99 bool verbose_ = true); 100 100 101 /** Construct a TcpServer for a WritableDatabase and start listening for102 * connections.103 *104 * @param db_ The WritableDatabase to provide remote access to.105 * @param host The hostname or address for the interface to listen on106 * (or "" to listen on all interfaces).107 * @port The TCP port number to listen on.108 * @param msecs_active_timeout Timeout between messages during a109 * single operation (in milliseconds)110 * (default 10000).111 * @param msecs_idle_timeout Timeout between operations (in112 * milliseconds) (default 60000).113 * @param verbose_ Should we produce output when connections are114 * made or lost? (default true).115 */116 TcpServer(Xapian::WritableDatabase db_, const std::string &host, int port,117 int msecs_normal_timeout_ = 10000,118 int msecs_idle_timeout_ = 60000,119 bool verbose_ = true);120 121 101 /** Destructor. */ 122 102 ~TcpServer(); 123 103 -
common/remoteserver.h
150 150 * @param idle_timeout_ Timeout while waiting for a new action from 151 151 * the client (specified in millisrconds). 152 152 */ 153 RemoteServer( Xapian::Database * db, int fdin, int fdout,153 RemoteServer(const std::vector<std::string> &dbpaths, int fdin, int fdout, 154 154 Xapian::timeout active_timeout_ = 10000, 155 Xapian::timeout idle_timeout_ = 60000); 155 Xapian::timeout idle_timeout_ = 60000, 156 bool writable = false); 156 157 157 158 /** Construct a writable RemoteServer. 158 159 *