summaryrefslogtreecommitdiffstats
path: root/cli/src/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/cli.c')
-rw-r--r--cli/src/cli.c467
1 files changed, 467 insertions, 0 deletions
diff --git a/cli/src/cli.c b/cli/src/cli.c
new file mode 100644
index 00000000000..970db712fe3
--- /dev/null
+++ b/cli/src/cli.c
@@ -0,0 +1,467 @@
+/*
+ Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/file.h>
+#include <netdb.h>
+#include <signal.h>
+#include <libgen.h>
+
+#include <sys/utsname.h>
+
+#include <stdint.h>
+#include <pthread.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <semaphore.h>
+#include <errno.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#ifdef HAVE_MALLOC_STATS
+#ifdef DEBUG
+#include <mcheck.h>
+#endif
+#endif
+
+#include "cli.h"
+#include "cli-cmd.h"
+#include "cli-mem-types.h"
+
+#include "xlator.h"
+#include "glusterfs.h"
+#include "compat.h"
+#include "logging.h"
+#include "dict.h"
+#include "list.h"
+#include "timer.h"
+#include "stack.h"
+#include "revision.h"
+#include "common-utils.h"
+#include "event.h"
+#include "globals.h"
+#include "syscall.h"
+
+#include <fnmatch.h>
+
+/* using argp for command line parsing */
+static char gf_doc[] = "";
+
+static char argp_doc[] = "COMMAND [PARAM ...]";
+
+const char *argp_program_version = "" \
+ PACKAGE_NAME" "PACKAGE_VERSION" built on "__DATE__" "__TIME__ \
+ "\nRepository revision: " GLUSTERFS_REPOSITORY_REVISION "\n" \
+ "Copyright (c) 2006-2010 Gluster Inc. " \
+ "<http://www.gluster.com>\n" \
+ "GlusterFS comes with ABSOLUTELY NO WARRANTY.\n" \
+ "You may redistribute copies of GlusterFS under the terms of "\
+ "the GNU General Public License.";
+
+const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
+
+static struct argp_option gf_options[] = {
+ {0, 0, 0, 0, "Basic options:"},
+ {"debug", ARGP_DEBUG_KEY, 0, 0,
+ "Process runs in foreground and logs to console"},
+ {0, }
+};
+
+struct rpc_clnt *global_rpc;
+
+rpc_clnt_prog_t *cli_rpc_prog;
+
+
+extern struct rpc_clnt_program cli3_1_prog;
+
+static error_t
+parse_opts (int key, char *arg, struct argp_state *argp_state)
+{
+ struct cli_state *state = NULL;
+ char **argv = NULL;
+
+ state = argp_state->input;
+
+ switch (key) {
+ case ARGP_DEBUG_KEY:
+ break;
+ case ARGP_KEY_ARG:
+ if (!state->argc) {
+ argv = calloc (state->argc + 2,
+ sizeof (*state->argv));
+ } else {
+ argv = realloc (state->argv, (state->argc + 2) *
+ sizeof (*state->argv));
+ }
+ if (!argv)
+ return -1;
+
+ state->argv = argv;
+
+ argv[state->argc] = strdup (arg);
+ if (!argv[state->argc])
+ return -1;
+ state->argc++;
+ argv[state->argc] = NULL;
+
+ break;
+ }
+
+ return 0;
+}
+
+
+static char *
+generate_uuid ()
+{
+ char tmp_str[1024] = {0,};
+ char hostname[256] = {0,};
+ struct timeval tv = {0,};
+ struct tm now = {0, };
+ char now_str[32];
+
+ if (gettimeofday (&tv, NULL) == -1) {
+ gf_log ("glusterfsd", GF_LOG_ERROR,
+ "gettimeofday: failed %s",
+ strerror (errno));
+ }
+
+ if (gethostname (hostname, 256) == -1) {
+ gf_log ("glusterfsd", GF_LOG_ERROR,
+ "gethostname: failed %s",
+ strerror (errno));
+ }
+
+ localtime_r (&tv.tv_sec, &now);
+ strftime (now_str, 32, "%Y/%m/%d-%H:%M:%S", &now);
+ snprintf (tmp_str, 1024, "%s-%d-%s:%"
+#ifdef GF_DARWIN_HOST_OS
+ PRId32,
+#else
+ "ld",
+#endif
+ hostname, getpid(), now_str, tv.tv_usec);
+
+ return gf_strdup (tmp_str);
+}
+
+static int
+glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx)
+{
+ cmd_args_t *cmd_args = NULL;
+ struct rlimit lim = {0, };
+ call_pool_t *pool = NULL;
+
+ xlator_mem_acct_init (THIS, cli_mt_end);
+
+ ctx->process_uuid = generate_uuid ();
+ if (!ctx->process_uuid)
+ return -1;
+
+ ctx->page_size = 128 * GF_UNIT_KB;
+
+ ctx->iobuf_pool = iobuf_pool_new (8 * GF_UNIT_MB, ctx->page_size);
+ if (!ctx->iobuf_pool)
+ return -1;
+
+ ctx->event_pool = event_pool_new (DEFAULT_EVENT_POOL_SIZE);
+ if (!ctx->event_pool)
+ return -1;
+
+ pool = GF_CALLOC (1, sizeof (call_pool_t),
+ cli_mt_call_pool_t);
+ if (!pool)
+ return -1;
+ INIT_LIST_HEAD (&pool->all_frames);
+ LOCK_INIT (&pool->lock);
+ ctx->pool = pool;
+
+ pthread_mutex_init (&(ctx->lock), NULL);
+
+ cmd_args = &ctx->cmd_args;
+
+ /* parsing command line arguments */
+ cmd_args->log_file = "/dev/stderr";
+ cmd_args->log_level = GF_LOG_NORMAL;
+
+ INIT_LIST_HEAD (&cmd_args->xlator_options);
+
+ lim.rlim_cur = RLIM_INFINITY;
+ lim.rlim_max = RLIM_INFINITY;
+ setrlimit (RLIMIT_CORE, &lim);
+
+ return 0;
+}
+
+
+static int
+logging_init (glusterfs_ctx_t *ctx)
+{
+ cmd_args_t *cmd_args = NULL;
+
+ cmd_args = &ctx->cmd_args;
+
+ if (gf_log_init (cmd_args->log_file) == -1) {
+ fprintf (stderr,
+ "failed to open logfile %s. exiting\n",
+ cmd_args->log_file);
+ return -1;
+ }
+
+ gf_log_set_loglevel (cmd_args->log_level);
+
+ return 0;
+}
+
+int
+cli_submit_request (void *req, call_frame_t *frame,
+ rpc_clnt_prog_t *prog,
+ int procnum, struct iobref *iobref,
+ cli_serialize_t sfunc, xlator_t *this,
+ fop_cbk_fn_t cbkfn)
+{
+ int ret = -1;
+ int count = 0;
+ char start_ping = 0;
+ struct iovec iov = {0, };
+ struct iobuf *iobuf = NULL;
+ char new_iobref = 0;
+
+ GF_ASSERT (this);
+
+ iobuf = iobuf_get (this->ctx->iobuf_pool);
+ if (!iobuf) {
+ goto out;
+ };
+
+ if (!iobref) {
+ iobref = iobref_new ();
+ if (!iobref) {
+ goto out;
+ }
+
+ new_iobref = 1;
+ }
+
+ iobref_add (iobref, iobuf);
+
+ iov.iov_base = iobuf->ptr;
+ iov.iov_len = 128 * GF_UNIT_KB;
+
+
+ /* Create the xdr payload */
+ if (req && sfunc) {
+ ret = sfunc (iov, req);
+ if (ret == -1) {
+ goto out;
+ }
+ iov.iov_len = ret;
+ count = 1;
+ }
+
+ /* Send the msg */
+ ret = rpc_clnt_submit (global_rpc, prog, procnum, cbkfn,
+ &iov, count,
+ NULL, 0, iobref, frame);
+
+ if (ret == 0) {
+ pthread_mutex_lock (&global_rpc->conn.lock);
+ {
+ if (!global_rpc->conn.ping_started) {
+ start_ping = 1;
+ }
+ }
+ pthread_mutex_unlock (&global_rpc->conn.lock);
+ }
+
+ if (start_ping)
+ //client_start_ping ((void *) this);
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int
+parse_cmdline (int argc, char *argv[], struct cli_state *state)
+{
+ int ret = 0;
+ struct argp argp = { 0,};
+
+ argp.options = gf_options;
+ argp.parser = parse_opts;
+ argp.args_doc = argp_doc;
+ argp.doc = gf_doc;
+
+ ret = argp_parse (&argp, argc, argv, ARGP_IN_ORDER, NULL, state);
+
+ return ret;
+}
+
+
+int
+cli_cmd_tree_init (struct cli_cmd_tree *tree)
+{
+ struct cli_cmd_word *root = NULL;
+ int ret = 0;
+
+ root = &tree->root;
+ root->tree = tree;
+
+ return ret;
+}
+
+
+int
+cli_state_init (struct cli_state *state)
+{
+ struct cli_cmd_tree *tree = NULL;
+ int ret = 0;
+
+ tree = &state->tree;
+ tree->state = state;
+
+ ret = cli_cmd_tree_init (tree);
+
+ return ret;
+}
+
+
+int
+cli_out (const char *fmt, ...)
+{
+ struct cli_state *state = NULL;
+ va_list ap;
+
+ state = global_state;
+
+ va_start (ap, fmt);
+
+#ifdef HAVE_READLINE
+ if (state->rl_enabled && !state->rl_processing)
+ return cli_rl_out(state, fmt, ap);
+#endif
+
+ return vprintf (fmt, ap);
+}
+
+struct rpc_clnt *
+cli_rpc_init (struct cli_state *state)
+{
+ struct rpc_clnt *rpc = NULL;
+ struct rpc_clnt_config rpc_cfg = {0,};
+ dict_t *options = NULL;
+ int ret = -1;
+
+ rpc_cfg.remote_host = "localhost";
+ rpc_cfg.remote_port = CLI_GLUSTERD_PORT;
+
+ cli_rpc_prog = &cli3_1_prog;
+ options = dict_new ();
+ if (!options)
+ goto out;
+
+ ret = dict_set_str (options, "remote-host", "localhost");
+ if (ret)
+ goto out;
+
+ ret = dict_set_int32 (options, "remote-port", CLI_GLUSTERD_PORT);
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (options, "transport.address-family", "inet");
+ if (ret)
+ goto out;
+
+ rpc = rpc_clnt_init (&rpc_cfg, options, THIS->ctx, THIS->name);
+
+out:
+ return rpc;
+}
+
+struct cli_state *global_state;
+
+int
+main (int argc, char *argv[])
+{
+ struct cli_state state = {0, };
+ int ret = -1;
+ glusterfs_ctx_t *ctx = NULL;
+
+ ret = glusterfs_globals_init ();
+ if (ret)
+ return ret;
+
+ ctx = glusterfs_ctx_get ();
+ if (!ctx)
+ return ENOMEM;
+
+ ret = glusterfs_ctx_defaults_init (ctx);
+ if (ret)
+ goto out;
+
+ ret = cli_state_init (&state);
+ if (ret)
+ goto out;
+
+ state.ctx = ctx;
+ global_state = &state;
+
+ ret = parse_cmdline (argc, argv, &state);
+ if (ret)
+ goto out;
+
+ ret = logging_init (ctx);
+ if (ret)
+ goto out;
+
+ ret = cli_cmds_register (&state);
+ if (ret)
+ goto out;
+
+ ret = cli_input_init (&state);
+ if (ret)
+ goto out;
+
+ global_rpc = cli_rpc_init (&state);
+ if (!global_rpc)
+ goto out;
+
+ ret = event_dispatch (ctx->event_pool);
+
+out:
+// glusterfs_ctx_destroy (ctx);
+
+ return ret;
+}