00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include <cstdlib>
00026
00027 #include "safeerrno.h"
00028
00029 #include <iostream>
00030 #include <string>
00031
00032 #include "gnu_getopt.h"
00033
00034 #include "xapian/error.h"
00035 #include "remotetcpserver.h"
00036
00037 using namespace std;
00038
00039 static void register_user_weighting_schemes(TcpServer &server) {
00040 (void)server;
00041
00042
00043
00044
00045
00046 }
00047
00048 const int MSECS_IDLE_TIMEOUT_DEFAULT = 60000;
00049 const int MSECS_ACTIVE_TIMEOUT_DEFAULT = 15000;
00050
00051 #define PROG_NAME "xapian-tcpsrv"
00052 #define PROG_DESC "TCP daemon for use with Xapian's remote backend"
00053
00054 #define OPT_HELP 1
00055 #define OPT_VERSION 2
00056
00057 static const char * opts = "I:p:a:i:t:oqw";
00058 static const struct option long_opts[] = {
00059 {"interface", required_argument, 0, 'I'},
00060 {"port", required_argument, 0, 'p'},
00061 {"active-timeout", required_argument, 0, 'a'},
00062 {"idle-timeout", required_argument, 0, 'i'},
00063 {"timeout", required_argument, 0, 't'},
00064 {"one-shot", no_argument, 0, 'o'},
00065 {"quiet", no_argument, 0, 'q'},
00066 {"writable", no_argument, 0, 'w'},
00067 {"help", no_argument, 0, OPT_HELP},
00068 {"version", no_argument, 0, OPT_VERSION},
00069 {NULL, 0, 0, 0}
00070 };
00071
00072 static void show_usage() {
00073 cout << "Usage: "PROG_NAME" [OPTIONS] DATABASE_DIRECTORY...\n\n"
00074 "Options:\n"
00075 " --port PORTNUM listen on port PORTNUM for connections (no default)\n"
00076 " --interface ADDRESS listen on the interface associated with name or\n"
00077 " address ADDRESS (default is all interfaces)\n"
00078 " --idle-timeout MSECS set timeout for idle connections (default " << MSECS_IDLE_TIMEOUT_DEFAULT << "ms)\n"
00079 " --active-timeout MSECS set timeout for active connections (default " << MSECS_ACTIVE_TIMEOUT_DEFAULT << "ms)\n"
00080 " --timeout MSECS set both timeout values\n"
00081 " --one-shot serve a single connection and exit\n"
00082 " --quiet disable information messages to stdout\n"
00083 " --writable allow updates (only one database directory allowed)\n"
00084 " --help display this help and exit\n"
00085 " --version output version information and exit" << endl;
00086 }
00087
00088 int main(int argc, char **argv) {
00089 string host;
00090 int port = 0;
00091 double active_timeout = MSECS_ACTIVE_TIMEOUT_DEFAULT * 1e-3;
00092 double idle_timeout = MSECS_IDLE_TIMEOUT_DEFAULT * 1e-3;
00093
00094 bool one_shot = false;
00095 bool verbose = true;
00096 bool writable = false;
00097 bool syntax_error = false;
00098
00099 int c;
00100 while ((c = gnu_getopt_long(argc, argv, opts, long_opts, NULL)) != -1) {
00101 switch (c) {
00102 case OPT_HELP:
00103 cout << PROG_NAME" - "PROG_DESC"\n\n";
00104 show_usage();
00105 exit(0);
00106 case OPT_VERSION:
00107 cout << PROG_NAME" - "PACKAGE_STRING << endl;
00108 exit(0);
00109 case 'I':
00110 host.assign(optarg);
00111 break;
00112 case 'p':
00113 port = atoi(optarg);
00114 break;
00115 case 'a':
00116 active_timeout = atoi(optarg) * 1e-3;
00117 break;
00118 case 'i':
00119 idle_timeout = atoi(optarg) * 1e-3;
00120 break;
00121 case 't':
00122 active_timeout = idle_timeout = atoi(optarg) * 1e-3;
00123 break;
00124 case 'o':
00125 one_shot = true;
00126 break;
00127 case 'q':
00128 verbose = false;
00129 break;
00130 case 'w':
00131 writable = true;
00132 break;
00133 default:
00134 syntax_error = true;
00135 }
00136 }
00137
00138 if (syntax_error || argv[optind] == NULL) {
00139 show_usage();
00140 exit(1);
00141 }
00142
00143 if (port <= 0 || port >= 65536) {
00144 cerr << "Error: must specify a valid port number (between 1 and 65535)."
00145 " We actually got " << port << endl;
00146 exit(1);
00147 }
00148
00149 if (writable && (argc - optind) != 1) {
00150 cerr << "Error: only one database directory allowed with '--writable'." << endl;
00151 exit(1);
00152 }
00153
00154 try {
00155 vector<string> dbnames;
00156
00157
00158 if (writable) {
00159 Xapian::WritableDatabase db(argv[optind], Xapian::DB_CREATE_OR_OPEN);
00160 dbnames.push_back(argv[optind]);
00161 } else {
00162 while (argv[optind]) {
00163 dbnames.push_back(argv[optind]);
00164 Xapian::Database db(argv[optind++]);
00165 }
00166 }
00167
00168 if (verbose) {
00169 cout << "Starting";
00170 if (writable)
00171 cout << " writable";
00172 cout << " server on";
00173 if (!host.empty())
00174 cout << " host " << host << ",";
00175 cout << " port " << port << endl;
00176 }
00177
00178 RemoteTcpServer server(dbnames, host, port, active_timeout,
00179 idle_timeout, writable, verbose);
00180
00181 if (verbose)
00182 cout << "Listening..." << endl;
00183
00184 register_user_weighting_schemes(server);
00185
00186 if (one_shot) {
00187 server.run_once();
00188 } else {
00189 server.run();
00190 }
00191 } catch (const Xapian::Error &e) {
00192 cerr << e.get_description() << endl;
00193 exit(1);
00194 } catch (const exception &e) {
00195 cerr << "Caught standard exception: " << e.what() << endl;
00196 exit(1);
00197 } catch (...) {
00198 cerr << "Caught unknown exception" << endl;
00199 exit(1);
00200 }
00201 }