Ticket #141: multi_writer_lock.2.patch
File multi_writer_lock.2.patch, 15.8 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) { 155 // Try to open the database just to give the user a 156 // reasonable error now instead of waiting for the first 157 // connection. 154 158 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; 162 } 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 } 159 dbnames.push_back(argv[optind]); 177 160 } else { 178 Xapian::Database db;179 161 while (argv[optind]) { 180 db.add_database(Xapian::Database(argv[optind++])); 162 dbnames.push_back(argv[optind]); 163 Xapian::Database db(argv[optind++]); 181 164 } 165 } 182 166 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 } 167 if (verbose) { 168 cout << "Starting"; 169 if (writable) 170 cout << " writable"; 171 cout << " server on"; 172 if (!host.empty()) 173 cout << " host " << host << ","; 174 cout << " port " << port << endl; 175 } 190 176 191 TcpServer server(db, host, port, msecs_active_timeout,192 msecs_idle_timeout, verbose);177 TcpServer server(dbnames, host, port, msecs_active_timeout, 178 msecs_idle_timeout, writable, verbose); 193 179 194 195 180 if (verbose) 181 cout << "Listening..." << endl; 196 182 197 183 register_user_weighting_schemes(server); 198 184 199 if (one_shot) { 200 server.run_once(); 201 } else { 202 server.run(); 203 } 185 if (one_shot) { 186 server.run_once(); 187 } else { 188 server.run(); 204 189 } 205 190 } catch (const Xapian::Error &e) { 206 191 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 */ 98 try { 99 if (writable) { 100 wdb = Xapian::WritableDatabase(argv[optind], Xapian::DB_CREATE_OR_OPEN); 101 } else { 102 while (argv[optind]) { 103 dbs.add_database(Xapian::Database(argv[optind++])); 104 } 105 } 106 } catch (const Xapian::Error &e) { 107 // FIXME: we shouldn't build messages by hand here. 108 string msg = serialise_error(e); 109 cout << char(REPLY_EXCEPTION) << encode_length(msg.size()) << msg << flush; 110 } catch (...) { 111 // FIXME: we shouldn't build messages by hand here. 112 cout << char(REPLY_EXCEPTION) << encode_length(0) << flush; 113 } 95 vector<string> dbnames; 96 /* Unlike the tcp server, a prog server only has a single 'connection' 97 * which is established immediately. Thus, there is no need to 98 * attempt opening the database for convenience - if it can't be opened 99 * they will immediately see the problem anyway - so just get to it! 100 */ 114 101 115 102 /* Catch exceptions from running the server, but don't pass them 116 103 * on to the remote end, as the RemoteServer will do that itself. 117 104 */ 118 105 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()); 106 RemoteServer server(dbnames, 0, 1, timeout, timeout, writable); 107 // If you have defined your own weighting scheme, register it here 108 // like so: 109 // server.register_weighting_scheme(FooWeight()); 124 110 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 } 111 server.run(); 134 112 } catch (...) { 135 113 } 136 114 } -
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_, ""), 50 db(NULL), wdb(NULL), 50 51 active_timeout(active_timeout_), idle_timeout(idle_timeout_) 51 52 { 52 initialise(); 53 } 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 // build a better description than db.get_description() gives. 66 context = dbpaths[0]; 67 vector<std::string>::const_iterator i(dbpaths.begin()); 68 for (++i; i != dbpaths.end(); ++i) { 69 context += ' '; 70 context += *i; 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 void 67 RemoteServer::initialise() 68 { 73 } catch (const Xapian::Error &err) { 74 // Propagate the exception across the connection and get out-of-here! 75 send_message(REPLY_EXCEPTION, serialise_error(err)); 76 throw; 77 } 78 /* Initialize things */ 69 79 #ifndef __WIN32__ 70 80 // It's simplest to just ignore SIGPIPE. We'll still know if the 71 81 // connection dies because we'll get EPIPE back from write(). … … 94 104 95 105 RemoteServer::~RemoteServer() 96 106 { 107 delete db; // wdb is either null or db - so it's ok 97 108 map<string, Xapian::Weight*>::const_iterator i; 98 109 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) { 99 110 delete i->second; -
common/remoteconnection.h
105 105 /// The file descriptor used for writing. 106 106 int fdout; 107 107 108 /// The context to report with errors 108 protected: 109 /// The context to report with errors (which subclasses are allowed 110 /// to manage) 109 111 std::string context; 112 private: 110 113 111 114 /// Buffer to hold unprocessed input. 112 115 std::string buffer; -
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
68 68 /// Registered weighting schemes. 69 69 map<string, Xapian::Weight *> wtschemes; 70 70 71 /// Initialisation code needed by both ctors.72 void initialise();73 74 71 /// Accept a message from the client. 75 72 message_type get_message(Xapian::timeout timeout, string & result, 76 73 message_type required_type = MSG_MAX); … … 139 136 void msg_replacedocumentterm(const std::string & message); 140 137 141 138 public: 142 /** Construct a read-onlyRemoteServer.139 /** Construct a RemoteServer. 143 140 * 144 * @param db The Xapian::Databaseto use.141 * @param dbpaths The paths to the xapian databases to use. 145 142 * @param fdin The file descriptor to read from. 146 143 * @param fdout The file descriptor to write to (fdin and fdout may be 147 144 * the same). … … 149 146 * (specified in milliseconds). 150 147 * @param idle_timeout_ Timeout while waiting for a new action from 151 148 * the client (specified in milliseconds). 149 * @param writable Should the DB be opened for writing? 152 150 */ 153 RemoteServer(Xapian::Database * db, int fdin, int fdout, 151 RemoteServer(const std::vector<std::string> &dbpaths, 152 int fdin, int fdout, 154 153 Xapian::timeout active_timeout_, 155 Xapian::timeout idle_timeout_); 154 Xapian::timeout idle_timeout_, 155 bool writable = false); 156 156 157 /** Construct a writable RemoteServer.158 *159 * @param wdb The Xapian::WritableDatabase to use.160 * @param fdin The file descriptor to read from.161 * @param fdout The file descriptor to write to (fdin and fdout may be162 * the same).163 * @param active_timeout_ Timeout for actions during a conversation164 * (specified in milliseconds).165 * @param idle_timeout_ Timeout while waiting for a new action from166 * the client (specified in milliseconds).167 */168 RemoteServer(Xapian::WritableDatabase * wdb, int fdin, int fdout,169 Xapian::timeout active_timeout_,170 Xapian::timeout idle_timeout_);171 172 157 /// Destructor. 173 158 ~RemoteServer(); 174 159