summaryrefslogtreecommitdiffstats
path: root/cli/src/cli-cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/cli-cmd.c')
-rw-r--r--cli/src/cli-cmd.c386
1 files changed, 386 insertions, 0 deletions
diff --git a/cli/src/cli-cmd.c b/cli/src/cli-cmd.c
new file mode 100644
index 000000000..b81f75b5b
--- /dev/null
+++ b/cli/src/cli-cmd.c
@@ -0,0 +1,386 @@
+/*
+ Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "cli.h"
+#include "cli-cmd.h"
+#include "cli-mem-types.h"
+#include "protocol-common.h"
+
+#include <fnmatch.h>
+
+static int cmd_done;
+static int cmd_sent;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t conn = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int cli_op_ret = 0;
+int connected = 0;
+
+int cli_cmd_log_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
+ const char **words, int wordcount);
+
+static unsigned
+cli_cmd_needs_connection (struct cli_cmd_word *word)
+{
+ if (!strcasecmp ("quit", word->word))
+ return 0;
+
+ if (!strcasecmp ("help", word->word))
+ return 0;
+
+ if (!strcasecmp ("getwd", word->word))
+ return 1;
+
+ if (!strcasecmp ("exit", word->word))
+ return 0;
+
+ return CLI_DEFAULT_CONN_TIMEOUT;
+}
+
+int
+cli_cmd_status_reset (void)
+{
+ int ret = 0;
+
+ ret = cli_cmd_lock ();
+ {
+ if (ret == 0) {
+ cmd_sent = 0;
+ cmd_done = 0;
+ }
+ }
+ ret = cli_cmd_unlock ();
+ return ret;
+
+}
+
+int
+cli_cmd_sent_status_get (int *status)
+{
+ int ret = 0;
+ GF_ASSERT (status);
+
+ ret = cli_cmd_lock ();
+ {
+ if (ret == 0)
+ *status = cmd_sent;
+ }
+ ret = cli_cmd_unlock ();
+ return ret;
+}
+
+int
+cli_cmd_process (struct cli_state *state, int argc, char **argv)
+{
+ int ret = 0;
+ struct cli_cmd_word *word = NULL;
+ struct cli_cmd_word *next = NULL;
+ int i = 0;
+
+ word = &state->tree.root;
+
+ if (!argc)
+ return 0;
+
+ for (i = 0; i < argc; i++) {
+ next = cli_cmd_nextword (word, argv[i]);
+
+ word = next;
+ if (!word)
+ break;
+
+ if (word->cbkfn)
+ break;
+ }
+
+ if (!word) {
+ cli_out ("unrecognized word: %s (position %d)",
+ argv[i], i);
+ return -1;
+ }
+
+ if (!word->cbkfn) {
+ cli_out ("unrecognized command");
+ return -1;
+ }
+
+ if ( strcmp (word->word,"help")==0 )
+ goto callback;
+
+ state->await_connected = cli_cmd_needs_connection (word);
+
+ ret = cli_cmd_await_connected (state->await_connected);
+ if (ret) {
+ cli_out ("Connection failed. Please check if gluster "
+ "daemon is operational.");
+ gf_log ("", GF_LOG_INFO, "Exiting with: %d", ret);
+ exit (ret);
+ }
+
+callback:
+ ret = word->cbkfn (state, word, (const char **)argv, argc);
+ (void) cli_cmd_status_reset ();
+ return ret;
+}
+
+int
+cli_cmd_input_token_count (const char *text)
+{
+ int count = 0;
+ const char *trav = NULL;
+ int is_spc = 1;
+
+ for (trav = text; *trav; trav++) {
+ if (*trav == ' ') {
+ is_spc = 1;
+ } else {
+ if (is_spc) {
+ count++;
+ is_spc = 0;
+ }
+ }
+ }
+
+ return count;
+}
+
+
+int
+cli_cmd_process_line (struct cli_state *state, const char *text)
+{
+ int count = 0;
+ char **tokens = NULL;
+ char **tokenp = NULL;
+ char *token = NULL;
+ char *copy = NULL;
+ char *saveptr = NULL;
+ int i = 0;
+ int ret = -1;
+
+ count = cli_cmd_input_token_count (text);
+
+ tokens = calloc (count + 1, sizeof (*tokens));
+ if (!tokens)
+ return -1;
+
+ copy = strdup (text);
+ if (!copy)
+ goto out;
+
+ tokenp = tokens;
+
+ for (token = strtok_r (copy, " \t\r\n", &saveptr); token;
+ token = strtok_r (NULL, " \t\r\n", &saveptr)) {
+ *tokenp = strdup (token);
+
+ if (!*tokenp)
+ goto out;
+ tokenp++;
+ i++;
+
+ }
+
+ ret = cli_cmd_process (state, count, tokens);
+out:
+ free (copy);
+
+ if (tokens)
+ cli_cmd_tokens_destroy (tokens);
+
+ return ret;
+}
+
+
+int
+cli_cmds_register (struct cli_state *state)
+{
+ int ret = 0;
+
+ ret = cli_cmd_volume_register (state);
+ if (ret)
+ goto out;
+
+ ret = cli_cmd_probe_register (state);
+ if (ret)
+ goto out;
+
+ ret = cli_cmd_system_register (state);
+ if (ret)
+ goto out;
+
+ ret = cli_cmd_misc_register (state);
+ if (ret)
+ goto out;
+
+ ret = cli_cmd_snapshot_register (state);
+ if (ret)
+ goto out;
+out:
+ return ret;
+}
+
+int
+cli_cmd_cond_init ()
+{
+
+ pthread_mutex_init (&cond_mutex, NULL);
+ pthread_cond_init (&cond, NULL);
+
+ pthread_mutex_init (&conn_mutex, NULL);
+ pthread_cond_init (&conn, NULL);
+
+ return 0;
+}
+
+int
+cli_cmd_lock ()
+{
+ pthread_mutex_lock (&cond_mutex);
+ return 0;
+}
+
+int
+cli_cmd_unlock ()
+{
+ pthread_mutex_unlock (&cond_mutex);
+ return 0;
+}
+
+static void
+seconds_from_now (unsigned secs, struct timespec *ts)
+{
+ struct timeval tv = {0,};
+
+ gettimeofday (&tv, NULL);
+
+ ts->tv_sec = tv.tv_sec + secs;
+ ts->tv_nsec = tv.tv_usec * 1000;
+}
+
+int
+cli_cmd_await_response (unsigned time)
+{
+ struct timespec ts = {0,};
+ int ret = 0;
+
+ cli_op_ret = -1;
+
+ seconds_from_now (time, &ts);
+ while (!cmd_done && !ret) {
+ ret = pthread_cond_timedwait (&cond, &cond_mutex,
+ &ts);
+ }
+
+ cmd_done = 0;
+
+ if (ret)
+ return ret;
+
+ return cli_op_ret;
+}
+
+int
+cli_cmd_broadcast_response (int32_t status)
+{
+
+ pthread_mutex_lock (&cond_mutex);
+ {
+ if (!cmd_sent)
+ goto out;
+ cmd_done = 1;
+ cli_op_ret = status;
+ pthread_cond_broadcast (&cond);
+ }
+
+
+out:
+ pthread_mutex_unlock (&cond_mutex);
+ return 0;
+}
+
+int32_t
+cli_cmd_await_connected (unsigned conn_timo)
+{
+ int32_t ret = 0;
+ struct timespec ts = {0,};
+
+ if (!conn_timo)
+ return 0;
+
+ pthread_mutex_lock (&conn_mutex);
+ {
+ seconds_from_now (conn_timo, &ts);
+ while (!connected && !ret) {
+ ret = pthread_cond_timedwait (&conn, &conn_mutex,
+ &ts);
+ }
+ }
+ pthread_mutex_unlock (&conn_mutex);
+
+
+ return ret;
+}
+
+int32_t
+cli_cmd_broadcast_connected ()
+{
+ pthread_mutex_lock (&conn_mutex);
+ {
+ connected = 1;
+ pthread_cond_broadcast (&conn);
+ }
+
+ pthread_mutex_unlock (&conn_mutex);
+
+ return 0;
+}
+
+int
+cli_cmd_submit (void *req, call_frame_t *frame,
+ rpc_clnt_prog_t *prog,
+ int procnum, struct iobref *iobref,
+ xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc)
+{
+ int ret = -1;
+ unsigned timeout = 0;
+
+ if ((GLUSTER_CLI_PROFILE_VOLUME == procnum) ||
+ (GLUSTER_CLI_HEAL_VOLUME == procnum))
+ timeout = CLI_TEN_MINUTES_TIMEOUT;
+ else
+ timeout = CLI_DEFAULT_CMD_TIMEOUT;
+
+ cli_cmd_lock ();
+ cmd_sent = 0;
+ ret = cli_submit_request (req, frame, prog,
+ procnum, NULL, this, cbkfn, xdrproc);
+
+ if (!ret) {
+ cmd_sent = 1;
+ ret = cli_cmd_await_response (timeout);
+ }
+
+ cli_cmd_unlock ();
+
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}