diff --git a/client/tarantool/tc.c b/client/tarantool/tc.c index e42708d67ef882df2a725d680a10f10bc913fbde..db59b30fa288975da51fde21aed3986d3b82c51a 100644 --- a/client/tarantool/tc.c +++ b/client/tarantool/tc.c @@ -45,9 +45,14 @@ #include "client/tarantool/tc.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" -#include "client/tarantool/tc_store.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; @@ -79,6 +84,8 @@ void tc_error(char *fmt, ...) { 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) @@ -95,12 +102,43 @@ static void tc_connect(void) tc_error("%s", tnt_strerror(tc.net)); } +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; +} + static void tc_connect_admin(void) { + if (tc_admin_connect(&tc.admin, tc.opt.host, tc.opt.port_admin) == -1) tc_error("admin console connection failed"); + if (tc.opt.port == 0) + tc.opt.port = get_primary_port(); } static void tc_validate(void) @@ -108,12 +146,11 @@ 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) - return tc_error("unsupported output xlog format '%s'", + tc_error("unsupported output xlog format '%s'", tc.opt.format); if (tc.opt.snap_printer == NULL) - return tc_error("unsupported output snap format '%s'", + tc_error("unsupported output snap format '%s'", tc.opt.format); - if (tc.opt.format && strcmp(tc.opt.format, "raw") == 0) tc.opt.raw = 1; } @@ -144,13 +181,13 @@ int main(int argc, char *argv[]) rc = tc_store_play(); break; case TC_OPT_CMD: - tc_connect(); tc_connect_admin(); + tc_connect(); rc = tc_cli_cmdv(); break; case TC_OPT_INTERACTIVE: - tc_connect(); tc_connect_admin(); + tc_connect(); tc_cli_motd(); rc = tc_cli(); break; diff --git a/client/tarantool/tc_buf.c b/client/tarantool/tc_buf.c index b4556bb796078d1b86f5b54a84b2146268e22c87..4826ed1361294867c03afb24155875d829d138a5 100644 --- a/client/tarantool/tc_buf.c +++ b/client/tarantool/tc_buf.c @@ -37,9 +37,10 @@ /* Strip trailing ws from (char*) */ size_t strip_end_ws(char *str) { size_t last = 0; - for (size_t i = 0; str[i] != 0; ++i) + for (size_t i = 0; str[i] != 0; ++i) { if (!isspace(str[i])) last = i + 1; + } str[last] = '\0'; return last; } @@ -49,16 +50,18 @@ int tc_buf(struct tc_buf *buf) { buf->size = TC_BUF_INIT_SIZE; buf->used = 0; buf->data = (char *)malloc(buf->size); - if (buf->data == NULL) + if (buf->data == NULL) { return -1; + } return 0; } /* Append len bytes of memory from str pointed memory */ int tc_buf_append(struct tc_buf *buf, void *str, size_t len) { if (buf->size - buf->used < len) { - if (buf->size < len) + if (buf->size < len) { buf->size = len; + } buf->size *= TC_BUF_MULTIPLIER; char *nd = (char *)realloc(buf->data, buf->size); if (nd == NULL) @@ -112,6 +115,26 @@ int tc_buf_str_append(struct tc_buf *buf, char *str, size_t len) { return 0; } +/* Remove last num symbols from STR */ +size_t tc_buf_str_delete(struct tc_buf *buf, size_t len) { + size_t ret = tc_buf_delete(buf, len + 1); /* Remove '\0' + len */ + if (tc_buf_append(buf, (void *)"\0", 1)) + return 0; + return ret; +} + +/* + * Make admin command from multiline command + * and delete delimiter (last num bytes) + */ +void tc_buf_cmdfy(struct tc_buf *buf, size_t num) { + tc_buf_str_delete(buf, num); + for (int i = 0; i < buf->used; ++i) { + if (buf->data[i] == '\n') + buf->data[i] = ' '; + } +} + /* Remove trailing ws from STR */ int tc_buf_str_stripws(struct tc_buf *buf) { if (buf->data) { diff --git a/client/tarantool/tc_buf.h b/client/tarantool/tc_buf.h index 52383666e7a7adf1cd869c1e96ff3a4e197d781d..3e528c20d7742a424aa9a4c417f81a5d8f7ddd39 100644 --- a/client/tarantool/tc_buf.h +++ b/client/tarantool/tc_buf.h @@ -40,12 +40,15 @@ struct tc_buf { int tc_buf(struct tc_buf *buf); void *tc_buf_realloc(void *data, size_t size); int tc_buf_append(struct tc_buf *buf, void *str, size_t len); -size_t tc_buf_delete(struct tc_buf *buf, size_t len); +size_t tc_buf_delete(struct tc_buf *buf, size_t num); int tc_buf_isempty(struct tc_buf *buf); void tc_buf_clear(struct tc_buf *buf); void tc_buf_free(struct tc_buf *buf); int tc_buf_str(struct tc_buf *buf); int tc_buf_str_append(struct tc_buf *buf, char *str, size_t len); +size_t tc_buf_str_delete(struct tc_buf *buf, size_t num); int tc_buf_str_stripws(struct tc_buf *buf); int tc_buf_str_isempty(struct tc_buf *buf); + +void tc_buf_cmdfy(struct tc_buf *buf, size_t num); diff --git a/client/tarantool/tc_cli.c b/client/tarantool/tc_cli.c index f6ea1ea346f90abe240f8a6fcf1c164a926ef4c4..53fda89668654c5590b5b94f9cf9352dcc7f1d25 100644 --- a/client/tarantool/tc_cli.c +++ b/client/tarantool/tc_cli.c @@ -109,7 +109,6 @@ static struct tnt_lex_keyword tc_lex_keywords[] = { "notee", 5, TC_NOTEE }, { "loadfile", 8, TC_LOADFILE }, { "setopt", 6, TC_SETOPT}, - { "delim", 5, TC_SETOPT_DELIM}, { "delimiter", 9, TC_SETOPT_DELIM}, { NULL, 0, TNT_TK_NONE } }; @@ -125,13 +124,13 @@ tc_cmd_usage(void) { char usage[] = "---\n" - "- console client commands\n" - "- - help\n" - " - tee 'path'\n" - " - notee\n" - " - loadfile 'path'\n" - " - setopt key=val\n" - " - (possible pairs: delim[iter]=\'string\')\n" + "console client commands:\n" + " - help\n" + " - tee 'path'\n" + " - notee\n" + " - loadfile 'path'\n" + " - setopt key val\n" + " - (possible pairs: delimiter 'string')\n" "...\n"; tc_printf("%s", usage); } @@ -225,6 +224,17 @@ tc_cmd_loadfile(char *path, int *reconnect) return rc; } +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'; +} + static enum tc_cli_cmd_ret tc_cmd_try(char *cmd, size_t size, int *reconnect) { @@ -263,8 +273,10 @@ tc_cmd_try(char *cmd, size_t size, int *reconnect) case TC_SETOPT: switch (tnt_lex(&lex, &tk)) { case TC_SETOPT_DELIM: - if (tnt_lex(&lex, &tk) == '=' && - tnt_lex(&lex, &tk) == TNT_TK_STRING) { + 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; @@ -277,11 +289,12 @@ tc_cmd_try(char *cmd, size_t size, int *reconnect) 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: setopt delim[iter]='string'\n"); + tc_printf(" - Expected `setopt delimiter 'string'`\n"); tc_printf("---\n"); } break; @@ -381,9 +394,9 @@ static char* tc_cli_readline_pipe() { ungetc(c_t, stdin); wctomb(str + pos++, 0); break; - } - else + } else { pos += wctomb(str + pos, c); + } } if (pos == 1 && c == WEOF) { free(str); @@ -394,7 +407,6 @@ static char* tc_cli_readline_pipe() { static int check_delim(char* str, size_t len, size_t sep_len) { const char *sep = tc.opt.delim; - len = strip_end_ws(str); if (sep_len == 0) return 1; if (len < sep_len) @@ -403,8 +415,6 @@ static int check_delim(char* str, size_t len, size_t sep_len) { for (i = len; sep_len > 0; --sep_len, --i) if (str[i - 1] != sep[sep_len - 1]) return 0; - str[i] = '\0'; - len = strip_end_ws(str); return 1; } @@ -434,44 +444,44 @@ int tc_cli(void) if (isatty(STDIN_FILENO)) { snprintf(prompt_delim, sizeof(prompt_delim), "%*s> ", prompt_len, "-"); - part_cmd = readline(!tc_buf_str_isempty(&cmd) ? prompt_delim - : prompt); + part_cmd = readline(! tc_buf_str_isempty(&cmd) + ? prompt_delim + : prompt); } else { clearerr(stdin); part_cmd = tc_cli_readline_pipe(); } if (!part_cmd) break; - size_t part_cmd_len = strlen(part_cmd); - int delim_exists = check_delim(part_cmd, - part_cmd_len, - tc.opt.delim_len); 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 (tc_buf_str_append(&cmd, " ", 1)) - tc_error(TC_REALLOCATION_ERROR, - cmd.size); + if (!delim_exists && !feof(stdin)) /* If still without delimiter and not EOF */ continue; - } - tc_buf_str_stripws(&cmd); + 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 */ if (delim_exists && tc_buf_str_isempty(&cmd)) - goto next; + goto next; /* If empty - don't send to server, it crashes */ tc_print_cmd2tee(cmd.used != 1 ? prompt_delim : prompt, cmd.data, cmd.used - 1); enum tc_cli_cmd_ret ret = tc_cli_cmd(cmd.data, cmd.used - 1); - if (isatty(STDIN_FILENO)) - add_history(cmd.data); next: tc_buf_clear(&cmd); if (ret == TC_CLI_EXIT || feof(stdin)) { tc_buf_free(&cmd); break; } -} + } /* updating history file */ write_history(history); diff --git a/client/tarantool/tc_opt.c b/client/tarantool/tc_opt.c index 93d0f4a00836edaf073efdbc0eb4d4245088ee24..c0096a275caf313d3acaa3e4fa7a65ade1dfec5a 100644 --- a/client/tarantool/tc_opt.c +++ b/client/tarantool/tc_opt.c @@ -37,7 +37,6 @@ #define TC_DEFAULT_HOST "localhost" -#define TC_DEFAULT_PORT 33013 #define TC_DEFAULT_PORT_ADMIN 33015 /* supported cli options */ @@ -116,7 +115,7 @@ enum tc_opt_mode tc_opt_init(struct tc_opt *opt, int argc, char **argv) /* server port */ const char *arg = NULL; - opt->port = TC_DEFAULT_PORT; + opt->port = 0; if (gopt_arg(tc_options, 'p', &arg)) opt->port = atoi(arg); diff --git a/extra/tarantool_box b/extra/tarantool_box old mode 100755 new mode 100644 index 3538a99ba62876fdcda6ebc65dacec0f33621885..ae855b504310969ade272925979ce9c727b4631b --- a/extra/tarantool_box +++ b/extra/tarantool_box @@ -32,8 +32,30 @@ then exit fi +checkactive() { + if [ -f ${WRAP_PIDFILE} ] + then + ps -p $(cat ${WRAP_PIDFILE}) >/dev/null 2>&1 + if [ $? -eq 0 ]; then + echo -n "(instance is active)" + echo_failure + exit 1 + fi + fi + if [ -f ${PIDFILE} ] + then + ps -p $(cat ${PIDFILE}) >/dev/null 2>&1 + if [ $? -eq 0 ]; then + echo -n "(instance is active)" + echo_failure + exit 1 + fi + fi +} + start() { echo -n $"Starting ${INST}: " + checkactive /usr/bin/${INST}.sh ${OPTIONS} >> /var/${INST}/logs/init.log 2>&1 RETVAL=${?} if [ ${RETVAL} -eq 0 ] diff --git a/src/say.cc b/src/say.cc index 55585103bb012330b4f1b2995087fb6abc474e69..bfaea8f521ec53f6bd62e66b31f0b09e693adb19 100644 --- a/src/say.cc +++ b/src/say.cc @@ -123,6 +123,7 @@ say_logger_init(int nonblock) execve(argv[0], argv, envp); goto error; } +#ifndef TARGET_OS_DARWIN /* * A courtesy to a DBA who might have * misconfigured the logger option: check whether @@ -135,6 +136,7 @@ say_logger_init(int nonblock) timeout.tv_nsec = 1; /* Mostly to trigger preemption. */ if (sigtimedwait(&mask, NULL, &timeout) == SIGCHLD) goto error; +#endif /* OK, let's hope for the best. */ sigprocmask(SIG_UNBLOCK, &mask, NULL);