From 927e9dbf45e421eb46a7726690693696555ff666 Mon Sep 17 00:00:00 2001 From: Roman Tokarev <rtokarev@corp.mail.ru> Date: Tue, 5 Apr 2011 17:02:18 +0400 Subject: [PATCH] Update files generated by confetti. Port tarantool to ObjectiveC. Implement basic TNTException class and TNTFiberException and TNTBoxException subclasses. Replace longjmp/setjmp with ObjectiveC exceptions. mod/box: Restructurize request processing in the following way: try begin dispatch commit catch abort where any error during request processing generate an exception. --- CMakeLists.txt | 10 +- cfg/CMakeLists.txt | 4 +- cfg/prscfg.c | 9 +- cfg/tarantool_box_cfg.c | 3 +- cfg/tarantool_feeder_cfg.c | 3 +- cfg/warning.c | 6 +- cfg/warning.h | 8 + core/CMakeLists.txt | 36 +- core/{admin.c => admin.m} | 0 core/{coro.c => coro.m} | 0 core/{diagnostics.c => diagnostics.m} | 1 + core/exceptions.m | 34 ++ core/{fiber.c => fiber.m} | 22 +- core/{iproto.c => iproto.m} | 0 core/{log_io.c => log_io.m} | 139 ++++--- core/{log_io_remote.c => log_io_remote.m} | 12 - core/{palloc.c => palloc.m} | 0 core/{pickle.c => pickle.m} | 39 +- core/{salloc.c => salloc.m} | 0 core/{say.c => say.m} | 0 core/{stat.c => stat.m} | 0 core/{tarantool.c => tarantool.m} | 3 +- core/{tarantool_ev.c => tarantool_ev.m} | 0 core/{tbuf.c => tbuf.m} | 0 core/{trace.c => trace.m} | 0 core/{util.c => util.m} | 0 include/exceptions.h | 16 + include/fiber.h | 17 +- include/pickle.h | 4 + include/tarantool.h | 1 - mod/box/CMakeLists.txt | 12 +- mod/box/box.h | 33 +- mod/box/{box.c => box.m} | 445 ++++++++++++---------- mod/box/index.h | 2 +- mod/box/{index.c => index.m} | 4 +- mod/box/{memcached.c => memcached.m} | 4 +- mod/box/memcached.rl | 4 +- mod/feeder/CMakeLists.txt | 2 +- mod/feeder/{feeder.c => feeder.m} | 0 39 files changed, 494 insertions(+), 379 deletions(-) rename core/{admin.c => admin.m} (100%) rename core/{coro.c => coro.m} (100%) rename core/{diagnostics.c => diagnostics.m} (98%) create mode 100644 core/exceptions.m rename core/{fiber.c => fiber.m} (97%) rename core/{iproto.c => iproto.m} (100%) rename core/{log_io.c => log_io.m} (95%) rename core/{log_io_remote.c => log_io_remote.m} (97%) rename core/{palloc.c => palloc.m} (100%) rename core/{pickle.c => pickle.m} (85%) rename core/{salloc.c => salloc.m} (100%) rename core/{say.c => say.m} (100%) rename core/{stat.c => stat.m} (100%) rename core/{tarantool.c => tarantool.m} (99%) rename core/{tarantool_ev.c => tarantool_ev.m} (100%) rename core/{tbuf.c => tbuf.m} (100%) rename core/{trace.c => trace.m} (100%) rename core/{util.c => util.m} (100%) create mode 100644 include/exceptions.h rename mod/box/{box.c => box.m} (89%) rename mod/box/{index.c => index.m} (99%) rename mod/box/{memcached.c => memcached.m} (99%) rename mod/feeder/{feeder.c => feeder.m} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee9f9944fc..29228c13c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ set (CMAKE_C_FLAGS_RELEASE "-DNDEBUG -DNVALGRIND") # # Enable 'make TAGS' target. # -add_custom_target(TAGS COMMAND ctags -R -e -f TAGS +add_custom_target(TAGS COMMAND ctags -R --langmap=ObjectiveC:.m.h -e -f TAGS WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) # @@ -180,6 +180,14 @@ if (ENABLE_STATIC) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static") endif() +# CMake believes that Objective C is a flavor of C++, not C, +# and uses g++ compiler for .m files. Since talking CMake out +# of this idea is difficult, and since gcc or g++ are only +# front-ends to the language-specific compiler specified in +# -x option, simply use CXX flags to build Objective C files. +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}") + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") add_subdirectory(third_party) add_subdirectory(cfg) diff --git a/cfg/CMakeLists.txt b/cfg/CMakeLists.txt index a13e8e0254..cd5fc2e574 100644 --- a/cfg/CMakeLists.txt +++ b/cfg/CMakeLists.txt @@ -10,7 +10,7 @@ add_custom_command( OUTPUT ${CMAKE_SOURCE_DIR}/cfg/prscfg.h ${CMAKE_SOURCE_DIR}/cfg/prscfg.c COMMAND ${ECHO} '%{' > tmp.cfg - COMMAND ${CAT} ${CMAKE_SOURCE_DIR}/cfg/warning.h >> tmp.cfg + COMMAND ${ECHO} '\#include \"cfg/warning.h\"' >> tmp.cfg COMMAND ${ECHO} '%}' >> tmp.cfg COMMAND ${CAT} ${CMAKE_SOURCE_DIR}/cfg/core_cfg.cfg_tmpl >> tmp.cfg COMMAND ${CONFETTI} -i tmp.cfg -n tarantool_cfg @@ -37,7 +37,7 @@ add_custom_command( ${CMAKE_SOURCE_DIR}/cfg/tarantool_${mod}_cfg.c ${CMAKE_SOURCE_DIR}/cfg/tarantool_${mod}_cfg.cfg COMMAND ${ECHO} '%{' > ${mod}_tmp.cfg - COMMAND ${CAT} ${CMAKE_SOURCE_DIR}/cfg/warning.h >> ${mod}_tmp.cfg + COMMAND ${ECHO} '\#include \"cfg/warning.h\"' >> ${mod}_tmp.cfg COMMAND ${ECHO} '\#include \"cfg/tarantool_${mod}_cfg.h\"' >> ${mod}_tmp.cfg COMMAND ${ECHO} '%}' >> ${mod}_tmp.cfg COMMAND ${CAT} ${CMAKE_SOURCE_DIR}/cfg/core_cfg.cfg_tmpl >> ${mod}_tmp.cfg diff --git a/cfg/prscfg.c b/cfg/prscfg.c index cc4ef3a14f..6f930b537c 100644 --- a/cfg/prscfg.c +++ b/cfg/prscfg.c @@ -1,6 +1,5 @@ -#include "prscfg.h" -void out_warning(ConfettyError r, char *format, ...); +#include "cfg/warning.h" #include <stdio.h> typedef struct prscfg_yy_extra_type { @@ -1770,7 +1769,7 @@ YYSTYPE yylval; /* Line 1455 of yacc.c */ #line 173 "prscfg.y" { - OptDef *str; + OptDef *str; NameAtom *idx; MakeAtom(idx, NULL); @@ -1787,7 +1786,7 @@ YYSTYPE yylval; /* Line 1455 of yacc.c */ #line 184 "prscfg.y" { - OptDef *str; + OptDef *str; NameAtom *idx; MakeAtom(idx, NULL); @@ -2100,7 +2099,7 @@ compileName(OptDef *def) { return 1; if (index >= 0) { - beginPtr->index = index; + endPtr->index = index; index = -1; } diff --git a/cfg/tarantool_box_cfg.c b/cfg/tarantool_box_cfg.c index 7218b9624b..deea203080 100644 --- a/cfg/tarantool_box_cfg.c +++ b/cfg/tarantool_box_cfg.c @@ -11,8 +11,7 @@ */ -#include "prscfg.h" -void out_warning(ConfettyError r, char *format, ...); +#include "cfg/warning.h" #include "cfg/tarantool_box_cfg.h" static int cmpNameAtoms(NameAtom *a, NameAtom *b) { diff --git a/cfg/tarantool_feeder_cfg.c b/cfg/tarantool_feeder_cfg.c index 6719ca8a8e..654730105b 100644 --- a/cfg/tarantool_feeder_cfg.c +++ b/cfg/tarantool_feeder_cfg.c @@ -11,8 +11,7 @@ */ -#include "prscfg.h" -void out_warning(ConfettyError r, char *format, ...); +#include "cfg/warning.h" #include "cfg/tarantool_feeder_cfg.h" static int cmpNameAtoms(NameAtom *a, NameAtom *b) { diff --git a/cfg/warning.c b/cfg/warning.c index 0075f778e7..c3887e92ed 100644 --- a/cfg/warning.c +++ b/cfg/warning.c @@ -1,8 +1,10 @@ #include "warning.h" + +#include <tbuf.h> + #include <stdarg.h> -#include <tarantool.h> -#include <util.h> +struct tbuf *cfg_out = NULL; /** This is a callback function used by the generated * configuration file parser (tarantool_{box, feeder, ...}_cfg.c) diff --git a/cfg/warning.h b/cfg/warning.h index 3898f77987..58792abe3a 100644 --- a/cfg/warning.h +++ b/cfg/warning.h @@ -1,2 +1,10 @@ +#ifndef TARANTOOL_WARNING_H +#define TARANTOOL_WARNING_H + #include "prscfg.h" + +extern struct tbuf *cfg_out; + void out_warning(ConfettyError r, char *format, ...); + +#endif diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 9ccc809a0f..1c59e887b9 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,12 +1,12 @@ # # libev library # -add_library(ev tarantool_ev.c) +add_library(ev tarantool_ev.m) check_c_compiler_flag ("-Wno-unused-result" gcc_has_wno_unused_result) if (gcc_has_wno_unused_result) - set_source_files_properties(tarantool_ev.c + set_source_files_properties(tarantool_ev.m PROPERTIES COMPILE_FLAGS "-Wno-unused-result") endif() @@ -25,21 +25,21 @@ endif() target_link_libraries(ev m) # -# Build admin.c from admin.rl, but only if admin.rl was changed. -# The same applies to memcached.c/memcached.rl. -# We track admin.c and memcached.c in revision control, and thus do not +# Build admin.m from admin.rl, but only if admin.rl was changed. +# The same applies to memcached.m/memcached.rl. +# We track admin.m and memcached.m in revision control, and thus do not # require engineers who do not modify .rl files to have Ragel # installed. # -add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/core/admin.c +add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/core/admin.m WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND ${RAGEL} -G2 core/admin.rl -o core/admin.c + COMMAND ${RAGEL} -G2 core/admin.rl -o core/admin.m DEPENDS ${CMAKE_SOURCE_DIR}/core/admin.rl) -add_custom_target(generate_admin_c DEPENDS ${CMAKE_SOURCE_DIR}/core/admin.c) +add_custom_target(generate_admin_c DEPENDS ${CMAKE_SOURCE_DIR}/core/admin.m) # -# Do not clean admin.c, memcached.c or other +# Do not clean admin.m, memcached.m or other # generated files in 'make clean' -- they are under # revision control. # @@ -49,24 +49,24 @@ set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM 1) # Used by modules. # set (recompiled_core_sources - ${CMAKE_SOURCE_DIR}/core/tarantool.c - ${CMAKE_SOURCE_DIR}/core/say.c - ${CMAKE_SOURCE_DIR}/core/admin.c - ${CMAKE_SOURCE_DIR}/core/fiber.c PARENT_SCOPE) + ${CMAKE_SOURCE_DIR}/core/tarantool.m + ${CMAKE_SOURCE_DIR}/core/say.m + ${CMAKE_SOURCE_DIR}/core/admin.m + ${CMAKE_SOURCE_DIR}/core/fiber.m PARENT_SCOPE) -set (common_sources tbuf.c palloc.c util.c diagnostics.c - salloc.c pickle.c coro.c stat.c log_io.c - log_io_remote.c iproto.c) +set (common_sources tbuf.m palloc.m util.m diagnostics.m + salloc.m pickle.m coro.m stat.m log_io.m + log_io_remote.m iproto.m exceptions.m) if (ENABLE_TRACE) - set (common_sources ${common_sources} trace.c) + set (common_sources ${common_sources} trace.m) endif() add_library(core STATIC ${common_sources}) add_dependencies(core generate_headers) set_target_properties(core PROPERTIES COMPILE_FLAGS "${core_cflags}") -set (common_libraries cfg core ev coro gopt misc) +set (common_libraries cfg core ev coro gopt misc objc) if (ENABLE_GCOV) set (common_libraries ${common_libraries} gcov) diff --git a/core/admin.c b/core/admin.m similarity index 100% rename from core/admin.c rename to core/admin.m diff --git a/core/coro.c b/core/coro.m similarity index 100% rename from core/coro.c rename to core/coro.m diff --git a/core/diagnostics.c b/core/diagnostics.m similarity index 98% rename from core/diagnostics.c rename to core/diagnostics.m index 7a6e6a2445..3266ae52a0 100644 --- a/core/diagnostics.c +++ b/core/diagnostics.m @@ -88,4 +88,5 @@ struct Error *diag_get_last_error() void diag_clear() { error_destroy(fiber->diagnostics); + fiber->diagnostics = NULL; } diff --git a/core/exceptions.m b/core/exceptions.m new file mode 100644 index 0000000000..45eaacf81b --- /dev/null +++ b/core/exceptions.m @@ -0,0 +1,34 @@ +#include <exceptions.h> + +@implementation TNTException ++(id) withReason:(const char *)str +{ + static id e = nil; + + if (![e isKindOf:self]) { + [e free]; + e = [[self alloc] init]; + } + + return [e setReason:str]; +} + +-(void) init +{ + [super init]; + + reason = ""; +} + +-(TNTException *) setReason:(const char *)str +{ + reason = str; + + return self; +} + +-(const char *) Reason +{ + return reason; +} +@end diff --git a/core/fiber.c b/core/fiber.m similarity index 97% rename from core/fiber.c rename to core/fiber.m index 690f4f7557..b0645334f7 100644 --- a/core/fiber.c +++ b/core/fiber.m @@ -56,6 +56,9 @@ #include <pickle.h> #include "diagnostics.h" +@implementation TNTFiberException +@end + static struct fiber sched; struct fiber *fiber = &sched; static struct fiber **sp, *call_stack[64]; @@ -342,10 +345,20 @@ fiber_loop(void *data __attribute__((unused))) { while (42) { assert(fiber != NULL && fiber->f != NULL && fiber->fid != 0); - if (setjmp(fiber->exc) == 0) { + @try { fiber->f(fiber->f_data); - } else { - panic("fiber %s failure, exiting", fiber->name); + } + @catch (TNTFiberException *e) { + say_info("fiber `%s': exception `TNTFiberException': `%s'", fiber->name, [e Reason]); + say_info("fiber `%s': exiting", fiber->name); + } + @catch (TNTException *e) { + say_error("fiber `%s': exception `%s': `%s'", fiber->name, [e name], [e Reason]); + panic("fiber `%s': exiting", fiber->name); + } + @catch (id e) { + say_error("fiber `%s': exception `%s'", fiber->name, [e name]); + panic("fiber `%s': exiting", fiber->name); } fiber_close(); @@ -1119,9 +1132,6 @@ fiber_info(struct tbuf *out) tbuf_printf(out, " fd: %4i" CRLF, fiber->fd); tbuf_printf(out, " peer: %s" CRLF, fiber_peer_name(fiber)); tbuf_printf(out, " stack: %p" CRLF, stack_top); - tbuf_printf(out, " exc: %p" CRLF, - ((void **)fiber->exc)[3]); - tbuf_printf(out, " exc_frame: %p,"CRLF, ((void **)fiber->exc)[3] + 2 * sizeof(void *)); #ifdef ENABLE_BACKTRACE tbuf_printf(out, " backtrace:" CRLF "%s", backtrace(fiber->last_stack_frame, diff --git a/core/iproto.c b/core/iproto.m similarity index 100% rename from core/iproto.c rename to core/iproto.m diff --git a/core/log_io.c b/core/log_io.m similarity index 95% rename from core/log_io.c rename to core/log_io.m index 345c8e94c4..00d3f9f5c6 100644 --- a/core/log_io.c +++ b/core/log_io.m @@ -903,53 +903,48 @@ recover_snap(struct recovery_state *r) struct log_io_iter i; struct log_io *snap = NULL; struct tbuf *row; - int result = -1; i64 lsn; - memset(&i, 0, sizeof(i)); + @try { + memset(&i, 0, sizeof(i)); - if (setjmp(fiber->exc) != 0) { - result = -1; - goto out; - } + lsn = greatest_lsn(r->snap_prefered_class); + if (lsn <= 0) + raise("can't find snapshot"); - lsn = greatest_lsn(r->snap_prefered_class); + snap = open_for_read(r, r->snap_class, lsn, 0, NULL); + if (snap == NULL) + raise("can't find/open snapshot"); - if (lsn <= 0) { - say_error("can't find snapshot"); - goto out; - } + iter_open(snap, &i, read_rows); + say_info("recover from `%s'", snap->filename); - snap = open_for_read(r, r->snap_class, lsn, 0, NULL); - if (snap == NULL) { - say_error("can't find/open snapshot"); - goto out; - } + while ((row = iter_inner(&i, (void *)1))) { + if (r->row_handler(r, row) < 0) + raise("can't apply row"); + } + if (i.error != 0) + raise("error during snapshot processing"); - iter_open(snap, &i, read_rows); - say_info("recover from `%s'", snap->filename); + r->lsn = r->confirmed_lsn = lsn; - while ((row = iter_inner(&i, (void *)1))) { - if (r->row_handler(r, row) < 0) { - result = -1; - goto out; - } + return 0; } - result = i.error; - if (result == 0) - r->lsn = r->confirmed_lsn = lsn; - out: - if (result != 0) + @catch (TNTException *e) { + say_error("TNTException: `%s'", [e Reason]); say_error("failure reading snapshot"); - if (i.log != NULL) - close_iter(&i); + return -1; + } + @finally { + if (i.log != NULL) + close_iter(&i); - if (snap != NULL) - close_log(&snap); + if (snap != NULL) + close_log(&snap); - prelease(fiber->pool); - return result; + prelease(fiber->pool); + } } /* @@ -966,56 +961,54 @@ recover_wal(struct recovery_state *r, struct log_io *l) { struct log_io_iter i; struct tbuf *row = NULL; - int result; - if (setjmp(fiber->exc) != 0) { - result = -1; - goto out; - } + @try { + memset(&i, 0, sizeof(i)); + iter_open(l, &i, read_rows); - memset(&i, 0, sizeof(i)); - iter_open(l, &i, read_rows); + while ((row = iter_inner(&i, (void *)1))) { + i64 lsn = row_v11(row)->lsn; + if (r && lsn <= r->confirmed_lsn) { + say_debug("skipping too young row"); + continue; + } - while ((row = iter_inner(&i, (void *)1))) { - i64 lsn = row_v11(row)->lsn; - if (r && lsn <= r->confirmed_lsn) { - say_debug("skipping too young row"); - continue; - } + /* after handler(r, row) returned, row may be modified, do not use it */ + if (r->row_handler(r, row) < 0) + raise("can't apply row"); - /* after handler(r, row) returned, row may be modified, do not use it */ - if (r->row_handler(r, row) < 0) { - say_error("row_handler returned error"); - result = -1; - goto out; + if (r) { + next_lsn(r, lsn); + confirm_lsn(r, lsn); + } } - if (r) { - next_lsn(r, lsn); - confirm_lsn(r, lsn); - } - } - result = i.error; - out: - /* - * since we don't close log_io - * we must rewind log_io to last known - * good position if where was error - */ - if (row) - iter_inner(&i, NULL); + if (i.error != 0) + raise("error during xlog processing"); - if (result == 0) { if (i.eof) - result = LOG_EOF; - else - result = 1; + return LOG_EOF; + + return 1; } + @catch (TNTException *e) { + say_error("TNTException: `%s'", [e Reason]); + say_error("failure reading xlog"); - close_iter(&i); - prelease(fiber->pool); + return -1; + } + @finally { + /* + * since we don't close log_io + * we must rewind log_io to last known + * good position if where was error + */ + if (row) + iter_inner(&i, NULL); - return result; + close_iter(&i); + prelease(fiber->pool); + } } /* diff --git a/core/log_io_remote.c b/core/log_io_remote.m similarity index 97% rename from core/log_io_remote.c rename to core/log_io_remote.m index 7201582979..db02df43c0 100644 --- a/core/log_io_remote.c +++ b/core/log_io_remote.m @@ -133,18 +133,6 @@ pull_from_remote(void *state) struct remote_state *h = state; struct tbuf *row; - switch (setjmp(fiber->exc)) { - case 0: - break; - - case FIBER_EXIT: - fiber_close(); - return; - - default: - fiber_close(); - } - for (;;) { row = remote_read_row(h->r->confirmed_lsn + 1); h->r->recovery_lag = ev_now() - row_v11(row)->tm; diff --git a/core/palloc.c b/core/palloc.m similarity index 100% rename from core/palloc.c rename to core/palloc.m diff --git a/core/pickle.c b/core/pickle.m similarity index 85% rename from core/pickle.c rename to core/pickle.m index 013c5fe6ba..5185e32e33 100644 --- a/core/pickle.c +++ b/core/pickle.m @@ -30,6 +30,11 @@ #include <iproto.h> /* for err codes */ #include "say.h" +#define pickle_raise(reason...) @throw [TNTPickleException withReason:reason"\0"] + +@implementation TNTPickleException +@end + /* caller must ensure that there is space in target */ u8 * save_varint32(u8 *target, u32 value) @@ -76,16 +81,16 @@ write_varint32(struct tbuf *b, u32 value) append_byte(b, (u8)((value) & 0x7F)); } -#define read_u(bits) \ - u##bits read_u##bits(struct tbuf *b) \ - { \ - if (b->len < (bits)/8) \ - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); \ - u##bits r = *(u##bits *)b->data; \ - b->size -= (bits)/8; \ - b->len -= (bits)/8; \ - b->data += (bits)/8; \ - return r; \ +#define read_u(bits) \ + u##bits read_u##bits(struct tbuf *b) \ + { \ + if (b->len < (bits)/8) \ + pickle_raise("buffer too short"); \ + u##bits r = *(u##bits *)b->data; \ + b->size -= (bits)/8; \ + b->len -= (bits)/8; \ + b->data += (bits)/8; \ + return r; \ } read_u(8) @@ -100,7 +105,7 @@ read_varint32(struct tbuf *buf) int len = buf->len; if (len < 1) - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); + pickle_raise("buffer too short"); if (!(b[0] & 0x80)) { buf->data += 1; buf->size -= 1; @@ -109,7 +114,7 @@ read_varint32(struct tbuf *buf) } if (len < 2) - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); + pickle_raise("buffer too short"); if (!(b[1] & 0x80)) { buf->data += 2; buf->size -= 2; @@ -117,7 +122,7 @@ read_varint32(struct tbuf *buf) return (b[0] & 0x7f) << 7 | (b[1] & 0x7f); } if (len < 3) - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); + pickle_raise("buffer too short"); if (!(b[2] & 0x80)) { buf->data += 3; buf->size -= 3; @@ -126,7 +131,7 @@ read_varint32(struct tbuf *buf) } if (len < 4) - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); + pickle_raise("buffer too short"); if (!(b[3] & 0x80)) { buf->data += 4; buf->size -= 4; @@ -136,7 +141,7 @@ read_varint32(struct tbuf *buf) } if (len < 5) - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); + pickle_raise("buffer too short"); if (!(b[4] & 0x80)) { buf->data += 5; buf->size -= 5; @@ -145,7 +150,7 @@ read_varint32(struct tbuf *buf) (b[2] & 0x7f) << 14 | (b[3] & 0x7f) << 7 | (b[4] & 0x7f); } - raise(ERR_CODE_UNKNOWN_ERROR, "impossible happened"); + pickle_raise("impossible happened"); return 0; } @@ -165,7 +170,7 @@ read_field(struct tbuf *buf) u32 data_len = read_varint32(buf); if (data_len > buf->len) - raise(ERR_CODE_UNKNOWN_ERROR, "buffer too short"); + pickle_raise("buffer too short"); buf->size -= data_len; buf->len -= data_len; diff --git a/core/salloc.c b/core/salloc.m similarity index 100% rename from core/salloc.c rename to core/salloc.m diff --git a/core/say.c b/core/say.m similarity index 100% rename from core/say.c rename to core/say.m diff --git a/core/stat.c b/core/stat.m similarity index 100% rename from core/stat.c rename to core/stat.m diff --git a/core/tarantool.c b/core/tarantool.m similarity index 99% rename from core/tarantool.c rename to core/tarantool.m index 1450e582ad..d14b975cd5 100644 --- a/core/tarantool.c +++ b/core/tarantool.m @@ -53,13 +53,13 @@ #include TARANTOOL_CONFIG #include <util.h> #include <third_party/gopt/gopt.h> +#include <cfg/warning.h> static pid_t master_pid; #define DEFAULT_CFG_FILENAME "tarantool.cfg" const char *cfg_filename = DEFAULT_CFG_FILENAME; char *cfg_filename_fullpath = NULL; -struct tbuf *cfg_out = NULL; char *binary_filename; struct tarantool_cfg cfg; struct recovery_state *recovery_state; @@ -67,7 +67,6 @@ struct recovery_state *recovery_state; bool init_storage, booting = true; extern int daemonize(int nochdir, int noclose); -void out_warning(int v, char *format, ...); static i32 load_cfg(struct tarantool_cfg *conf, i32 check_rdonly) diff --git a/core/tarantool_ev.c b/core/tarantool_ev.m similarity index 100% rename from core/tarantool_ev.c rename to core/tarantool_ev.m diff --git a/core/tbuf.c b/core/tbuf.m similarity index 100% rename from core/tbuf.c rename to core/tbuf.m diff --git a/core/trace.c b/core/trace.m similarity index 100% rename from core/trace.c rename to core/trace.m diff --git a/core/util.c b/core/util.m similarity index 100% rename from core/util.c rename to core/util.m diff --git a/include/exceptions.h b/include/exceptions.h new file mode 100644 index 0000000000..d872055316 --- /dev/null +++ b/include/exceptions.h @@ -0,0 +1,16 @@ +#ifndef TARANTOOL_EXCEPTIONS_H +#define TARANTOOL_EXCEPTIONS_H + +#include <objc/Object.h> + +@interface TNTException: Object { + const char *reason; +} + ++(id) withReason:(const char *)str; + +-(TNTException *) setReason:(const char *)str; +-(const char *) Reason; +@end + +#endif diff --git a/include/fiber.h b/include/fiber.h index 42871d6251..191bdd8d12 100644 --- a/include/fiber.h +++ b/include/fiber.h @@ -40,8 +40,10 @@ #include <util.h> #include "third_party/queue.h" +#include <exceptions.h> -#define FIBER_EXIT -1 +@interface TNTFiberException: TNTException +@end struct msg { uint32_t sender_fid; @@ -76,9 +78,6 @@ struct fiber { struct ring *inbox; - jmp_buf exc; - const char *errstr; - const char *name; void (*f) (void *); void *f_data; @@ -118,11 +117,11 @@ void unwait(int events); void yield(void); void raise_(int); void fiber_destroy_all(); -#define raise(v, err) \ - ({ \ - say_debug("raise 0x%x/%s at %s:%i", v, err, __FILE__, __LINE__); \ - fiber->errstr = (err); \ - longjmp(fiber->exc, (v)); \ +#define raise(err...) \ + ({ \ + const char *_errstr = err"\0"; \ + say_debug("raise %s at %s:%i", _errstr, __FILE__, __LINE__); \ + @throw [TNTException withReason:_errstr]; \ }) struct msg *read_inbox(void); diff --git a/include/pickle.h b/include/pickle.h index 8a51cde672..9fb718b5c6 100644 --- a/include/pickle.h +++ b/include/pickle.h @@ -28,6 +28,10 @@ #include <stdbool.h> #include <util.h> +#include <exceptions.h> + +@interface TNTPickleException: TNTException +@end struct tbuf; diff --git a/include/tarantool.h b/include/tarantool.h index cc839a8eac..60cdf4032d 100644 --- a/include/tarantool.h +++ b/include/tarantool.h @@ -42,7 +42,6 @@ void mod_exec(char *str, int len, struct tbuf *out); extern struct tarantool_module module; extern struct tarantool_cfg cfg; -extern struct tbuf *cfg_out; extern const char *cfg_filename; extern bool init_storage, booting; extern char *binary_filename; diff --git a/mod/box/CMakeLists.txt b/mod/box/CMakeLists.txt index f92e265ecd..7d0af32b5d 100644 --- a/mod/box/CMakeLists.txt +++ b/mod/box/CMakeLists.txt @@ -1,11 +1,11 @@ -add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/mod/box/memcached.c +add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/mod/silverbox/memcached.m WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND ${RAGEL} -G2 mod/box/memcached.rl -o mod/box/memcached.c - DEPENDS ${CMAKE_SOURCE_DIR}/mod/box/memcached.rl) -# Do not clean memcached.c in 'make clean'. + COMMAND ${RAGEL} -G2 mod/silverbox/memcached.rl -o mod/silverbox/memcached.m + DEPENDS ${CMAKE_SOURCE_DIR}/mod/silverbox/memcached.rl) +# Do not clean memcached.m in 'make clean'. set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM 1) -set_source_files_properties(memcached.c +set_source_files_properties(memcached.m PROPERTIES COMPILE_FLAGS "-Wno-uninitialized") -tarantool_module("box" index.c box.c memcached.c) +tarantool_module("box" index.m box.m memcached.m) diff --git a/mod/box/box.h b/mod/box/box.h index ba2a470b58..5a3de9b17e 100644 --- a/mod/box/box.h +++ b/mod/box/box.h @@ -27,6 +27,18 @@ */ #include <mod/box/index.h> +#include <exceptions.h> +#include <tbuf.h> + +@interface TNTBoxException: TNTException { + u32 value; +} + ++(id) withReason:(const char *)str withValue:(u32)val; + +-(TNTBoxException *) setValue:(u32)val; +-(u32) Value; +@end extern bool box_updates_allowed; void memcached_handler(void * /* data */); @@ -57,7 +69,7 @@ struct box_tuple { } __attribute__((packed)); struct box_txn { - int op; + u16 op; u32 flags; struct namespace *namespace; @@ -69,7 +81,11 @@ struct box_txn { struct box_tuple *tuple; struct box_tuple *lock_tuple; + size_t saved_iov_cnt; + struct tbuf req; + bool in_recover; + bool write_to_wal; }; enum tuple_flags { @@ -117,16 +133,17 @@ enum box_mode { ENUM(messages, MESSAGES); -#define box_raise(n, err) \ - ({ \ - if (n != ERR_CODE_NODE_IS_RO) \ - say_warn("%s/%s", error_codes_strs[(n)], err); \ - raise(n, err); \ +#define box_raise(n, err...) \ + ({ \ + const char *_errstr = err"\0"; \ + if (n != ERR_CODE_NODE_IS_RO) \ + say_warn("%s/%s", error_codes_strs[(n)], _errstr); \ + @throw [TNTBoxException withReason:_errstr withValue:n]; \ }) struct box_txn *txn_alloc(u32 flags); -u32 box_dispatch(struct box_txn *txn, enum box_mode mode, u16 op, - struct tbuf *data); +u32 box_process(struct box_txn *txn, u32 op, enum box_mode mode, struct tbuf *request_data); + void tuple_txn_ref(struct box_txn *txn, struct box_tuple *tuple); void txn_cleanup(struct box_txn *txn); diff --git a/mod/box/box.c b/mod/box/box.m similarity index 89% rename from mod/box/box.c rename to mod/box/box.m index d501e85b5d..2eb6a46ccd 100644 --- a/mod/box/box.c +++ b/mod/box/box.m @@ -81,6 +81,32 @@ struct box_snap_row { u8 data[]; } __attribute__((packed)); +@implementation TNTBoxException ++(id) withReason:(char *)str withValue:(u32)val +{ + return [[self withReason:str] setValue:val]; +} + +-(void) init +{ + [super init]; + + value = ERR_CODE_UNKNOWN_ERROR; +} + +-(TNTBoxException *) setValue:(u32)val +{ + value = val; + + return self; +} + +-(u32) Value +{ + return value; +} +@end + static inline struct box_snap_row * box_snap_row(const struct tbuf *t) { @@ -229,7 +255,7 @@ tuple_txn_ref(struct box_txn *txn, struct box_tuple *tuple) tuple_ref(tuple, +1); } -static int __attribute__((noinline)) +static void __attribute__((noinline)) prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data) { assert(data != NULL); @@ -290,14 +316,19 @@ prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data) index->replace(index, NULL, txn->tuple); } - return -1; + if (!(txn->flags & BOX_QUIET) && !txn->in_recover) { + u32 tuples_affected = 1; + + add_iov_dup(&tuples_affected, sizeof(uint32_t)); + + if (txn->flags & BOX_RETURN_TUPLE) + tuple_add_iov(txn, txn->tuple); + } } static void commit_replace(struct box_txn *txn) { - int tuples_affected = 1; - if (txn->old_tuple != NULL) { foreach_index(txn->n, index) index->replace(index, txn->old_tuple, txn->tuple); @@ -305,14 +336,9 @@ commit_replace(struct box_txn *txn) tuple_ref(txn->old_tuple, -1); } - txn->tuple->flags &= ~GHOST; - tuple_ref(txn->tuple, +1); - - if (!(txn->flags & BOX_QUIET) && !txn->in_recover) { - add_iov_dup(&tuples_affected, sizeof(uint32_t)); - - if (txn->flags & BOX_RETURN_TUPLE) - tuple_add_iov(txn, txn->tuple); + if (txn->tuple != NULL) { + txn->tuple->flags &= ~GHOST; + tuple_ref(txn->tuple, +1); } } @@ -430,7 +456,7 @@ do_field_splice(struct tbuf *field, void *args_data, u32 args_data_size) *field = *new_field; } -static int __attribute__((noinline)) +static void __attribute__((noinline)) prepare_update_fields(struct box_txn *txn, struct tbuf *data) { struct tbuf **fields; @@ -438,6 +464,7 @@ prepare_update_fields(struct box_txn *txn, struct tbuf *data) int i; void *key; u32 op_cnt; + u32 tuples_affected = 1; u32 key_len = read_u32(data); if (key_len != 1) @@ -454,11 +481,11 @@ prepare_update_fields(struct box_txn *txn, struct tbuf *data) txn->old_tuple = txn->index->find(txn->index, key); if (txn->old_tuple == NULL) { - if (!txn->in_recover) { - int tuples_affected = 0; - add_iov_dup(&tuples_affected, sizeof(uint32_t)); - } - return ERR_CODE_OK; + txn->write_to_wal = false; + + tuples_affected = 0; + + goto out; } lock_tuple(txn, txn->old_tuple); @@ -534,7 +561,14 @@ prepare_update_fields(struct box_txn *txn, struct tbuf *data) if (data->len != 0) box_raise(ERR_CODE_ILLEGAL_PARAMS, "can't unpack request"); - return -1; + +out: + if (!(txn->flags & BOX_QUIET) && !txn->in_recover) { + add_iov_dup(&tuples_affected, sizeof(uint32_t)); + + if (txn->flags & BOX_RETURN_TUPLE) + tuple_add_iov(txn, txn->tuple); + } } static void @@ -554,7 +588,7 @@ tuple_add_iov(struct box_txn *txn, struct box_tuple *tuple) } } -static int __attribute__((noinline)) +static void __attribute__((noinline)) process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data) { struct box_tuple *tuple; @@ -573,7 +607,7 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data) /* End the loop if reached the limit. */ if (limit == *found) - goto end; + return; u32 key_len = read_u32(data); void *key = read_field(data); @@ -606,7 +640,7 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data) /* End the loop if reached the limit. */ if (limit == *found) - goto end; + return; u32 key_len = read_u32(data); if (key_len != 1) @@ -629,43 +663,43 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data) if (data->len != 0) box_raise(ERR_CODE_ILLEGAL_PARAMS, "can't unpack request"); - -end: - return ERR_CODE_OK; } -static int __attribute__((noinline)) +static void __attribute__((noinline)) prepare_delete(struct box_txn *txn, void *key) { + u32 tuples_affected = 0; + txn->old_tuple = txn->index->find(txn->index, key); - if (txn->old_tuple == NULL) { - if (!txn->in_recover) { - u32 tuples_affected = 0; - add_iov_dup(&tuples_affected, sizeof(tuples_affected)); - } - return ERR_CODE_OK; - } else { + if (txn->old_tuple == NULL) + txn->write_to_wal = false; + else { tuple_txn_ref(txn, txn->old_tuple); + lock_tuple(txn, txn->old_tuple); + + tuples_affected = 1; } - lock_tuple(txn, txn->old_tuple); - return -1; + if (!(txn->flags & BOX_QUIET) && !txn->in_recover) + add_iov_dup(&tuples_affected, sizeof(tuples_affected)); } static void commit_delete(struct box_txn *txn) { - if (!(txn->flags & BOX_QUIET) && !txn->in_recover) { - int tuples_affected = 1; - add_iov_dup(&tuples_affected, sizeof(tuples_affected)); - } + if (txn->old_tuple == NULL) + return; foreach_index(txn->n, index) index->remove(index, txn->old_tuple); tuple_ref(txn->old_tuple, -1); +} - return; +static bool +op_is_select(u32 op) +{ + return op == SELECT || op == SELECT_LIMIT; } struct box_txn * @@ -674,9 +708,37 @@ txn_alloc(u32 flags) struct box_txn *txn = p0alloc(fiber->pool, sizeof(*txn)); txn->ref_tuples = tbuf_alloc(fiber->pool); txn->flags |= flags; /* note - select will overwrite this flags */ + txn->write_to_wal = true; return txn; } +static void +txn_begin(struct box_txn *txn, enum box_mode mode, u16 op, struct tbuf *data) +{ + txn->saved_iov_cnt = fiber->iov_cnt; + + if (!txn->in_recover) { + if (!op_is_select(op) && (mode == RO || !box_updates_allowed)) { + say_error("can't process %i command on RO port", op); + box_raise(ERR_CODE_NONMASTER); + } + } + + txn->op = op; + txn->req = (struct tbuf){ .data = data->data, .len = data->len }; + txn->n = read_u32(data); + if (txn->n < 0 || txn->n > namespace_count - 1) + box_raise(ERR_CODE_NO_SUCH_NAMESPACE, "bad namespace number"); + txn->index = &namespace[txn->n].index[0]; + + if (!namespace[txn->n].enabled) { + say_warn("namespace %i is not enabled", txn->n); + box_raise(ERR_CODE_NO_SUCH_NAMESPACE, "namespace is not enabled"); + } + + txn->namespace = &namespace[txn->n]; +} + void txn_cleanup(struct box_txn *txn) { @@ -710,14 +772,33 @@ txn_commit(struct box_txn *txn) if (txn->op == 0) return; - say_debug("box_commit(op:%s)", messages_strs[txn->op]); + if (!op_is_select(txn->op)) { + say_debug("box_commit(op:%s)", messages_strs[txn->op]); - unlock_tuples(txn); + if (!txn->in_recover && txn->write_to_wal) { + fiber_peer_name(fiber); /* fill the cookie */ + struct tbuf *t = tbuf_alloc(fiber->pool); + tbuf_append(t, &txn->op, sizeof(txn->op)); + tbuf_append(t, txn->req.data, txn->req.len); - if (txn->op == DELETE) - commit_delete(txn); + i64 lsn = next_lsn(recovery_state, 0); + if (!wal_write(recovery_state, wal_tag, fiber->cookie, lsn, t)) + box_raise(ERR_CODE_UNKNOWN_ERROR); + confirm_lsn(recovery_state, lsn); + } + + unlock_tuples(txn); + + if (txn->op == DELETE) + commit_delete(txn); + else + commit_replace(txn); + } + + if (txn->in_recover) + txn_cleanup(txn); else - commit_replace(txn); + fiber_register_cleanup((fiber_cleanup_handler)txn_cleanup, txn); } static void @@ -725,64 +806,31 @@ txn_abort(struct box_txn *txn) { if (txn->op == 0) return; - say_debug("box_rollback(op:%s)", messages_strs[txn->op]); - unlock_tuples(txn); + fiber->iov_cnt = txn->saved_iov_cnt; - if (txn->op == DELETE) - return; + if (!op_is_select(txn->op)) { + say_debug("box_rollback(op:%s)", messages_strs[txn->op]); - if (txn->op == INSERT) - rollback_replace(txn); -} + unlock_tuples(txn); -static bool -op_is_select(u32 op) -{ - return op == SELECT || op == SELECT_LIMIT; + if (txn->op == INSERT) + rollback_replace(txn); + } + + txn_cleanup(txn); } -u32 -box_dispatch(struct box_txn *txn, enum box_mode mode, u16 op, - struct tbuf *data) +static void +box_dispach(struct box_txn *txn, struct tbuf *data) { u32 cardinality; - int ret_code; - struct tbuf req = { .data = data->data, .len = data->len }; - int saved_iov_cnt = fiber->iov_cnt; - ev_tstamp start = ev_now(), stop; - - if ((ret_code = setjmp(fiber->exc)) != 0) - goto abort; - - say_debug("box_dispatch(%i)", op); - - if (!txn->in_recover) { - if (!op_is_select(op) && (mode == RO || !box_updates_allowed)) { - say_error("can't process %i command on RO port", op); - return ERR_CODE_NONMASTER; - } - - fiber_register_cleanup((void *)txn_cleanup, txn); - } - - txn->op = op; - txn->n = read_u32(data); - if (txn->n < 0 || txn->n > namespace_count - 1) - box_raise(ERR_CODE_NO_SUCH_NAMESPACE, "bad namespace number"); - txn->index = &namespace[txn->n].index[0]; - - if (!namespace[txn->n].enabled) { - say_warn("namespace %i is not enabled", txn->n); - box_raise(ERR_CODE_NO_SUCH_NAMESPACE, "namespace is not enabled"); - } - - txn->namespace = &namespace[txn->n]; - void *key; u32 key_len; - switch (op) { + say_debug("box_dispach(%i)", txn->op); + + switch (txn->op) { case INSERT: txn->flags = read_u32(data); cardinality = read_u32(data); @@ -790,8 +838,7 @@ box_dispatch(struct box_txn *txn, enum box_mode mode, u16 op, && namespace[txn->n].cardinality != cardinality) box_raise(ERR_CODE_ILLEGAL_PARAMS, "tuple cardinality must match namespace cardinality"); - ret_code = prepare_replace(txn, cardinality, data); - stat_collect(stat_base, op, 1); + prepare_replace(txn, cardinality, data); break; case DELETE: @@ -803,8 +850,7 @@ box_dispatch(struct box_txn *txn, enum box_mode mode, u16 op, if (data->len != 0) box_raise(ERR_CODE_ILLEGAL_PARAMS, "can't unpack request"); - ret_code = prepare_delete(txn, key); - stat_collect(stat_base, op, 1); + prepare_delete(txn, key); break; case SELECT:{ @@ -818,49 +864,19 @@ box_dispatch(struct box_txn *txn, enum box_mode mode, u16 op, if (txn->index->key_cardinality == 0) box_raise(ERR_CODE_ILLEGAL_PARAMS, "index is invalid"); - stat_collect(stat_base, op, 1); - return process_select(txn, limit, offset, data); + process_select(txn, limit, offset, data); + break; } case UPDATE_FIELDS: txn->flags = read_u32(data); - stat_collect(stat_base, op, 1); - ret_code = prepare_update_fields(txn, data); + prepare_update_fields(txn, data); break; default: - say_error("box_dispatch: unsupported command = %" PRIi32 "", op); - return ERR_CODE_ILLEGAL_PARAMS; + say_error("silverbox_dispach: unsupported command = %" PRIi32 "", txn->op); + box_raise(ERR_CODE_ILLEGAL_PARAMS); } - - if (ret_code == -1) { - if (!txn->in_recover) { - fiber_peer_name(fiber); /* fill the cookie */ - struct tbuf *t = tbuf_alloc(fiber->pool); - tbuf_append(t, &op, sizeof(op)); - tbuf_append(t, req.data, req.len); - - i64 lsn = next_lsn(recovery_state, 0); - if (!wal_write(recovery_state, wal_tag, fiber->cookie, lsn, t)) { - ret_code = ERR_CODE_UNKNOWN_ERROR; - goto abort; - } - confirm_lsn(recovery_state, lsn); - } - txn_commit(txn); - - stop = ev_now(); - if (stop - start > cfg.too_long_threshold) - say_warn("too long %s: %.3f sec", messages_strs[op], stop - start); - return 0; - } - - return ret_code; - - abort: - fiber->iov_cnt = saved_iov_cnt; - txn_abort(txn); - return ret_code; } static int @@ -970,75 +986,6 @@ box_snap_reader(FILE *f, struct palloc_pool *pool) return convert_to_v11(row, snap_tag, default_cookie, 0); } -static int -snap_apply(struct box_txn *txn, struct tbuf *t) -{ - struct box_snap_row *row; - - read_u64(t); /* drop cookie */ - - row = box_snap_row(t); - txn->n = row->namespace; - - if (!namespace[txn->n].enabled) { - say_error("namespace %i is not configured", txn->n); - return -1; - } - txn->index = &namespace[txn->n].index[0]; - assert(txn->index->key_cardinality > 0); - - struct tbuf *b = palloc(fiber->pool, sizeof(*b)); - b->data = row->data; - b->len = row->data_size; - - if (prepare_replace(txn, row->tuple_size, b) != -1) { - say_error("unable prepare"); - return -1; - } - - txn->op = INSERT; - txn_commit(txn); - return 0; -} - -static int -wal_apply(struct box_txn *txn, struct tbuf *t) -{ - read_u64(t); /* drop cookie */ - - u16 type = read_u16(t); - if (box_dispatch(txn, RW, type, t) != 0) - return -1; - - txn_cleanup(txn); - return 0; -} - -static int -recover_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t) -{ - struct box_txn *txn = txn_alloc(0); - int result = -1; - txn->in_recover = true; - - /* drop wal header */ - if (tbuf_peek(t, sizeof(struct row_v11)) == NULL) - return -1; - - u16 tag = read_u16(t); - if (tag == wal_tag) { - result = wal_apply(txn, t); - } else if (tag == snap_tag) { - result = snap_apply(txn, t); - } else { - say_error("unknown row tag: %i", (int)tag); - return -1; - } - - txn_cleanup(txn); - return result; -} - static int snap_print(struct recovery_state *r __attribute__((unused)), struct tbuf *t) { @@ -1150,7 +1097,7 @@ custom_init(void) else if (strcmp(cfg_key_field->type, "NUM64") == 0) index->key_field[k].type = NUM64; else if (strcmp(cfg_key_field->type, "STR") == 0) - index->key_field[k].type = STR; + index->key_field[k].type = STRING; else panic("(namespace = %" PRIu32 " index = %" PRIu32 ") " "unknown field data type: `%s'", @@ -1208,16 +1155,104 @@ custom_init(void) } } +u32 +box_process(struct box_txn *txn, u32 op, enum box_mode mode, struct tbuf *request_data) +{ + ev_tstamp start = ev_now(), stop; + + if (!txn->in_recover) + stat_collect(stat_base, txn->op, 1); + + @try { + txn_begin(txn, mode, op, request_data); + box_dispach(txn, request_data); + txn_commit(txn); + + return ERR_CODE_OK; + } + @catch (TNTPickleException *e) { + txn_abort(txn); + + say_debug("catch exception: %s", [e Reason]); + + return ERR_CODE_UNKNOWN_ERROR; + } + @catch (TNTBoxException *e) { + txn_abort(txn); + + say_debug("catch exception: 0x%x/%s", [e Value], [e Reason]); + + return [e Value]; + } + @catch (id e) { + txn_abort(txn); + + @throw; + } + @finally { + stop = ev_now(); + if (!txn->in_recover && + stop - start > cfg.too_long_threshold) + say_warn("too long %s: %.3f sec", messages_strs[txn->op], stop - start); + } +} + static u32 box_process_ro(u32 op, struct tbuf *request_data) { - return box_dispatch(txn_alloc(0), RO, op, request_data); + return box_process(txn_alloc(0), op, RO, request_data); } static u32 -box_process(u32 op, struct tbuf *request_data) +box_process_rw(u32 op, struct tbuf *request_data) { - return box_dispatch(txn_alloc(0), RW, op, request_data); + return box_process(txn_alloc(0), op, RW, request_data); +} + +static struct tbuf * +convert_snap_row_to_wal(struct tbuf *t) +{ + struct tbuf *r = tbuf_alloc(fiber->pool); + struct box_snap_row *row = box_snap_row(t); + u16 op = INSERT; + u32 flags = 0; + + tbuf_append(r, &op, sizeof(op)); + tbuf_append(r, &row->namespace, sizeof(row->namespace)); + tbuf_append(r, &flags, sizeof(flags)); + tbuf_append(r, &row->tuple_size, sizeof(row->tuple_size)); + tbuf_append(r, row->data, row->data_size); + + return r; +} + +static int +recover_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t) +{ + struct box_txn *txn = txn_alloc(0); + u16 op; + + txn->in_recover = true; + + /* drop wal header */ + if (tbuf_peek(t, sizeof(struct row_v11)) == NULL) + return -1; + + u16 tag = read_u16(t); + read_u64(t); /* drop cookie */ + if (tag == snap_tag) + t = convert_snap_row_to_wal(t); + else if (tag != wal_tag) { + say_error("unknown row tag: %i", (int)tag); + return -1; + } + + op = read_u16(t); + + if (box_process(txn, op, RW, t) != ERR_CODE_OK) + return -1; + + return 0; } static void @@ -1389,7 +1424,7 @@ mod_init(void) box_process_ro, NULL); if (cfg.primary_port != 0) - fiber_server(tcp_server, cfg.primary_port, iproto_interact, box_process, + fiber_server(tcp_server, cfg.primary_port, iproto_interact, box_process_rw, box_bound_to_primary); } diff --git a/mod/box/index.h b/mod/box/index.h index 7c259d6e69..7a0a2d15c0 100644 --- a/mod/box/index.h +++ b/mod/box/index.h @@ -49,7 +49,7 @@ struct field { }; }; -enum field_data_type { NUM, NUM64, STR }; +enum field_data_type { NUM, NUM64, STRING }; struct tree_index_member { struct box_tuple *tuple; diff --git a/mod/box/index.c b/mod/box/index.m similarity index 99% rename from mod/box/index.c rename to mod/box/index.m index 8c7a54aecb..9f235cbe3c 100644 --- a/mod/box/index.c +++ b/mod/box/index.m @@ -80,7 +80,7 @@ field_compare(struct field *f1, struct field *f2, enum field_data_type type) assert(f1->len == sizeof(f1->u64)); return f1->u64 >f2->u64 ? 1 : f1->u64 == f2->u64 ? 0 : -1; - } else if (type == STR) { + } else if (type == STRING) { i32 cmp; void *f1_data, *f2_data; @@ -451,7 +451,7 @@ validate_indeces(struct box_txn *txn) if (namespace[txn->n].index[1].key_cardinality != 0) { /* there is more then one index */ foreach_index(txn->n, index) { for (u32 f = 0; f < index->key_cardinality; ++f) { - if (index->key_field[f].type == STR) + if (index->key_field[f].type == STRING) continue; void *field = tuple_field(txn->tuple, index->key_field[f].fieldno); diff --git a/mod/box/memcached.c b/mod/box/memcached.m similarity index 99% rename from mod/box/memcached.c rename to mod/box/memcached.m index be8efa19f3..06a842f67f 100644 --- a/mod/box/memcached.c +++ b/mod/box/memcached.m @@ -120,7 +120,7 @@ store(struct box_txn *txn, void *key, u32 exptime, u32 flags, u32 bytes, u8 *dat int key_len = load_varint32(&key); say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64, key_len, key_len, (u8 *)key, exptime, flags, cas); - return box_dispatch(txn, RW, INSERT, req); /* FIXME: handle RW/RO */ + return box_process(txn, RW, INSERT, req); /* FIXME: handle RW/RO */ } static int @@ -133,7 +133,7 @@ delete(struct box_txn *txn, void *key) tbuf_append(req, &key_len, sizeof(key_len)); tbuf_append_field(req, key); - return box_dispatch(txn, RW, DELETE, req); + return box_process(txn, RW, DELETE, req); } static struct box_tuple * diff --git a/mod/box/memcached.rl b/mod/box/memcached.rl index a7e0259d93..219a6e832d 100644 --- a/mod/box/memcached.rl +++ b/mod/box/memcached.rl @@ -111,7 +111,7 @@ store(struct box_txn *txn, void *key, u32 exptime, u32 flags, u32 bytes, u8 *dat int key_len = load_varint32(&key); say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64, key_len, key_len, (u8 *)key, exptime, flags, cas); - return box_dispatch(txn, RW, INSERT, req); /* FIXME: handle RW/RO */ + return box_process(txn, RW, INSERT, req); /* FIXME: handle RW/RO */ } static int @@ -124,7 +124,7 @@ delete(struct box_txn *txn, void *key) tbuf_append(req, &key_len, sizeof(key_len)); tbuf_append_field(req, key); - return box_dispatch(txn, RW, DELETE, req); + return box_process(txn, RW, DELETE, req); } static struct box_tuple * diff --git a/mod/feeder/CMakeLists.txt b/mod/feeder/CMakeLists.txt index 8e7914935c..4852343fe7 100644 --- a/mod/feeder/CMakeLists.txt +++ b/mod/feeder/CMakeLists.txt @@ -1 +1 @@ -tarantool_module("feeder" feeder.c) +tarantool_module("feeder" feeder.m) diff --git a/mod/feeder/feeder.c b/mod/feeder/feeder.m similarity index 100% rename from mod/feeder/feeder.c rename to mod/feeder/feeder.m -- GitLab