Ticket #141: multi_writer_lock.patch

File multi_writer_lock.patch, 13.3 KB (added by Mark Hammond, 17 years ago)

patch as described

  • bin/xapian-tcpsrv.cc

     
    150150    }
    151151
    152152    try {
     153        vector<string> dbnames;
    153154        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);
    162160            }
    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]);
    177162        } 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                }
    181169            }
     170        }
    182171
    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        }
    190183
    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);
    193186
    194             if (verbose)
    195                 cout << "Listening..." << endl;
     187        if (verbose)
     188            cout << "Listening..." << endl;
    196189
    197             register_user_weighting_schemes(server);
     190        register_user_weighting_schemes(server);
    198191
    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();
    204196        }
    205197    } catch (const Xapian::Error &e) {
    206198        cerr << e.get_type() << ": " << e.get_msg();
  • bin/xapian-progsrv.cc

     
    5757
    5858int main(int argc, char **argv) {
    5959    /* variables needed in both try/catch blocks */
    60     Xapian::WritableDatabase wdb;
    61     Xapian::Database dbs;
    6260    unsigned int timeout = 60000;
    6361    bool writable = false;
    6462    bool syntax_error = false;
     
    9492        exit(1);
    9593    }
    9694
    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
    98100    try {
     101        Xapian::WritableDatabase wdb;
     102        Xapian::Database dbs;
    99103        if (writable) {
    100104            wdb = Xapian::WritableDatabase(argv[optind], Xapian::DB_CREATE_OR_OPEN);
     105            dbnames.push_back(argv[optind]);
    101106        } else {
    102107            while (argv[optind]) {
     108                dbnames.push_back(argv[optind]);
    103109                dbs.add_database(Xapian::Database(argv[optind++]));
    104110            }
    105111        }
     
    116122     * on to the remote end, as the RemoteServer will do that itself.
    117123     */
    118124    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());
    124129
    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();
    134131    } catch (...) {
    135132    }
    136133}
  • net/tcpserver.cc

     
    5454#endif
    5555
    5656/// The TcpServer constructor, taking a database and a listening port.
    57 TcpServer::TcpServer(Xapian::Database db_, const std::string & host, int port,
     57TcpServer::TcpServer(const vector<std::string> &dbpaths_, const std::string & host, int port,
    5858                     int msecs_active_timeout_,
    5959                     int msecs_idle_timeout_,
     60                     bool writable_,
    6061                     bool verbose_)
    61         : writable(false), db(db_), listen_socket(get_listening_socket(host, port)),
     62        : writable(writable_), listen_socket(get_listening_socket(host, port)),
    6263          msecs_active_timeout(msecs_active_timeout_),
    6364          msecs_idle_timeout(msecs_idle_timeout_),
     65          dbpaths(dbpaths_),
    6466          verbose(verbose_)
    6567{
    66 
    6768}
    6869
    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 
    8170int
    8271TcpServer::get_listening_socket(const std::string & host, int port)
    8372{
     
    224213        // child code
    225214        close(listen_socket);
    226215        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);
    237220            }
    238221        } catch (const Xapian::Error &err) {
    239222            cerr << "Got exception " << err.get_type()
     
    291274    while (true) {
    292275        try {
    293276            run_once();
    294         } catch (const Xapian::DatabaseModifiedError &) {
    295             cerr << "Database modified - calling db.reopen()" << endl;
    296             db.reopen();
    297277        } catch (const Xapian::Error &err) {
    298278            // FIXME: better error handling.
    299279            cerr << "Caught " << err.get_type()
     
    367347TcpServer::handle_one_request(int connected_socket)
    368348{
    369349    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();
    381355    } catch (const Xapian::Error &err) {
    382356        cerr << "Got exception " << err.get_type()
    383357             << ": " << err.get_msg() << endl;
     
    441415            // really matter...
    442416            CloseHandle(hthread);
    443417       
    444         } catch (const Xapian::DatabaseModifiedError &) {
    445             cerr << "Database modified - calling db.reopen()" << endl;
    446             db.reopen();
    447418        } catch (const Xapian::Error &err) {
    448419            // FIXME: better error handling.
    449420            cerr << "Caught " << err.get_type()
  • net/remoteserver.cc

     
    4141/// Class to throw when we receive the connection closing message.
    4242struct ConnectionClosed { };
    4343
    44 RemoteServer::RemoteServer(Xapian::Database * db_,
     44RemoteServer::RemoteServer(const std::vector<std::string> &dbpaths,
    4545                           int fdin_, int fdout_,
    4646                           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),
    5051      active_timeout(active_timeout_), idle_timeout(idle_timeout_)
    5152{
     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    }
    5270    initialise();
    5371}
    5472
    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 
    6673void
    6774RemoteServer::initialise()
    6875{
     
    94101
    95102RemoteServer::~RemoteServer()
    96103{
     104    delete db; // wdb is either null or db - so its ok
    97105    map<string, Xapian::Weight*>::const_iterator i;
    98106    for (i = wtschemes.begin(); i != wtschemes.end(); ++i) {
    99107        delete i->second;
  • common/tcpserver.h

     
    4242    /// Don't allow copying.
    4343    TcpServer(const TcpServer &);
    4444
     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
    4549    /** Is this a WritableDatabase?
    4650     *
    47      *  If true, the wdb member is used.  If false, the db member is.
    4851     */
    4952    bool writable;
    5053
    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 
    5754    /** The socket we're listening on. */
    5855    int listen_socket;
    5956
     
    8178    /** Construct a TcpServer for a Database and start listening for
    8279     *  connections.
    8380     *
    84      *  @param db_      The Database to provide remote access to.
     81     *  @param dbpaths_ The locations of the databases we should open.
    8582     *  @param host     The hostname or address for the interface to listen on
    8683     *                  (or "" to listen on all interfaces).
    8784     *  @port           The TCP port number to listen on.
     
    9087     *                                  (default 10000).
    9188     *  @param msecs_idle_timeout       Timeout between operations (in
    9289     *                                  milliseconds) (default 60000).
     90     *  @param writable_                Should we open the DB for writing? (default
     91     *                          false).
    9392     *  @param verbose_         Should we produce output when connections are
    9493     *                          made or lost? (default true).
    9594     */
    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,
    9796              int msecs_normal_timeout_ = 10000,
    9897              int msecs_idle_timeout_ = 60000,
     98              bool writable_ = false,
    9999              bool verbose_ = true);
    100100
    101     /** Construct a TcpServer for a WritableDatabase and start listening for
    102      *  connections.
    103      *
    104      *  @param db_      The WritableDatabase to provide remote access to.
    105      *  @param host     The hostname or address for the interface to listen on
    106      *                  (or "" to listen on all interfaces).
    107      *  @port           The TCP port number to listen on.
    108      *  @param msecs_active_timeout     Timeout between messages during a
    109      *                                  single operation (in milliseconds)
    110      *                                  (default 10000).
    111      *  @param msecs_idle_timeout       Timeout between operations (in
    112      *                                  milliseconds) (default 60000).
    113      *  @param verbose_         Should we produce output when connections are
    114      *                          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 
    121101    /** Destructor. */
    122102    ~TcpServer();
    123103
  • common/remoteserver.h

     
    150150     *  @param idle_timeout_    Timeout while waiting for a new action from
    151151     *                  the client (specified in millisrconds).
    152152     */
    153     RemoteServer(Xapian::Database * db, int fdin, int fdout,
     153    RemoteServer(const std::vector<std::string> &dbpaths, int fdin, int fdout,
    154154                 Xapian::timeout active_timeout_ = 10000,
    155                  Xapian::timeout idle_timeout_ = 60000);
     155                 Xapian::timeout idle_timeout_ = 60000,
     156                 bool writable = false);
    156157
    157158    /** Construct a writable RemoteServer.
    158159     *