diff --git a/.gitmodules b/.gitmodules index 56afac8cb1ddcb8821bdf0d9e696b86124d0f5cd..992d2a7fcb186e5fc2376c3ec12a4df8978cdfb7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "src/lib/msgpuck"] path = src/lib/msgpuck url = https://github.com/tarantool/msgpuck.git +[submodule "connector/c/tb"] + path = connector/c/tb + url = https://github.com/tarantool/tarantool-c diff --git a/CMakeLists.txt b/CMakeLists.txt index 194f356ce330437de823c4e330bfc852577ed5cf..8909faa03b704b2e729b663b161b48fb4d369ba6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -348,7 +348,7 @@ include (cmake/rpm.cmake) add_subdirectory(cfg) # Disable connector_c for 1.6 -# add_subdirectory(connector) +add_subdirectory(connector) add_subdirectory(src) add_subdirectory(extra) add_subdirectory(client) diff --git a/client/tarantool/CMakeLists.txt b/client/tarantool/CMakeLists.txt index 12b71cf7de5f7731e9e507a4193636fd0e261168..563c03041ad07a867b07ebbf5d15be9f9f5ef03f 100644 --- a/client/tarantool/CMakeLists.txt +++ b/client/tarantool/CMakeLists.txt @@ -1,24 +1,24 @@ -project(tnt_cli) -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) include(FindReadline) if (NOT READLINE_FOUND) message(FATAL_ERROR "readline library not found.") endif() -set (cli "tarantool") -set (cli_sources tc.c tc_opt.c tc_admin.c tc_query.c tc_print.c tc_buf.c - tc_cli.c tc_pager.c) - -set (cli_libs gopt ${READLINE_LIBRARIES}) +set(cli "tarantool") +set(cli_sources main.c opt.c query.c print.c buf.c cli.c pager.c store.c) +set(cli_libs gopt ${READLINE_LIBRARIES} tb) include_directories(${READLINE_INCLUDE_DIR}) +add_definitions("-DTB_LOCAL=${PROJECT_SOURCE_DIR}/connector/c/tb/lib") + list(APPEND cli_sources ${CMAKE_SOURCE_DIR}/src/errcode.c) add_executable(${cli} ${cli_sources}) set_source_files_compile_flags("TARANTOOL" ${cli_sources}) target_link_libraries (${cli} ${cli_libs}) -install (TARGETS ${cli} DESTINATION bin) +install(TARGETS ${cli} DESTINATION bin) + diff --git a/client/tarantool/tc_buf.c b/client/tarantool/buf.c similarity index 99% rename from client/tarantool/tc_buf.c rename to client/tarantool/buf.c index 4826ed1361294867c03afb24155875d829d138a5..d8aad7eb2c64556b5efd4abcac165e25d835d929 100644 --- a/client/tarantool/tc_buf.c +++ b/client/tarantool/buf.c @@ -32,7 +32,7 @@ #include <stddef.h> #include <ctype.h> -#include "client/tarantool/tc_buf.h" +#include "client/tarantool/buf.h" /* Strip trailing ws from (char*) */ size_t strip_end_ws(char *str) { diff --git a/client/tarantool/tc_buf.h b/client/tarantool/buf.h similarity index 99% rename from client/tarantool/tc_buf.h rename to client/tarantool/buf.h index 3e528c20d7742a424aa9a4c417f81a5d8f7ddd39..fd1ad2e47d8cb896c9a35e3c6106a3739fcb648b 100644 --- a/client/tarantool/tc_buf.h +++ b/client/tarantool/buf.h @@ -26,6 +26,7 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + #define TC_BUF_INIT_SIZE 4096 #define TC_BUF_MULTIPLIER 2 diff --git a/client/tarantool/cli.c b/client/tarantool/cli.c new file mode 100644 index 0000000000000000000000000000000000000000..83e6a0eb918d49c917ff044809f535806e70666e --- /dev/null +++ b/client/tarantool/cli.c @@ -0,0 +1,469 @@ +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <lib/tarantool.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <wchar.h> + +#include <readline/readline.h> +#include <readline/history.h> + +#include <client/tarantool/opt.h> +#include <client/tarantool/main.h> +#include <client/tarantool/pager.h> +#include <client/tarantool/query.h> +#include <client/tarantool/cli.h> +#include <client/tarantool/print.h> +#include <client/tarantool/buf.h> + +extern struct tarantool_client tc; + +static inline int tc_clierror(char *e) { + if (e) + tc_printf("%s\n", e); + return 1; +} + +static int tc_clireconnect(void) +{ + tb_sesclose(&tc.console); + int rc = tb_sesconnect(&tc.console); + if (rc == -1) { + tc_printf("reconnect: admin console connection failed\n"); + return 1; + } + tc_printf("reconnected\n"); + return 0; +} + +static int +tc_cliquery(char *cmd, int exit) +{ + tc_query_t cb = (exit) ? NULL : tc_printer; + if (!exit) + tc_pager_start(); + if (tc_query(cmd, cb) == -1) + return tc_clierror("failed to send admin query"); + if (!exit) + tc_pager_stop(); + return 0; +} + +enum tc_keywords { + TC_EXIT = TB_TCUSTOM + 1, + TC_LOADFILE, + TC_HELP, + TC_SETOPT, + TC_SETOPT_DELIM, + TC_SETOPT_PAGER +}; + +static struct tbkeyword tc_keywords[] = +{ + { "exit", 4, TC_EXIT }, + { "quit", 4, TC_EXIT }, + { "help", 4, TC_HELP }, + { "loadfile", 8, TC_LOADFILE }, + { "setopt", 6, TC_SETOPT }, + { "delimiter", 9, TC_SETOPT_DELIM }, + { "pager", 5, TC_SETOPT_PAGER }, + { NULL, 0, TB_TNONE } +}; + +enum tc_cliret { + TC_CLI_OK, + TC_CLI_ERROR, + TC_CLI_EXIT +}; + +static void +tc_cmdusage(void) +{ + char usage[] = + "---\n" + " - console client commands\n" + " - help\n" + " - loadfile 'path'\n" + " - setopt key=val\n" + " - - delimiter = \'string\'\n" + " - pager = \'command\'\n" + "...\n"; + tc_printf("%s", usage); +} + +#if 0 +static int +tc_cmddostring(char *buf, size_t size, int *reconnect) +{ +#if 0 + struct tnt_tuple args; + tnt_tuple_init(&args); + tnt_tuple_add(&args, buf, size); + int rc = tnt_call(tc.net, 0, "box.dostring", &args); + if (rc < 0) + goto error; + rc = tnt_flush(tc.net); + if (rc < 0) + goto error; + tnt_tuple_free(&args); + char *e = NULL; + tc_pager_start(); + if (tc_query_foreach(tc_query_printer, NULL, &e) == -1) { + *reconnect = tc_cl_error(e); + return -1; + } + tc_pager_stop(); + return 0; +error: + tc_printf("error: %s\n", tnt_strerror(tc.net)); + tnt_tuple_free(&args); + return -1; +#endif + (void)buf; + (void)size; + (void)reconnect; + return 0; +} + +static int +tc_cmd_loadfile(char *path, int *reconnect) +{ + struct stat st; + if (stat(path, &st) == -1) { + tc_printf("error: stat(): %s\n", strerror(errno)); + return -1; + } + int fd = open(path, O_RDONLY); + if (fd == -1) + return -1; + char *buf = (char *)malloc(st.st_size); + if (buf == NULL) { + tc_printf(TC_ALLOCATION_ERROR, + st.st_size); + return -1; + } + size_t off = 0; + do { + ssize_t r = read(fd, buf + off, st.st_size - off); + if (r == -1) { + close(fd); + free(buf); + tc_printf("error: read(): %s\n", strerror(errno)); + return -1; + } + off += r; + } while (off != st.st_size); + close(fd); + + int rc = tc_cmd_dostring(buf, st.st_size, reconnect); + free(buf); + return rc; +} +#endif + +static void +tc_strip(char *cmd) +{ + int len = strlen(cmd); + int offset = 0; + for (int i = 0; i < len - 1; ++i) + if (cmd[i] == '\\' && cmd[i + 1] == 'n') + cmd[i++ - offset++] = '\n'; + else if (offset != 0) + cmd[i - offset] = cmd[i]; + cmd[len - offset] = '\0'; +} + +static void +tc_setopt(struct tblex *lex) +{ + struct tbtoken *tk; + switch (tb_lex(lex, &tk)) { + case TC_SETOPT_DELIM: + if (tb_lex(lex, &tk) != '=') + tb_lexpush(lex, tk); + if (tb_lex(lex, &tk) != TB_TSTRING) { + tc_printf("---\n"); + tc_printf(" - Expected delimiter='string'\n"); + tc_printf("---\n"); + break; + } + if (! tk->v.s.size) { + if (tc.opt.delim) + free(tc.opt.delim); + tc.opt.delim = NULL; + tc.opt.delim_len = 0; + break; + } + char *temp = tc_malloc(tk->v.s.size + 1); + strncpy(temp, (const char*)tk->v.s.data, tk->v.s.size + 1); + temp[tk->v.s.size] = '\0'; + tc_strip(temp); + tc.opt.delim = temp; + tc.opt.delim_len = strlen(tc.opt.delim); + break; + case TC_SETOPT_PAGER: + if (tb_lex(lex, &tk) == '=' && + tb_lex(lex, &tk) == TB_TSTRING) { + if (! tk->v.s.size) { + if (tc.opt.pager) + free(tc.opt.pager); + tc.opt.pager = NULL; + break; + } + char *temp = (char *)malloc(tk->v.s.size + 1); + if (temp == NULL) + tc_oom(); + strncpy(temp, (const char *)tk->v.s.data, tk->v.s.size + 1); + temp[tk->v.s.size] = '\0'; + tc.opt.pager = temp; + } else { + tc_printf("---\n"); + tc_printf(" - Expected pager='command'\n"); + tc_printf("---\n"); + } + break; + default: + tc_printf("---\n"); + tc_printf(" - Unknown option to set\n"); + tc_printf("---\n"); + break; + } +} + +static enum tc_cliret +tc_cmdtry(char *cmd, size_t size, int *reconnect) +{ + enum tc_cliret rc = TC_CLI_OK; + struct tblex lex; + if (tb_lexinit(&lex, tc_keywords, cmd, size) == -1) + return TC_CLI_ERROR; + struct tbtoken *tk; + switch (tb_lex(&lex, &tk)) { + case TC_EXIT: + rc = TC_CLI_EXIT; + break; + case TC_HELP: + tc_cmdusage(); + cmd = "help()"; + break; + case TC_SETOPT: + tc_setopt(&lex); + goto done; +#if 0 + case TC_LOADFILE: + if (tnt_lex(&lex, &tk) != TNT_TK_STRING) { + rc = TC_CLI_ERROR; + goto done; + } + if (tc_cmd_loadfile((char*)TNT_TK_S(tk)->data, reconnect) == -1) + rc = TC_CLI_ERROR; + goto done; +#endif + } + *reconnect = tc_cliquery(cmd, rc == TC_CLI_EXIT); + if (*reconnect) + rc = TC_CLI_ERROR; +done: + tb_lexfree(&lex); + return rc; +} + +static enum tc_cliret +tc_clicmd(char *cmd, size_t size) +{ + int reconnect = 0; + do { + if (reconnect) { + reconnect = tc_clireconnect(); + if (reconnect) + return TC_CLI_ERROR; + } + enum tc_cliret rc = tc_cmdtry(cmd, size, &reconnect); + if (reconnect) + continue; + if (rc == TC_CLI_EXIT || rc == TC_CLI_ERROR) + return rc; + } while (reconnect); + + return TC_CLI_OK; +} + +int tc_clicmdv(void) +{ + int i, rc = 0; + for (i = 0 ; i < tc.opt.cmdc ; i++) { + char *cmd = tc.opt.cmdv[i]; + int len = strlen(tc.opt.cmdv[i]); + enum tc_cliret ret = tc_clicmd(cmd, len); + if (ret == TC_CLI_EXIT) + break; + if (ret == TC_CLI_ERROR) { + rc = 1; + break; + } + } + return rc; +} + +static void +tc_cliinit(void) +{ + /* ignore SIGPIPE for reconnection handling */ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + if (sigaction(SIGPIPE, &sa, NULL) == -1) + tc_error("signal initialization failed\n"); +} + +static char* +tc_clipipe(void) +{ + int size = 8192, pos = 0; + const size_t wcsize = sizeof(wchar_t); + char *str = malloc(size); + if (str == NULL) + tc_oom(); + wchar_t c; + while ((c = getwchar())) { + if (size < (pos + wcsize)) { + size *= 2; + char *nd = (char *)realloc(str, size); + if (nd == NULL) + tc_oom(); + str = nd; + } + if (c == '\r' || c == '\n' || c == WEOF) { + char c_t = (c != WEOF ? getchar() : '\n'); + if (c_t != '\r' && c_t != '\n') + ungetc(c_t, stdin); + wctomb(str + pos++, 0); + break; + } else { + pos += wctomb(str + pos, c); + } + } + if (pos == 1 && c == WEOF) { + free(str); + return NULL; + } + return str; +} + +static int +tc_hasdelim(char* str, size_t len, size_t lensep) +{ + const char *sep = tc.opt.delim; + if (lensep == 0) + return 1; + if (len < lensep) + return 0; + size_t i; + for (i = len; lensep > 0; --lensep, --i) + if (str[i - 1] != sep[lensep - 1]) + return 0; + return 1; +} + +int tc_cli(void) +{ + /* initialize cli */ + tc_cliinit(); + + /* load history file */ + char *home = getenv("HOME"); + char history[1024]; + snprintf(history, sizeof(history), "%s/%s", home, + TC_DEFAULT_HISTORY_FILE); + read_history(history); + + /* set prompt */ + char prompt[128]; + int prompt_len = + snprintf(prompt, sizeof(prompt), "%s> ", tc.opt.host) - 2; + char prompt_delim[128]; + + /* interactive mode */ + char *part_cmd; + struct tc_buf cmd; + if (tc_buf_str(&cmd)) + tc_oom(); + + while (1) { + if (isatty(STDIN_FILENO)) { + snprintf(prompt_delim, sizeof(prompt_delim), + "%*s> ", prompt_len, "-"); + part_cmd = readline(!tc_buf_str_isempty(&cmd) ? + prompt_delim : prompt); + } else { + clearerr(stdin); + part_cmd = tc_clipipe(); + } + if (!part_cmd) + break; + if (tc_buf_str_append(&cmd, part_cmd, strlen(part_cmd))) + tc_oom(); + + int delim_exists = + tc_hasdelim(cmd.data, cmd.used - 1, + tc.opt.delim_len); + + if (tc_buf_str_append(&cmd, "\n", 1)) + tc_oom(); + free(part_cmd); + if (!delim_exists && !feof(stdin)) + continue; + tc_buf_str_delete(&cmd, 1); + if (isatty(STDIN_FILENO)) + add_history(cmd.data); + tc_buf_cmdfy(&cmd, tc.opt.delim_len); + if (delim_exists && tc_buf_str_isempty(&cmd)) + goto next; + + enum tc_cliret ret = tc_clicmd(cmd.data, cmd.used - 1); +next: + tc_buf_clear(&cmd); + if (ret == TC_CLI_EXIT || feof(stdin)) { + tc_buf_free(&cmd); + break; + } + } + + /* update history file */ + write_history(history); + clear_history(); + return 0; +} diff --git a/client/tarantool/tc_cli.h b/client/tarantool/cli.h similarity index 96% rename from client/tarantool/tc_cli.h rename to client/tarantool/cli.h index 9650457cb26fc7cfa0ac107ffd9ec25e91d12159..6120e0312597341b6a5644c56f79127600332d4e 100644 --- a/client/tarantool/tc_cli.h +++ b/client/tarantool/cli.h @@ -28,8 +28,7 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -int tc_cli_cmdv(void); int tc_cli(void); -int tc_cli_motd(void); +int tc_clicmdv(void); #endif /* TC_CLI_H_INCLUDED */ diff --git a/client/tarantool/main.c b/client/tarantool/main.c new file mode 100644 index 0000000000000000000000000000000000000000..75aa71f83f44c29dc02500f83ef3278e538f0108 --- /dev/null +++ b/client/tarantool/main.c @@ -0,0 +1,194 @@ + +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <lib/tarantool.h> +#include <locale.h> +#include <unistd.h> + +#include <client/tarantool/opt.h> +#include <client/tarantool/main.h> +#include <client/tarantool/pager.h> +#include <client/tarantool/cli.h> +#include <client/tarantool/print.h> +#include <client/tarantool/store.h> +#include <client/tarantool/query.h> +/*#include <client/tarantool/print_snap.h>*/ +/*#include <client/tarantool/print_xlog.h>*/ + +struct tarantool_client tc; + +static void +tc_init(void) +{ + memset(&tc, 0, sizeof(tc)); + setlocale(LC_ALL, ""); + if (tc.opt.pager) + free(tc.opt.pager); + if (tc.opt.delim) + free(tc.opt.delim); + tc.pager_fd = fileno(stdout); + tc.pager_pid = 0; + tb_sesinit(&tc.console); +} + +static void +tc_shutdown(void) +{ + tb_sesclose(&tc.console); + tc_pager_kill(); +} + +void tc_error(char *fmt, ...) +{ + char msg[256]; + va_list args; + tc_shutdown(); + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + tc_printf("error: %s\n", msg); + exit(1); +} + +static int +tc_motdof(char *r) +{ + if (strcmp(r, TC_ERRCMD) != 0) + tc_printf("%s", r); + return 0; +} + +static void +tc_motd(void) +{ + int rc = tc_query("motd()", tc_motdof); + if (rc == -1) + tc_error("%s\n", "failed to send console query"); +} + +static int +tc_primaryportof(char *r) +{ + if (strcmp(r, TC_ERRCMD) != 0) + return 0; + int port = 0; + sscanf(r, "---\n - %d\n...", &port); + return port; +} + +static int +tc_primaryport() +{ + int rc = tc_query("box.cfg.primary_port", tc_primaryportof); + if (rc == -1) + tc_error("%s\n", "failed to send console query"); + if (rc > 0) + return rc; + rc = tc_query("lua box.cfg.primary_port", tc_primaryportof); + if (rc == -1) + tc_error("%s\n", "failed to send console query"); + return rc; +} + +static void +tc_connect(void) +{ + tb_sesset(&tc.console, TB_HOST, tc.opt.host); + tb_sesset(&tc.console, TB_PORT, tc.opt.port_console); + tb_sesset(&tc.console, TB_SENDBUF, 0); + tb_sesset(&tc.console, TB_READBUF, 0); + + int rc = tb_sesconnect(&tc.console); + if (rc == -1) + tc_error("console connection failed"); + + if (tc.opt.port == 0) + tc.opt.port = tc_primaryport(); +} + +#if 0 +static void tc_validate(void) +{ + tc.opt.xlog_printer = tc_print_getxlogcb(tc.opt.format); + tc.opt.snap_printer = tc_print_getsnapcb(tc.opt.format); + if (tc.opt.xlog_printer == NULL) + tc_error("unsupported output xlog format '%s'", + tc.opt.format); + if (tc.opt.snap_printer == NULL) + tc_error("unsupported output snap format '%s'", + tc.opt.format); + if (tc.opt.format && strcmp(tc.opt.format, "raw") == 0) + tc.opt.raw = 1; +} +#endif + +int main(int argc, char *argv[], char *envp[]) +{ + tc_init(); + enum tc_opt_mode mode = + tc_opt_init(&tc.opt, argc, argv, envp); + + /*tc_validate();*/ + + int rc = 0; + switch (mode) { + case TC_OPT_USAGE: + tc_opt_usage(); + break; + case TC_OPT_VERSION: + tc_opt_version(); + break; + case TC_OPT_WAL_CAT: + rc = tc_store_cat(); + break; +#if 0 + case TC_OPT_RPL: + tc_connect(); + rc = tc_store_remote(); + break; + case TC_OPT_WAL_PLAY: + tc_connect(); + rc = tc_store_play(); + break; +#endif + case TC_OPT_CMD: + tc_connect(); + rc = tc_clicmdv(); + break; + case TC_OPT_INTERACTIVE: + tc_connect(); + tc_motd(); + rc = tc_cli(); + break; + } + + tc_shutdown(); + return rc; +} diff --git a/client/tarantool/tc.h b/client/tarantool/main.h similarity index 67% rename from client/tarantool/tc.h rename to client/tarantool/main.h index f001346125bcb8e3e57cc9639a8a71c32af92807..fd809f6d3611ae2d1e68506aabd30eb905db6ac4 100644 --- a/client/tarantool/tc.h +++ b/client/tarantool/main.h @@ -1,5 +1,5 @@ -#ifndef TC_H_INCLUDED -#define TC_H_INCLUDED +#ifndef TC_MAIN_H_INCLUDED +#define TC_MAIN_H_INCLUDED /* * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following @@ -29,14 +29,44 @@ * SUCH DAMAGE. */ -struct tc { +#define TC_VERSION_MAJOR "0" +#define TC_VERSION_MINOR "3" + +#define TC_DEFAULT_HOST "localhost" +#define TC_DEFAULT_PORT 33013 +#define TC_DEFAULT_ADMIN_PORT 33015 +#define TC_DEFAULT_HISTORY_FILE ".tarantool_history" + +struct tarantool_client { + struct tbses console; struct tc_opt opt; - struct tc_admin admin; - struct tnt_stream *net; int pager_fd; pid_t pager_pid; }; void tc_error(char *fmt, ...); +static inline void +tc_oom(void) { + tc_error("memory allocation failed"); +} + +static inline void* +tc_malloc(size_t size) { + void *p = malloc(size); + if (p == NULL) + tc_oom(); + return p; +} + +static inline char* +tc_strdup(char *sz) { + char *p = strdup(sz); + if (p == NULL) + tc_oom(); + return p; +} + +#define TC_ERRCMD "---\nunknown command. try typing help.\n...\n" + #endif /* TC_H_INCLUDED */ diff --git a/client/tarantool/tc_opt.c b/client/tarantool/opt.c similarity index 91% rename from client/tarantool/tc_opt.c rename to client/tarantool/opt.c index 544af0ccabedc74bb9ae315a5a305b7d7d64e3e9..9c54c7a844800d9d664b2eee250b91420eef333f 100644 --- a/client/tarantool/tc_opt.c +++ b/client/tarantool/opt.c @@ -26,17 +26,12 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> +#include <lib/tarantool.h> #include <third_party/gopt/gopt.h> -#include "client/tarantool/tc_opt.h" - - -#define TC_DEFAULT_HOST "localhost" +#include <client/tarantool/opt.h> +#include <client/tarantool/main.h> /* supported cli options */ static const void *tc_options_def = gopt_start( @@ -47,12 +42,13 @@ static const void *tc_options_def = gopt_start( gopt_longs("port"), " <port number>", "server port"), #endif gopt_option('a', GOPT_ARG, gopt_shorts('a'), - gopt_longs("admin-port"), " <port number>", "server admin port"), -#if 0 + gopt_longs("admin-port"), " <port number>", "server admin console port"), gopt_option('C', GOPT_ARG, gopt_shorts('C'), gopt_longs("cat"), " <file name>", "print xlog or snapshot file content"), +#if 0 gopt_option('P', GOPT_ARG, gopt_shorts('P'), gopt_longs("play"), " <file name>", "replay xlog file to the specified server"), +#endif gopt_option('S', GOPT_ARG, gopt_shorts('S'), gopt_longs("space"), " <space number>", "filter by space number"), gopt_option('F', GOPT_ARG, gopt_shorts('F'), @@ -61,6 +57,7 @@ static const void *tc_options_def = gopt_start( gopt_longs("to"), " <log serial number>", "stop on specified xlog lsn"), gopt_option('M', GOPT_ARG, gopt_shorts('M'), gopt_longs("format"), " <name>", "cat output format (tarantool, raw)"), +#if 0 gopt_option('H', 0, gopt_shorts('H'), gopt_longs("header"), NULL, "add file headers for the raw output"), gopt_option('R', GOPT_ARG, gopt_shorts('R'), @@ -68,12 +65,12 @@ static const void *tc_options_def = gopt_start( gopt_option('B', 0, gopt_shorts('B'), gopt_longs("bin"), NULL, "print STR in lua printer instead" " of NUM32 and NUM64, except arithmetic update arguments"), +#endif gopt_option('D', GOPT_ARG, gopt_shorts('D'), gopt_longs("delim"), " <delim>", "if you use --cat, then it will add delim to an end of every line of your " "Lua file, when used at CLI start of client, then it's replacement of " "setopt delim='<delim>' command"), -#endif gopt_option('?', 0, gopt_shorts('?'), gopt_longs("help"), NULL, "display this help and exit"), gopt_option('V', 0, gopt_shorts('V'), gopt_longs("version"), @@ -96,7 +93,8 @@ void tc_opt_version(void) exit(0); } -enum tc_opt_mode tc_opt_init(struct tc_opt *opt, int argc, char **argv, char **envp) +enum tc_opt_mode +tc_opt_init(struct tc_opt *opt, int argc, char **argv, char **envp) { /* usage */ void *tc_options = gopt_sort(&argc, (const char**)argv, tc_options_def); @@ -116,19 +114,16 @@ enum tc_opt_mode tc_opt_init(struct tc_opt *opt, int argc, char **argv, char **e if (opt->host == NULL) opt->host = TC_DEFAULT_HOST; -#if 0 /* server port */ const char *arg = NULL; - opt->port = 0; + opt->port = TC_DEFAULT_PORT; if (gopt_arg(tc_options, 'p', &arg)) opt->port = atoi(arg); -#endif - const char *arg = NULL; - /* server admin port */ - opt->port_admin = 0; + /* server admin console port */ + opt->port_console = TC_DEFAULT_ADMIN_PORT; if (gopt_arg(tc_options, 'a', &arg)) - opt->port_admin = atoi(arg); + opt->port_console = atoi(arg); #if 0 /* space */ @@ -169,13 +164,13 @@ enum tc_opt_mode tc_opt_init(struct tc_opt *opt, int argc, char **argv, char **e opt->str_instead_int = 1; #endif -#if 0 /* set delimiter on start */ - opt->delim = ""; + opt->delim = NULL; opt->delim_len = 0; - if (gopt_arg(tc_options, 'D', &opt->delim)) + if (gopt_arg(tc_options, 'D', (const char**)&opt->delim)) opt->delim_len = strlen(opt->delim); +#if 0 /* replica mode */ if (gopt_arg(tc_options, 'R', &arg)) { opt->mode = TC_OPT_RPL; @@ -206,7 +201,12 @@ enum tc_opt_mode tc_opt_init(struct tc_opt *opt, int argc, char **argv, char **e } else { opt->mode = TC_OPT_INTERACTIVE; } - opt->pager = getenv("PAGER"); + + char *pager = getenv("PAGER"); + if (pager) + opt->pager = tc_strdup(pager); + else + opt->pager = NULL; opt->envp = envp; done: gopt_free(tc_options); diff --git a/client/tarantool/tc_opt.h b/client/tarantool/opt.h similarity index 94% rename from client/tarantool/tc_opt.h rename to client/tarantool/opt.h index 311e0eb4280d3cddcc42ab69b3c396e97310cd01..dfa5a7d262a7c26d947b0ac1946ae7b9a04d8b3a 100644 --- a/client/tarantool/tc_opt.h +++ b/client/tarantool/opt.h @@ -29,15 +29,12 @@ * SUCH DAMAGE. */ -#define TC_VERSION_MAJOR "0" -#define TC_VERSION_MINOR "2" - enum tc_opt_mode { TC_OPT_USAGE, TC_OPT_VERSION, + TC_OPT_WAL_CAT, #if 0 TC_OPT_RPL, - TC_OPT_WAL_CAT, TC_OPT_WAL_PLAY, #endif TC_OPT_CMD, @@ -48,7 +45,7 @@ struct tc_opt { enum tc_opt_mode mode; const char *host; int port; - int port_admin; + int port_console; uint64_t lsn; uint64_t lsn_from; int lsn_from_set; @@ -66,9 +63,9 @@ struct tc_opt { char **cmdv; int cmdc; char **envp; - const char *delim; + char *delim; size_t delim_len; - const char *pager; + char *pager; }; void tc_opt_usage(void); diff --git a/client/tarantool/tc_admin.h b/client/tarantool/pager.c similarity index 51% rename from client/tarantool/tc_admin.h rename to client/tarantool/pager.c index 56e109a98d8684140fccf3c1baebb179a13bb6be..8babcca1d793aa50d5c8a5ccf61d768008e33b10 100644 --- a/client/tarantool/tc_admin.h +++ b/client/tarantool/pager.c @@ -1,5 +1,4 @@ -#ifndef TC_ADMIN_H_INCLUDED -#define TC_ADMIN_H_INCLUDED + /* * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following @@ -27,20 +26,62 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - */ +*/ + +#include <lib/tarantool.h> +#include <unistd.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "client/tarantool/opt.h" +#include "client/tarantool/main.h" +#include "client/tarantool/pager.h" -struct tc_admin { - const char *host; - int port; - int fd; -}; +extern struct tarantool_client tc; -int tc_admin_connect(struct tc_admin *a, const char *host, int port); -int tc_admin_reconnect(struct tc_admin *a); +void tc_pager_start() +{ + if (tc.pager_pid != 0) + tc_pager_kill(); + if (tc.opt.pager == NULL) { + tc.pager_fd = fileno(stdout); + return; + } + int pipefd[2]; + const char *const argv[] = {"/bin/sh", "-c", tc.opt.pager, NULL}; + if (pipe(pipefd) < 0) + tc_error("Failed to open pipe. Errno: %s", strerror(errno)); -void tc_admin_close(struct tc_admin *a); + pid_t pid = fork(); + if (pid < 0) { + tc_error("Failed to fork. Errno: %s", strerror(errno)); + } else if (pid == 0) { + close(pipefd[1]); + dup2(pipefd[0], STDIN_FILENO); + execve(argv[0], (char * const*)argv, (char * const*)tc.opt.envp); + tc_error("Can't start pager! Errno: %s", strerror(errno)); + } else { + close(pipefd[0]); + tc.pager_fd = pipefd[1]; + tc.pager_pid = pid; + } +} -int tc_admin_query(struct tc_admin *a, char *q); -int tc_admin_reply(struct tc_admin *a, char **r, size_t *size); +void tc_pager_stop() +{ + if (tc.pager_pid != 0) { + close(tc.pager_fd); + tc.pager_fd = fileno(stdout); + waitpid(tc.pager_pid, NULL, 0); + tc.pager_pid = 0; + } +} -#endif /* TC_ADMIN_H_INCLUDED */ +void tc_pager_kill() +{ + if (tc.pager_pid != 0) { + kill(tc.pager_pid, SIGTERM); + tc_pager_stop(); + } +} diff --git a/client/tarantool/tc_pager.h b/client/tarantool/pager.h similarity index 99% rename from client/tarantool/tc_pager.h rename to client/tarantool/pager.h index eb7d0cda6b06c935962916d88c7d779d874f5da8..eaef6e16d7fac7f3f260f9bbe6171c7b99ee383a 100644 --- a/client/tarantool/tc_pager.h +++ b/client/tarantool/pager.h @@ -32,4 +32,5 @@ void tc_pager_start(); void tc_pager_stop(); void tc_pager_kill(); + #endif /* TC_PAGER_H_INCLUDED */ diff --git a/client/tarantool/tc_print.c b/client/tarantool/print.c similarity index 89% rename from client/tarantool/tc_print.c rename to client/tarantool/print.c index ed8985f92869129c7ea34ce7c2abfa253327fab7..e6ace8a2a9429b900fad0e5d7ff69534de03dbfb 100644 --- a/client/tarantool/tc_print.c +++ b/client/tarantool/print.c @@ -25,34 +25,21 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - */ -#include <stdlib.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <string.h> +*/ + +#include <lib/tarantool.h> #include <ctype.h> #include <wctype.h> - #include <unistd.h> #include <errno.h> -#if 0 -#include <connector/c/include/tarantool/tnt.h> -#include <connector/c/include/tarantool/tnt_xlog.h> -#include <connector/c/include/tarantool/tnt_rpl.h> -#endif - -#include "client/tarantool/tc_opt.h" -#include "client/tarantool/tc_admin.h" -#include "client/tarantool/tc.h" -#include "client/tarantool/tc_print.h" -#include "client/tarantool/tc_query.h" +#include <client/tarantool/opt.h> +#include <client/tarantool/main.h> +#include <client/tarantool/print.h> +#include <client/tarantool/query.h> -extern struct tc tc; +extern struct tarantool_client tc; -/*##################### Base printing functions #####################*/ void tc_print_buf(char *buf, size_t size) { printf("%-.*s", (int)size, buf); fflush(stdout); diff --git a/client/tarantool/tc_print.h b/client/tarantool/print.h similarity index 100% rename from client/tarantool/tc_print.h rename to client/tarantool/print.h diff --git a/client/tarantool/tc_print_snap.c b/client/tarantool/print_snap.c similarity index 100% rename from client/tarantool/tc_print_snap.c rename to client/tarantool/print_snap.c diff --git a/client/tarantool/tc_print_snap.h b/client/tarantool/print_snap.h similarity index 100% rename from client/tarantool/tc_print_snap.h rename to client/tarantool/print_snap.h diff --git a/client/tarantool/tc_print_xlog.c b/client/tarantool/print_xlog.c similarity index 100% rename from client/tarantool/tc_print_xlog.c rename to client/tarantool/print_xlog.c diff --git a/client/tarantool/tc_print_xlog.h b/client/tarantool/print_xlog.h similarity index 100% rename from client/tarantool/tc_print_xlog.h rename to client/tarantool/print_xlog.h diff --git a/client/tarantool/tc_query.c b/client/tarantool/query.c similarity index 74% rename from client/tarantool/tc_query.c rename to client/tarantool/query.c index 28be5afde31cb3a7ae4abdcd4a687c42e2c86f6f..3cdb9dda1d1e5d185aca47ee3bce35c220b1f854 100644 --- a/client/tarantool/tc_query.c +++ b/client/tarantool/query.c @@ -1,3 +1,4 @@ + /* * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following @@ -25,31 +26,44 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - */ -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <stdint.h> +*/ + +#include <lib/tarantool.h> #include "errcode.h" +#include <client/tarantool/opt.h> +#include <client/tarantool/main.h> +#include <client/tarantool/print.h> +#include <client/tarantool/query.h> -#if 0 -#include <connector/c/include/tarantool/tnt.h> -#include <connector/c/include/tarantool/tnt_net.h> -#include <connector/c/include/tarantool/tnt_sql.h> -#include <connector/c/include/tarantool/tnt_xlog.h> -#include <connector/c/include/tarantool/tnt_rpl.h> -#endif +extern struct tarantool_client tc; -#include "client/tarantool/tc_opt.h" -#include "client/tarantool/tc_admin.h" -#include "client/tarantool/tc.h" -#include "client/tarantool/tc_print.h" -#include "client/tarantool/tc_query.h" +int tc_printer(char *reply, size_t size, void *ctx) +{ + (void)ctx; + (void)size; + tc_printf("%s", reply); + return 0; +} -extern struct tc tc; +int tc_exec(char *q, tc_query_t cb, void *ctx) +{ + int rc = tb_conwrite(&tc.console, q, strlen(q)); + if (rc == -1) + return -1; + size_t size; + char *reply; + rc = tb_conread(&tc.console, &reply, &size); + if (rc == -1) + return -1; + rc = 0; + if (cb && reply) + rc = cb(reply, size, ctx); + free(reply); + return rc; +} +#if 0 char *tc_query_error(char *fmt, ...) { char msg[256]; va_list args; @@ -62,7 +76,6 @@ char *tc_query_error(char *fmt, ...) { return ptr; } -#if 0 char *tc_query_type(uint32_t type) { switch (type) { case TNT_OP_PING: return "Ping"; @@ -134,32 +147,3 @@ int tc_query(char *q, char **e) { } #endif -int tc_query_admin_printer(char *r, char **e) { - (void)e; - tc_printf("%s", r); - return 0; -} - -int tc_query_admin(char *q, tc_query_admin_t cb, char **e) -{ - if (tc_admin_query(&tc.admin, q) == -1) { - *e = tc_query_error("failed to send admin query"); - return -1; - } - if (cb == NULL) - return 0; - char *reply = NULL; - size_t reply_size = 0; - if (tc_admin_reply(&tc.admin, &reply, &reply_size) == -1) { - *e = tc_query_error("failed to recv admin reply"); - return -1; - } - if (cb && reply) { - if (cb(reply, e) == -1) { - free(reply); - return -1; - } - } - free(reply); - return 0; -} diff --git a/client/tarantool/tc_query.h b/client/tarantool/query.h similarity index 87% rename from client/tarantool/tc_query.h rename to client/tarantool/query.h index 36dc74ac7a57a0b0d02a85e892772a169a0d60f5..3b4046db4675cf3cbb633cda6f68a2de74498b86 100644 --- a/client/tarantool/tc_query.h +++ b/client/tarantool/query.h @@ -29,7 +29,15 @@ * SUCH DAMAGE. */ -typedef int (*tc_query_admin_t)(char *r, char **e); +typedef int (*tc_query_t)(char *reply, size_t size, void *ctx); + +int tc_printer(char *r, size_t size, void *ctx); +int tc_exec(char *q, tc_query_t cb, void *ctx); + +static inline int +tc_query(char *q, void *cb) { + return tc_exec(q, (tc_query_t)cb, NULL); +} #if 0 typedef int (*tc_query_t)(struct tnt_reply *r, void *ptr, char **e); @@ -39,14 +47,11 @@ char *tc_query_type(uint32_t type); int tc_query_printer(struct tnt_reply *r, void *ptr, char **e); int tc_query_foreach(tc_query_t cb, void *cba, char **e); int tc_query(char *q, char **e); -#endif - -int tc_query_admin_printer(char *r, char **e); -int tc_query_admin(char *q, tc_query_admin_t cb, char **e); struct tnt_reply; char *tc_query_error(char *fmt, ...); char *tc_query_op(struct tnt_reply *r); +#endif #endif /* TC_QUERY_H_INCLUDED */ diff --git a/client/tarantool/tc_store.c b/client/tarantool/store.c similarity index 55% rename from client/tarantool/tc_store.c rename to client/tarantool/store.c index 17228fe2c7245a6af7d2d74ddbc4643817225946..976621d4a3449be7503d6d1261f1099969e2aaa4 100644 --- a/client/tarantool/tc_store.c +++ b/client/tarantool/store.c @@ -26,32 +26,18 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <inttypes.h> -#include <limits.h> -#include <stdint.h> -#include <connector/c/include/tarantool/tnt.h> -#include <connector/c/include/tarantool/tnt_net.h> -#include <connector/c/include/tarantool/tnt_sql.h> -#include <connector/c/include/tarantool/tnt_xlog.h> -#include <connector/c/include/tarantool/tnt_snapshot.h> -#include <connector/c/include/tarantool/tnt_rpl.h> +#include <lib/tarantool.h> -#include "client/tarantool/tc_opt.h" -#include "client/tarantool/tc_admin.h" -#include "client/tarantool/tc.h" -#include "client/tarantool/tc_print.h" -#include "client/tarantool/tc_print_xlog.h" -#include "client/tarantool/tc_print_snap.h" -#include "client/tarantool/tc_query.h" -#include "client/tarantool/tc_store.h" +#include <client/tarantool/opt.h> +#include <client/tarantool/main.h> +#include <client/tarantool/print.h> +#include <client/tarantool/query.h> +#include <client/tarantool/store.h> -extern struct tc tc; +struct tarantool_client tc; -typedef int (*tc_iter_t)(struct tnt_iter *i); +typedef int (*tc_iter_t)(struct tbfile *f); static int tc_store_error(char *fmt, ...) { char msg[256]; @@ -63,126 +49,64 @@ static int tc_store_error(char *fmt, ...) { return -1; } -static int tc_store_foreach(struct tnt_iter *i, tc_iter_t cb) { - while (tnt_next(i)) { - if (cb(i) == -1) { - tnt_iter_free(i); +static int tc_store_foreach(struct tbfile *f, tc_iter_t cb) +{ + int rc; + while ((rc = tb_filenext(f)) > 0) { + if (cb(f) == -1) return -1; - } } - int rc = 0; - if (i->status == TNT_ITER_FAIL) - rc = tc_store_error("parsing failed"); + if (rc < 0) + tc_store_error("parsing error: %s", tb_fileerror(f, rc)); return rc; } -static void tc_store_print(struct tnt_log_header_v11 *hdr, - struct tnt_request *r) +static int +tc_store_foreach_xlog(tc_iter_t cb) { - tc_printf("%s lsn: %"PRIu64", time: %f, len: %"PRIu32"\n", - tc_query_type(r->h.type), - hdr->lsn, - hdr->tm, - hdr->len); - switch (r->h.type) { - case TNT_OP_INSERT: - tc_print_tuple(&r->r.insert.t); - break; - case TNT_OP_DELETE: - tc_print_tuple(&r->r.del.t); - break; - case TNT_OP_DELETE_1_3: - tc_print_tuple(&r->r.del_1_3.t); - break; - case TNT_OP_UPDATE: - tc_print_tuple(&r->r.update.t); - break; - case TNT_OP_CALL: - tc_print_tuple(&r->r.call.t); - break; - } + struct tbfile f; + int rc = tb_fileopen(&f, (char*)tc.opt.file); + if (rc < 0) + return 1; + rc = tc_store_foreach(&f, cb); + tb_fileclose(&f); + return rc; } -static int tc_store_check_skip(struct tnt_iter *i, struct tnt_request *r) { - struct tnt_stream_xlog *s = - TNT_SXLOG_CAST(TNT_IREQUEST_STREAM(i)); +static int +tc_store_check_skip(struct tbfile *f) +{ +#if 0 if (tc.opt.space_set) { - if (r->h.type == TNT_OP_CALL) + if (f->h.type == TNT_OP_CALL) return 1; uint32_t ns = *(uint32_t*)&r->r; if (ns != tc.opt.space) return 1; } +#endif if (tc.opt.lsn_from_set) { - if (s->log.current.hdr.lsn < tc.opt.lsn_from) + if (f->h.lsn < tc.opt.lsn_from) return 1; } if (tc.opt.lsn_to_set) { - if (s->log.current.hdr.lsn > tc.opt.lsn_to) + if (f->h.lsn > tc.opt.lsn_to) return 1; } return 0; } -static int tc_store_xlog_printer(struct tnt_iter *i) { - struct tnt_request *r = TNT_IREQUEST_PTR(i); - if (tc_store_check_skip(i, r)) +static int tc_store_xlog_printer(struct tbfile *f) +{ + if (tc_store_check_skip(f)) return 0; - struct tnt_stream_xlog *s = - TNT_SXLOG_CAST(TNT_IREQUEST_STREAM(i)); - ((tc_printerf_xlog_t)tc.opt.xlog_printer)(&s->log.current, r); + /*((tc_printerf_xlog_t)tc.opt.xlog_printer)(&s->log.current, r);*/ return 0; } -static int tc_store_snap_printer(struct tnt_iter *i) { - struct tnt_tuple *tu = TNT_ISTORAGE_TUPLE(i); - struct tnt_stream_snapshot *ss = - TNT_SSNAPSHOT_CAST(TNT_ISTORAGE_STREAM(i)); - if (tc.opt.space_set) { - if (ss->log.current.row_snap.space != tc.opt.space) - return 0; - } - ((tc_printerf_snap_t)tc.opt.snap_printer)(&ss->log.current, tu); - return 0; -} - -static int tc_store_foreach_request(struct tnt_stream *s, tc_iter_t cb) { - struct tnt_iter i; - tnt_iter_request(&i, s); - int rc = tc_store_foreach(&i, cb); - tnt_iter_free(&i); - return rc; -} - -static int tc_store_foreach_xlog(tc_iter_t cb) { - struct tnt_stream s; - tnt_xlog(&s); - if (tnt_xlog_open(&s, (char*)tc.opt.file) == -1) { - tnt_stream_free(&s); - return 1; - } - int rc = tc_store_foreach_request(&s, cb); - tnt_stream_free(&s); - return rc; -} - -static int tc_store_foreach_snap(tc_iter_t cb) { - struct tnt_stream s; - tnt_snapshot(&s); - if (tnt_snapshot_open(&s, (char*)tc.opt.file) == -1) { - tnt_stream_free(&s); - return 1; - } - struct tnt_iter i; - tnt_iter_storage(&i, &s); - int rc = tc_store_foreach(&i, cb); - tnt_iter_free(&i); - tnt_stream_free(&s); - return rc; -} - int tc_store_cat(void) { +#if 0 enum tnt_log_type type = tnt_log_guess((char*)tc.opt.file); if (type == TNT_LOG_NONE) return 1; @@ -194,27 +118,20 @@ int tc_store_cat(void) fputs(TNT_LOG_VERSION, stdout); fputs("\n", stdout); } - int rc; +#endif - switch (type) { - case TNT_LOG_SNAPSHOT: - rc = tc_store_foreach_snap(tc_store_snap_printer); - break; - case TNT_LOG_XLOG: - rc = tc_store_foreach_xlog(tc_store_xlog_printer); - break; - case TNT_LOG_NONE: - rc = 1; - break; - default: - return -1; - } + int rc = tc_store_foreach_xlog(tc_store_xlog_printer); + +#if 0 if (rc == 0 && print_headers) { fwrite(&tnt_log_marker_eof_v11, sizeof(tnt_log_marker_eof_v11), 1, stdout); - } +#endif + return rc; } + +#if 0 static int tc_store_snap_resender(struct tnt_iter *i) { struct tnt_tuple *tu = TNT_ISTORAGE_TUPLE(i); @@ -304,3 +221,4 @@ int tc_store_remote(void) tnt_stream_free(&s); return rc; } +#endif diff --git a/client/tarantool/tc_store.h b/client/tarantool/store.h similarity index 100% rename from client/tarantool/tc_store.h rename to client/tarantool/store.h diff --git a/client/tarantool/tc.c b/client/tarantool/tc.c deleted file mode 100644 index 5a232aa4cbcd93c1b35780076b0b77b2558478a4..0000000000000000000000000000000000000000 --- a/client/tarantool/tc.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <stdint.h> -#include <locale.h> - -#include <unistd.h> - -#if 0 -#include <connector/c/include/tarantool/tnt.h> -#include <connector/c/include/tarantool/tnt_net.h> -#include <connector/c/include/tarantool/tnt_sql.h> -#include <connector/c/include/tarantool/tnt_iter.h> -#include <connector/c/include/tarantool/tnt_xlog.h> -#endif - -#include "client/tarantool/tc_opt.h" -#include "client/tarantool/tc_admin.h" -#include "client/tarantool/tc.h" -#include "client/tarantool/tc_pager.h" -#include "client/tarantool/tc_cli.h" -#include "client/tarantool/tc_print.h" -/*#include "client/tarantool/tc_store.h"*/ -#include "client/tarantool/tc_query.h" -/*#include "client/tarantool/tc_print_snap.h"*/ -/*#include "client/tarantool/tc_print_xlog.h"*/ - -#define TC_DEFAULT_PORT 33013 -#define TC_DEFAULT_PORT 33013 -#define TC_ERR_CMD "---\nunknown command. try typing help.\n...\n" - -struct tc tc; - -static void tc_init(void) { - memset(&tc, 0, sizeof(tc)); - setlocale(LC_ALL, ""); - tc.pager_fd = fileno(stdout); - tc.pager_pid = 0; -} - -static void tc_free(void) { - /* - if (tc.net) { - tnt_stream_free(tc.net); - } - */ - tc_admin_close(&tc.admin); - /* - tc_cmd_tee_close(); - */ - tc_pager_kill(); -} - -void tc_error(char *fmt, ...) { - char msg[256]; - va_list args; - tc_free(); - /* - - - - */ - va_start(args, fmt); - vsnprintf(msg, sizeof(msg), fmt, args); - va_end(args); - tc_printf("error: %s\n", msg); - exit(1); -} - -#if 0 -static int get_admin_port(void) -{ - char *e = NULL; - tc_query("call box.dostring('return box.cfg.admin_port')", &e); - struct tnt_iter i, it, ifl; - tnt_iter_reply(&i, tc.net); - struct tnt_reply *r = TNT_IREPLY_PTR(&i); - if (!tnt_next(&i)) { - tnt_iter_free(&i); - } - if (tnt_error(tc.net) != TNT_EOK) { - tc_error(tc_query_error("%s ERROR, %s", - tc_query_op(r), - tnt_strerror(tc.net))); - } else if (r->code != 0) { - tc_error(tc_query_error("%s ERROR, %s (%s)", - tc_query_op(r), ((r->error) ? r->error : ""), - tnt_strerror(tc.net))); - } - tnt_iter_list(&it, TNT_REPLY_LIST(r)); - if (!tnt_next(&it)) { - tnt_iter_free(&it); - tnt_iter_free(&i); - } - struct tnt_tuple *tu = TNT_ILIST_TUPLE(&it); - tnt_iter(&ifl, tu); - if (!tnt_next(&ifl)) { - tc_error("Can't get admin port from primary port"); - } - int port = *((uint32_t* )TNT_IFIELD_DATA(&ifl)); - tnt_iter_free(&ifl); - tnt_iter_free(&it); - tnt_iter_free(&i); - if (e != NULL) - free(e); - return port; -} - -static void tc_connect(void) -{ - if (tc.opt.port == 0) - tc.opt.port = TC_DEFAULT_PORT; - /* allocating stream */ - tc.net = tnt_net(NULL); - if (tc.net == NULL) - tc_error("stream allocation error"); - /* initializing network stream */ - tnt_set(tc.net, TNT_OPT_HOSTNAME, tc.opt.host); - tnt_set(tc.net, TNT_OPT_PORT, tc.opt.port); - tnt_set(tc.net, TNT_OPT_SEND_BUF, 0); - tnt_set(tc.net, TNT_OPT_RECV_BUF, 0); - if (tnt_init(tc.net) == -1) - tc_error("%s", tnt_strerror(tc.net)); - /* connecting to server */ - if (tnt_connect(tc.net) == -1) - tc_error("%s", tnt_strerror(tc.net)); - if (tc.opt.port_admin == 0) - tc.opt.port_admin = get_admin_port(); -} -#endif - -#if 0 -static char *send_cmd(char *cmd) -{ - size_t size = 0; - char *reply = NULL; - if (tc_admin_query(&tc.admin, cmd) == -1) - tc_error("cannot send query"); - if (tc_admin_reply(&tc.admin, &reply, &size) == -1) - tc_error("cannot recv query"); - if (strncmp(reply, TC_ERR_CMD, size) == 0) { - free(reply); - return NULL; - } - return reply; -} - -static int get_primary_port() -{ - int port = 0; - char *reply = send_cmd("box.cfg.primary_port"); - if (reply == NULL) - reply = send_cmd("lua box.cfg.primary_port"); - if (reply != NULL) { - sscanf(reply, "---\n - %d\n...", &port); - free(reply); - } - return port; -} -#endif - -static void tc_connect_admin(void) -{ - tc.opt.port_admin = 33015; - if (tc_admin_connect(&tc.admin, - tc.opt.host, - tc.opt.port_admin) == -1) - tc_error("admin console connection failed"); -#if 0 - if (tc.opt.port == 0) - tc.opt.port = get_primary_port(); -#endif -} - -#if 0 -static void tc_connect_both(void) -{ - if (!tc.opt.port && tc.opt.port_admin) { - tc_connect_admin(); - tc_connect(); - } else { - tc_connect(); - tc_connect_admin(); - } -} - -static void tc_validate(void) -{ - tc.opt.xlog_printer = tc_print_getxlogcb(tc.opt.format); - tc.opt.snap_printer = tc_print_getsnapcb(tc.opt.format); - if (tc.opt.xlog_printer == NULL) - tc_error("unsupported output xlog format '%s'", - tc.opt.format); - if (tc.opt.snap_printer == NULL) - tc_error("unsupported output snap format '%s'", - tc.opt.format); - if (tc.opt.format && strcmp(tc.opt.format, "raw") == 0) - tc.opt.raw = 1; -} -#endif - -int main(int argc, char *argv[], char *envp[]) -{ - tc_init(); - - int rc = 0; - enum tc_opt_mode mode = tc_opt_init(&tc.opt, argc, argv, envp); - /*tc_validate();*/ - switch (mode) { - case TC_OPT_USAGE: - tc_opt_usage(); - break; - case TC_OPT_VERSION: - tc_opt_version(); - break; -#if 0 - case TC_OPT_RPL: - tc_connect(); - rc = tc_store_remote(); - break; - case TC_OPT_WAL_CAT: - rc = tc_store_cat(); - break; - case TC_OPT_WAL_PLAY: - tc_connect(); - rc = tc_store_play(); - break; -#endif - case TC_OPT_CMD: - tc_connect_admin(); - rc = tc_cli_cmdv(); - break; - case TC_OPT_INTERACTIVE: - tc_connect_admin(); - tc_cli_motd(); - rc = tc_cli(); - break; - } - - tc_free(); - return rc; -} diff --git a/client/tarantool/tc_admin.c b/client/tarantool/tc_admin.c deleted file mode 100644 index 8d57564e3ab7fc840a3ab7f76f21cc04b4863394..0000000000000000000000000000000000000000 --- a/client/tarantool/tc_admin.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <sys/uio.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <limits.h> - -#include "client/tarantool/tc_admin.h" - -int tc_admin_connect(struct tc_admin *a, const char *host, int port) -{ - a->host = host; - a->port = port; - a->fd = socket(AF_INET, SOCK_STREAM, 0); - if (a->fd < 0) - return -1; - int opt = 1; - if (setsockopt(a->fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1) - goto error; - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(a->port); - struct hostent *he = gethostbyname(a->host); - if (he) - memcpy(&addr.sin_addr, (void*)(he->h_addr), he->h_length); - else - goto error; - if (connect(a->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) - goto error; - return 0; -error: - close(a->fd); - return -1; -} - -int tc_admin_reconnect(struct tc_admin *a) -{ - tc_admin_close(a); - return tc_admin_connect(a, a->host, a->port); -} - -void tc_admin_close(struct tc_admin *a) -{ - if (a->fd > 0) - close(a->fd); - a->fd = 0; -} - -int tc_admin_query(struct tc_admin *a, char *q) -{ - size_t total = 0; - int count = 2; - struct iovec v[2]; - struct iovec *vp = v; - v[0].iov_base = q; - v[0].iov_len = strlen(q); - v[1].iov_base = "\n"; - v[1].iov_len = 1; - while (count > 0) - { - ssize_t r; - do { - r = writev(a->fd, vp, count); - } while (r == -1 && (errno == EINTR)); - if (r <= 0) - return -1; - total += r; - while (count > 0) { - if (vp->iov_len > (size_t)r) { - vp->iov_base += r; - vp->iov_len -= r; - break; - } else { - r -= vp->iov_len; - vp++; - count--; - } - } - } - return 0; -} - -int tc_admin_reply(struct tc_admin *a, char **r, size_t *size) -{ - char *buf = NULL; - size_t off = 0; - while (1) { - char rx[8096]; - ssize_t rxi = recv(a->fd, rx, sizeof(rx), 0); - if (rxi <= 0) - break; - char *bufn = (char *)realloc(buf, off + rxi + 1); - if (bufn == NULL) { - free(buf); - break; - } - buf = bufn; - memcpy(buf + off, rx, rxi); - off += rxi; - buf[off] = 0; - - int is_complete = - (off >= 6 && !memcmp(buf, "---", 3)) && - ((!memcmp(buf + off - 3, "...", 3)) || - (off >= 7 && !memcmp(buf + off - 4, "...\n", 4)) || - (off >= 7 && !memcmp(buf + off - 4, "...\r", 4)) || - (off >= 8 && !memcmp(buf + off - 5, "...\r\n", 5)) || - (off >= 8 && !memcmp(buf + off - 5, "...\n\n", 5))); - - if (is_complete) { - *r = buf; - *size = off; - return 0; - } - } - if (buf) - free(buf); - return -1; -} diff --git a/client/tarantool/tc_cli.c b/client/tarantool/tc_cli.c deleted file mode 100644 index 54f220fcdc500a828e830ee7ea3b24c72400e6dc..0000000000000000000000000000000000000000 --- a/client/tarantool/tc_cli.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include <stdlib.h> -#include <stdio.h> -#include <stdbool.h> -#include <stdarg.h> -#include <string.h> -#include <stdint.h> -#include <ctype.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <errno.h> -#include <wchar.h> - -#include <readline/readline.h> -#include <readline/history.h> - -#if 0 -#include <connector/c/include/tarantool/tnt.h> -#include <connector/c/include/tarantool/tnt_net.h> -#include <connector/c/include/tarantool/tnt_queue.h> -#include <connector/c/include/tarantool/tnt_utf8.h> -#include <connector/c/include/tarantool/tnt_lex.h> -#include <connector/c/include/tarantool/tnt_sql.h> -#include <connector/c/include/tarantool/tnt_xlog.h> -#include <connector/c/include/tarantool/tnt_rpl.h> -#endif - -#include "client/tarantool/tc_opt.h" -#include "client/tarantool/tc_admin.h" -#include "client/tarantool/tc.h" -#include "client/tarantool/tc_pager.h" -#include "client/tarantool/tc_query.h" -#include "client/tarantool/tc_cli.h" -#include "client/tarantool/tc_print.h" -#include "client/tarantool/tc_buf.h" - -#define TC_DEFAULT_HISTORY_FILE ".tarantool_history" - -#define TC_ALLOCATION_ERROR "error: memory allocation failed for %zu bytes\n" -#define TC_REALLOCATION_ERROR "error: memory reallocation failed for %zu bytes\n" - -extern struct tc tc; - -static inline int tc_cli_error(char *e) { - if (e) { - tc_printf("%s\n", e); - free(e); - } - return 1; -} - -static int tc_cli_reconnect(void) { -#if 0 - if (tnt_connect(tc.net) == -1) { - tc_printf("reconnect: %s\n", tnt_strerror(tc.net)); - return 1; - } -#endif - if (tc_admin_reconnect(&tc.admin) == -1) { - tc_printf("reconnect: admin console connection failed\n"); - return 1; - } - tc_printf("reconnected\n"); - return 0; -} - -#if 0 -enum tc_keywords { - TC_EXIT = TNT_TK_CUSTOM + 1, - TC_LOADFILE, - TC_HELP, - TC_SETOPT, - TC_SETOPT_DELIM, - TC_SETOPT_PAGER -}; - -static struct tnt_lex_keyword tc_lex_keywords[] = -{ - { "e", 1, TC_EXIT }, - { "ex", 2, TC_EXIT }, - { "exi", 3, TC_EXIT }, - { "exit", 4, TC_EXIT }, - { "q", 1, TC_EXIT }, - { "qu", 2, TC_EXIT }, - { "qui", 3, TC_EXIT }, - { "quit", 4, TC_EXIT }, - { "help", 4, TC_HELP }, - { "loadfile", 8, TC_LOADFILE }, - { "setopt", 6, TC_SETOPT }, - { "delimiter", 9, TC_SETOPT_DELIM }, - { "pager", 5, TC_SETOPT_PAGER }, - { NULL, 0, TNT_TK_NONE } -}; -#endif - -enum tc_cli_cmd_ret { - TC_CLI_OK, - TC_CLI_ERROR, - TC_CLI_EXIT -}; - -#if 0 -static void -tc_cmd_usage(void) -{ - char usage[] = - "---\n" - "console client commands:\n" - " - help\n" - " - loadfile 'path'\n" - " - setopt key=val\n" - " - (possible pairs: delimiter = \'string\' )\n" - " - ( pager = \'command\' )\n" - "...\n"; - tc_printf("%s", usage); -} -#endif - -static int tc_cli_admin(char *cmd, int exit) { - char *e = NULL; - tc_query_admin_t cb = (exit) ? NULL : tc_query_admin_printer; - if (!exit) tc_pager_start(); - if (tc_query_admin(cmd, cb, &e) == -1) - return tc_cli_error(e); - return 0; -} - -#if 0 -static int -tc_cmd_dostring(char *buf, size_t size, int *reconnect) -{ - struct tnt_tuple args; - tnt_tuple_init(&args); - tnt_tuple_add(&args, buf, size); - int rc = tnt_call(tc.net, 0, "box.dostring", &args); - if (rc < 0) - goto error; - rc = tnt_flush(tc.net); - if (rc < 0) - goto error; - tnt_tuple_free(&args); - char *e = NULL; - tc_pager_start(); - if (tc_query_foreach(tc_query_printer, NULL, &e) == -1) { - *reconnect = tc_cli_error(e); - return -1; - } - tc_pager_stop(); - return 0; -error: - tc_printf("error: %s\n", tnt_strerror(tc.net)); - tnt_tuple_free(&args); - return -1; -} - -static int -tc_cmd_loadfile(char *path, int *reconnect) -{ - struct stat st; - if (stat(path, &st) == -1) { - tc_printf("error: stat(): %s\n", strerror(errno)); - return -1; - } - int fd = open(path, O_RDONLY); - if (fd == -1) - return -1; - char *buf = (char *)malloc(st.st_size); - if (buf == NULL) { - tc_printf(TC_ALLOCATION_ERROR, - st.st_size); - return -1; - } - size_t off = 0; - do { - ssize_t r = read(fd, buf + off, st.st_size - off); - if (r == -1) { - close(fd); - free(buf); - tc_printf("error: read(): %s\n", strerror(errno)); - return -1; - } - off += r; - } while (off != st.st_size); - close(fd); - - int rc = tc_cmd_dostring(buf, st.st_size, reconnect); - free(buf); - return rc; -} -#endif - -#if 0 -static void replace_newline(char *cmd) { - int len = strlen(cmd); - int offset = 0; - for (int i = 0; i < len - 1; ++i) - if (cmd[i] == '\\' && cmd[i + 1] == 'n') - cmd[i++ - offset++] = '\n'; - else if (offset != 0) - cmd[i - offset] = cmd[i]; - cmd[len - offset] = '\0'; -} -#endif - -static enum tc_cli_cmd_ret -tc_cmd_try(char *cmd, size_t size, int *reconnect) -{ - (void)size; - enum tc_cli_cmd_ret rc = TC_CLI_OK; - if (! strcmp(cmd, "help")) - cmd = "help()"; -#if 0 - struct tnt_lex lex; - if (!tnt_lex_init(&lex, tc_lex_keywords, (unsigned char*)cmd, size)) - return TC_CLI_ERROR; - struct tnt_tk *tk; - switch (tnt_lex(&lex, &tk)) { - case TC_EXIT: - rc = TC_CLI_EXIT; - break; - case TC_HELP: - tc_cmd_usage(); - cmd = "help()"; - break; - case TC_LOADFILE: - if (tnt_lex(&lex, &tk) != TNT_TK_STRING) { - rc = TC_CLI_ERROR; - goto done; - } - if (tc_cmd_loadfile((char*)TNT_TK_S(tk)->data, reconnect) == -1) - rc = TC_CLI_ERROR; - goto done; - case TC_SETOPT: - switch (tnt_lex(&lex, &tk)) { - case TC_SETOPT_DELIM: - if (tnt_lex(&lex, &tk) != '=') { - tnt_lex_push(&lex, tk); - } - if (tnt_lex(&lex, &tk) == TNT_TK_STRING) { - if (!TNT_TK_S(tk)->size) { - tc.opt.delim = ""; - tc.opt.delim_len = 0; - goto done; - } - char * temp = (char *)malloc(TNT_TK_S(tk)->size + 1); - if (temp == NULL) - tc_error(TC_ALLOCATION_ERROR, - TNT_TK_S(tk)->size + 1); - strncpy(temp, - (const char *)TNT_TK_S(tk)->data, - TNT_TK_S(tk)->size + 1); - replace_newline(temp); - tc.opt.delim = temp; - tc.opt.delim_len = strlen(tc.opt.delim); - } else { - tc_printf("---\n"); - tc_printf(" - Expected delimiter='string'\n"); - tc_printf("---\n"); - } - break; - case TC_SETOPT_PAGER: - if (tnt_lex(&lex, &tk) == '=' && - tnt_lex(&lex, &tk) == TNT_TK_STRING) { - if (!TNT_TK_S(tk)->size) { - tc.opt.pager = NULL; - goto done; - } - char * temp = (char *)malloc(TNT_TK_S(tk)->size + 1); - if (temp == NULL) - tc_error(TC_ALLOCATION_ERROR, - TNT_TK_S(tk)->size + 1); - strncpy(temp, - (const char *)TNT_TK_S(tk)->data, - TNT_TK_S(tk)->size + 1); - temp[TNT_TK_S(tk)->size] = '\0'; - tc.opt.pager = temp; - } else { - tc_printf("---\n"); - tc_printf(" - Expected pager='command'\n"); - tc_printf("---\n"); - } - break; - default: - tc_printf("---\n"); - tc_printf(" - Unknown option to set\n"); - tc_printf("---\n"); - } - goto done; - } -#endif - *reconnect = tc_cli_admin(cmd, rc == TC_CLI_EXIT); - if (*reconnect) - return TC_CLI_ERROR; - /* -done: - tnt_lex_free(&lex); - */ - return rc; -} - -static enum tc_cli_cmd_ret tc_cli_cmd(char *cmd, size_t size) -{ - int reconnect = 0; - do { - if (reconnect) { - reconnect = tc_cli_reconnect(); - if (reconnect) - return TC_CLI_ERROR; - } -#if 0 - char *e = NULL; - if (tnt_query_is(cmd, size)) { - tc_pager_start(); - if (tc_query(cmd, &e) == 0) { - if (tc_query_foreach(tc_query_printer, NULL, &e) == -1) - reconnect = tc_cli_error(e); - } else { - reconnect = tc_cli_error(e); - } - tc_pager_stop(); - /* reconnect only for network errors */ - if (reconnect && tnt_error(tc.net) != TNT_ESYSTEM) - reconnect = 0; - } else { -#endif - enum tc_cli_cmd_ret rc = tc_cmd_try(cmd, size, &reconnect); - if (reconnect) - continue; - if (rc == TC_CLI_EXIT || rc == TC_CLI_ERROR) - return rc; -#if 0 - } -#endif - } while (reconnect); - - return TC_CLI_OK; -} - -int tc_cli_cmdv(void) -{ - int i, rc = 0; - for (i = 0 ; i < tc.opt.cmdc ; i++) { - char *cmd = tc.opt.cmdv[i]; - int cmd_len = strlen(tc.opt.cmdv[i]); - enum tc_cli_cmd_ret ret = tc_cli_cmd(cmd, cmd_len); - if (ret == TC_CLI_EXIT) - break; - if (ret == TC_CLI_ERROR) { - rc = 1; - break; - } - } - return rc; -} - -static void tc_cli_init(void) { - /* ignoring SIGPIPE for reconnection handling */ - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_IGN; - if (sigaction(SIGPIPE, &sa, NULL) == -1) - tc_error("signal initialization failed\n"); -} - -static char* tc_cli_readline_pipe() { - int size = 8192, pos = 0; - const size_t wcsize = sizeof(wchar_t); - char *str = (char *)malloc(size); - if (str == NULL) - tc_error(TC_ALLOCATION_ERROR, size); - wchar_t c; - while ((c = getwchar())) { - if (size < (pos + wcsize)) { - size *= 2; - char *nd = (char *)realloc(str, size); - if (nd == NULL) - tc_error(TC_REALLOCATION_ERROR, size); - str = nd; - } - if (c == '\r' || c == '\n' || c == WEOF) { - char c_t = (c != WEOF ? getchar() : '\n'); - if (c_t != '\r' && c_t != '\n') - ungetc(c_t, stdin); - wctomb(str + pos++, 0); - break; - } else { - pos += wctomb(str + pos, c); - } - } - if (pos == 1 && c == WEOF) { - free(str); - return NULL; - } - return str; -} - -static int check_delim(char* str, size_t len, size_t sep_len) { - const char *sep = tc.opt.delim; - if (sep_len == 0) - return 1; - if (len < sep_len) - return 0; - size_t i; - for (i = len; sep_len > 0; --sep_len, --i) - if (str[i - 1] != sep[sep_len - 1]) - return 0; - return 1; -} - -int tc_cli(void) -{ - /* initializing cli */ - tc_cli_init(); - - /* loading history file */ - char *home = getenv("HOME"); - char history[1024]; - snprintf(history, sizeof(history), "%s/%s", home, - TC_DEFAULT_HISTORY_FILE); - read_history(history); - - /* setting prompt */ - char prompt[128]; - int prompt_len = snprintf(prompt, sizeof(prompt), - "%s> ", tc.opt.host) - 2; - char prompt_delim[128]; - /* interactive mode */ - char *part_cmd; - struct tc_buf cmd; - if (tc_buf_str(&cmd)) - tc_error(TC_REALLOCATION_ERROR, - cmd.size); - while (1) { - if (isatty(STDIN_FILENO)) { - snprintf(prompt_delim, sizeof(prompt_delim), - "%*s> ", prompt_len, "-"); - part_cmd = readline(!tc_buf_str_isempty(&cmd) ? - prompt_delim : - prompt); - } else { - clearerr(stdin); - part_cmd = tc_cli_readline_pipe(); - } - if (!part_cmd) - break; - if (tc_buf_str_append(&cmd, part_cmd, strlen(part_cmd))) - tc_error(TC_REALLOCATION_ERROR, - cmd.size); - int delim_exists = check_delim( cmd.data, - cmd.used - 1, - tc.opt.delim_len); - if (tc_buf_str_append(&cmd, "\n", 1)) /* Append '\n' to the STR */ - tc_error(TC_REALLOCATION_ERROR, - cmd.size); - free(part_cmd); - if (!delim_exists && !feof(stdin)) /* If still without delimiter and not EOF */ - continue; - tc_buf_str_delete(&cmd, 1); /* Delete last appended '\n' */ - if (isatty(STDIN_FILENO)) /* Enable history on readline use only */ - add_history(cmd.data); - tc_buf_cmdfy(&cmd, tc.opt.delim_len); /* Create admin cmd from STR */ - enum tc_cli_cmd_ret ret; - if (delim_exists && tc_buf_str_isempty(&cmd)) { - tc_buf_clear(&cmd); - if (feof(stdin)) { - tc_buf_free(&cmd); - break; - } - } else { - ret = tc_cli_cmd(cmd.data, cmd.used - 1); - tc_buf_clear(&cmd); - if (ret == TC_CLI_EXIT || feof(stdin)) { - tc_buf_free(&cmd); - break; - } - } - } - - /* updating history file */ - write_history(history); - clear_history(); - return 0; -} - -#undef TC_ALLOCATION_ERROR -#undef TC_REALLOCATION_ERROR - -#if 0 -struct tc_version { - int a, b, c; - int commit; -}; - -static int -tc_versionof(struct tc_version *v, char *str) -{ - int rc = sscanf(str, "%d.%d.%d-%d", &v->a, &v->b, &v->c, &v->commit); - return rc == 4; -} - -static int -tc_versioncmp(struct tc_version *v, int a, int b, int c, int commit) -{ - int rc; - rc = v->a - a; - if (rc != 0) - return rc; - rc = v->b - b; - if (rc != 0) - return rc; - rc = v->c - c; - if (rc != 0) - return rc; - rc = v->commit - commit; - if (rc != 0) - return rc; - return 0; -} -#endif - -#if 0 - if (tc_admin_query(&tc.admin, "box.info.version") == -1) - return -1; - char *message = NULL; - size_t size = 0; - int rc = tc_admin_reply(&tc.admin, &message, &size); - if (rc == -1 || size < 8) { - free(message); - return -1; - } - char *version = message + 7; - char *eol = strchr(version, '\n'); - *eol = 0; - struct tc_version v; - rc = tc_versionof(&v, version); - if (rc == 0) { - free(message); - return -1; - } - free(message); - - /* call motd for version >= 1.5.3-93 */ - if (tc_versioncmp(&v, 1, 5, 3, 93) < 0) - return 0; - if (tc_admin_query(&tc.admin, "motd()") == -1) - return -1; - rc = tc_admin_reply(&tc.admin, &message, &size); - if (rc == -1 || size < 8) { - free(message); - return -1; - } - tc_printf("%s", message); - free(message); -#endif - -int tc_cli_motd(void) -{ - /* call motd for version >= 1.5.3-93 */ - if (tc_admin_query(&tc.admin, "motd()") == -1) - return -1; - char *message = NULL; - size_t size = 0; - int rc = tc_admin_reply(&tc.admin, &message, &size); - if (rc == -1 || size < 8) { - free(message); - return -1; - } - if (strcmp(message, "---\nunknown command. try typing help.\n...\n") == 0) { - free(message); - return 0; - } - tc_printf("%s", message); - free(message); - return 0; -} diff --git a/client/tarantool/tc_pager.c b/client/tarantool/tc_pager.c deleted file mode 100644 index a97b50dc00ab65e3ef4654377115253b8764511d..0000000000000000000000000000000000000000 --- a/client/tarantool/tc_pager.c +++ /dev/null @@ -1,60 +0,0 @@ -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <string.h> - -#include "client/tarantool/tc_opt.h" -#include "client/tarantool/tc_admin.h" -#include "client/tarantool/tc.h" -#include "client/tarantool/tc_pager.h" - -extern struct tc tc; - -void tc_pager_start() { - if (tc.pager_pid != 0) - tc_pager_kill(); - if (tc.opt.pager == NULL) { - tc.pager_fd = fileno(stdout); - return; - } - int pipefd[2]; - const char *const argv[] = {"/bin/sh", "-c", tc.opt.pager, NULL}; - - if (pipe(pipefd) < 0) - tc_error("Failed to open pipe. Errno: %s", strerror(errno)); - pid_t pid = fork(); - if (pid < 0) { - tc_error("Failed to fork. Errno: %s", strerror(errno)); - } else if (pid == 0) { - close(pipefd[1]); - dup2(pipefd[0], STDIN_FILENO); - execve(argv[0], (char * const*)argv, (char * const*)tc.opt.envp); - tc_error("Can't start pager! Errno: %s", strerror(errno)); - } else { - close(pipefd[0]); - tc.pager_fd = pipefd[1]; - tc.pager_pid = pid; - } - return; -} - -void tc_pager_stop () { - if (tc.pager_pid != 0) { - close(tc.pager_fd); - tc.pager_fd = fileno(stdout); - waitpid(tc.pager_pid, NULL, 0); - tc.pager_pid = 0; - } - return; -} - -void tc_pager_kill () { - if (tc.pager_pid != 0) { - kill(tc.pager_pid, SIGTERM); - tc_pager_stop(); - } -} diff --git a/connector/c/CMakeLists.txt b/connector/c/CMakeLists.txt index d2e18d8dbdb67629703816eed8f3510074dc90a6..c1e75e90e5840ea8d8cb30adac138df698df160d 100644 --- a/connector/c/CMakeLists.txt +++ b/connector/c/CMakeLists.txt @@ -2,16 +2,18 @@ # # library soname version # -set(LIBTNT_VERSION_MAJOR "1") -set(LIBTNT_VERSION_MINOR "1") +#set(LIBTNT_VERSION_MAJOR "1") +#set(LIBTNT_VERSION_MINOR "1") -set(LIBTNT_VERSION "${LIBTNT_VERSION_MAJOR}.${LIBTNT_VERSION_MINOR}") -set(LIBTNT_SOVERSION "${LIBTNT_VERSION_MAJOR}") +#set(LIBTNT_VERSION "${LIBTNT_VERSION_MAJOR}.${LIBTNT_VERSION_MINOR}") +#set(LIBTNT_SOVERSION "${LIBTNT_VERSION_MAJOR}") -include_directories("${PROJECT_SOURCE_DIR}/connector/c/include") +#include_directories("${PROJECT_SOURCE_DIR}/connector/c/include") -add_subdirectory(tnt) -add_subdirectory(tntsql) -add_subdirectory(tntnet) -add_subdirectory(tntrpl) -add_subdirectory(include) +#add_subdirectory(tnt) +#add_subdirectory(tntsql) +#add_subdirectory(tntnet) +#add_subdirectory(tntrpl) +#add_subdirectory(include) + +add_subdirectory(tb) diff --git a/connector/c/tb b/connector/c/tb new file mode 160000 index 0000000000000000000000000000000000000000..0d24b62555958ae6d5e0682c25062a9354ba3ae0 --- /dev/null +++ b/connector/c/tb @@ -0,0 +1 @@ +Subproject commit 0d24b62555958ae6d5e0682c25062a9354ba3ae0