/* * Copyright (C) 2005 Network Applied Communication Laboratory Co., Ltd. * * This file is part of Rast. * See the file COPYING for redistribution information. * */ #include #include #include #include #include #include #include #include "rast/rast.h" #include "rast/merger.h" #include "rast/xmlrpc_server.h" #define OPTION_READ_ONLY 256 #define OPTION_READ_WRITE 257 #define OPTION_PORT 258 #define OPTION_PID_FILE 259 #define OPTION_LOG_FILE 260 #define OPTION_HELP 261 #define DEFAULT_PORT 9999 static char * format_option(const apr_getopt_option_t *option, apr_pool_t *pool) { char *s; if (option == NULL) { return "?"; } if (option->optch <= 0xff) { s = apr_psprintf(pool, "-%c [--%s]", option->optch, option->name); } else { s = apr_psprintf(pool, "--%s", option->name); } if (option->has_arg) { s = apr_pstrcat(pool, s, " arg", NULL); } if (option->description != NULL) { s = apr_psprintf(pool, "%-24s : %s", s, option->description); } return s; } static char * create_usage(apr_getopt_option_t *opts, apr_pool_t *pool) { char *usage = ""; int i; for (i = 0; opts[i].optch != 0; i++) { char *line = format_option(&opts[i], pool); usage = apr_pstrcat(pool, usage, " ", line, "\n", NULL); } return usage; } typedef struct { int port; const char *pid_filename; const char *log_filename; } xmlrpc_server_option_t; static rast_error_t * xmlrpc_server_abyss_initialize(int argc, const char **argv, xmlrpc_server_t *server, xmlrpc_server_option_t *options) { int flags, count, num_dbs, i; const char **p, *db_name; xmlrpc_server_option_t default_cmd_options = { .port = DEFAULT_PORT, .pid_filename = NULL, .log_filename = NULL, }; rast_db_open_option_t *open_options; rast_error_t *error; rast_db_t *db, **dbs; apr_pool_t *pool, *option_pool; apr_getopt_t *os; apr_getopt_option_t opts[] = { { .name = "read-only", .optch = OPTION_READ_ONLY, .has_arg = 0, .description = "start rast_xmlrpc_server with read-only mode.", }, { .name = "read-write", .optch = OPTION_READ_WRITE, .has_arg = 0, .description = "start rast_xmlrpc_server with read-write mode.", }, { .name = "port", .optch = OPTION_PORT, .has_arg = 1, .description = "listen port number.", }, { .name = "pid-file", .optch = OPTION_PID_FILE, .has_arg = 1, .description = "write server process ID file.", }, { .name = "log-file", .optch = OPTION_LOG_FILE, .has_arg = 1, .description = "write server log.", }, { .name = "help", .optch = OPTION_HELP, .has_arg = 0, .description = "show usage.", }, {0}, }; if (argc < 1) { fprintf(stderr, "Usage: servertest rast_db\n"); exit(1); } apr_initialize(); atexit(apr_terminate); error = rast_initialize(); if (error != RAST_OK) { return error; } atexit(rast_finalize); apr_pool_create_ex(&pool, NULL, NULL, NULL); server->pool = pool; *options = default_cmd_options; flags = RAST_DB_RDONLY; apr_pool_create(&option_pool, server->pool); apr_getopt_init(&os, option_pool, argc, argv); for (count = 0; ; count++) { int option_char; const char *option_arg; apr_status_t status; status = apr_getopt_long(os, opts, &option_char, &option_arg); if (status == APR_EOF) { break; } if (status != APR_SUCCESS) { char message[RAST_BUFSIZ]; apr_strerror(status, message, sizeof(message)); fprintf(stderr, "apr_error: %s\n", message); apr_pool_destroy(option_pool); exit(2); } if (option_arg != NULL) { count++; } switch (option_char) { case OPTION_READ_ONLY: flags = RAST_DB_RDONLY; break; case OPTION_READ_WRITE: flags = RAST_DB_RDWR; break; case OPTION_PORT: options->port = atoi(option_arg); break; case OPTION_PID_FILE: options->pid_filename = option_arg; break; case OPTION_LOG_FILE: options->log_filename = option_arg; break; case OPTION_HELP: fprintf(stderr, "%s\n", create_usage(opts, option_pool)); apr_pool_destroy(option_pool); exit(0); break; default: fprintf(stderr, "%s\n", create_usage(opts, option_pool)); apr_pool_destroy(option_pool); return rast_error(RAST_ERROR_INVALID_ARGUMENT, ""); } } apr_pool_destroy(option_pool); num_dbs = argc - (count + 1); if (num_dbs <= 0) { fprintf(stderr, "%s\n", create_usage(opts, option_pool)); return rast_error(RAST_ERROR_INVALID_ARGUMENT, ""); } dbs = (rast_db_t **) apr_palloc(server->pool, sizeof(rast_db_t *) * num_dbs); p = &argv[count + 1]; open_options = NULL; for (i = 0; i < num_dbs; i++) { db_name = *p; error = rast_db_open(&dbs[i], db_name, flags, open_options, server->pool); if (error != RAST_OK) { return error; } p++; } if (num_dbs == 1) { db = dbs[0]; } else { error = rast_merger_open(&db, dbs, num_dbs, server->pool); if (error != RAST_OK) { return error; } } server->db = db; return RAST_OK; } static const char * get_tmpdir(void) { const char *tmpdir; if ((tmpdir = getenv("TMPDIR")) == NULL && (tmpdir = getenv("TMP")) == NULL && (tmpdir = getenv("TEMP")) == NULL) { tmpdir = "/tmp"; } return tmpdir; } static rast_error_t * initialize_abyss(xmlrpc_server_t *server, xmlrpc_server_option_t *options) { apr_status_t status; apr_file_t *file; char *abyss_conf_filename; abyss_conf_filename = apr_pstrcat(server->pool, get_tmpdir(), "/rast_xmlrpc_server.XXXXXX", NULL); status = apr_file_mktemp(&file, abyss_conf_filename, 0, server->pool); if (status != APR_SUCCESS) { return apr_status_to_rast_error(status); } apr_file_printf(file, "port %d\n", options->port); if (options->pid_filename != NULL) { apr_file_printf(file, "pidfile %s\n", options->pid_filename); } if (options->log_filename != NULL) { apr_file_printf(file, "logfile %s\n", options->log_filename); } xmlrpc_server_abyss_init(XMLRPC_SERVER_ABYSS_NO_FLAGS, (char *) abyss_conf_filename); return RAST_OK; } int main(int argc, const char **argv) { xmlrpc_server_t server; xmlrpc_server_option_t options; rast_error_t *error; error = xmlrpc_server_abyss_initialize(argc, argv, &server, &options); if (error != RAST_OK) { fprintf(stderr, "%s", error->message); exit(1); } initialize_abyss(&server, &options); xmlrpc_server_abyss_add_method_w_doc("rast.register", &xmlrpc_server_register, (void *) &server, "S:S", "register document to database."); xmlrpc_server_abyss_add_method_w_doc("rast.search", &xmlrpc_server_search, (void *) &server, "S:S", "search document from database."); xmlrpc_server_abyss_add_method_w_doc("rast.delete", &xmlrpc_server_delete, (void *) &server, "S:S", "delete document from database."); xmlrpc_server_abyss_add_method_w_doc("rast.update", &xmlrpc_server_update, (void *) &server, "S:S", "update document at database."); xmlrpc_server_abyss_add_method_w_doc("rast.get_text", &xmlrpc_server_get_text, (void *) &server, "S:S", "get text from database."); xmlrpc_server_abyss_add_method_w_doc("rast.encoding", &xmlrpc_server_encoding, (void *) &server, "S", "get database encoding."); xmlrpc_server_abyss_add_method_w_doc("rast.properties", &xmlrpc_server_properties, (void *) &server, "A", "get propertie's definitions from database."); xmlrpc_server_abyss_run(); return 0; }