From 4cc6b8a8ca4a982b8b6a521b40abffbcd9853807 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Tue, 20 Aug 2013 21:20:17 +0400 Subject: [PATCH] Rewrite --init-storage: dump a compiled-in blob in it Rewrite --init-storage to dump a compiled-in blob instead of firing off the entire save snapshot machinery. This should simplify bootstrap in presence of system spaces: there's going to be no need to implement the code which creates system, they will be created simply by recovery from a snapshot. --- cmake/utils.cmake | 16 ++++++++++ extra/CMakeLists.txt | 1 + extra/bin2c.c | 73 +++++++++++++++++++++++++++++++++++++++++++ include/box/box.h | 8 +---- include/recovery.h | 5 +-- src/CMakeLists.txt | 3 ++ src/bootstrap.snap | Bin 0 -> 15 bytes src/box/box.cc | 11 ++----- src/box/key_def.h | 8 +++++ src/recovery.cc | 6 ++-- src/replication.cc | 2 +- src/tarantool.cc | 40 +++++++++++++----------- test/box/args.result | 2 -- 13 files changed, 131 insertions(+), 44 deletions(-) create mode 100644 extra/bin2c.c create mode 100644 src/bootstrap.snap diff --git a/cmake/utils.cmake b/cmake/utils.cmake index e78e4bf7d9..c6a24f1a05 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -55,3 +55,19 @@ function(lua_source varname filename) set(var ${${varname}}) set(${varname} ${var} ${dstfile} PARENT_SCOPE) endfunction() + +function(bin_source varname srcfile dstfile) + set (tmpfile "${CMAKE_CURRENT_BINARY_DIR}/${dstfile}.tmp") + get_filename_component(module ${dstfile} NAME_WE) + + ADD_CUSTOM_COMMAND(OUTPUT ${dstfile} + COMMAND ${ECHO} 'const unsigned char ${module}_bin[] = {' > ${tmpfile} + COMMAND ${CMAKE_BINARY_DIR}/extra/bin2c ${srcfile} >> ${tmpfile} + COMMAND ${ECHO} '}\;' >> ${tmpfile} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${tmpfile} ${dstfile} + COMMAND ${CMAKE_COMMAND} -E remove ${tmpfile} + DEPENDS ${srcfile} bin2c) + + set(var ${${varname}}) + set(${varname} ${var} ${dstfile} PARENT_SCOPE) +endfunction() diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index 05cd374540..58b3eb54c0 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -26,3 +26,4 @@ endif() configure_file(rpm.spec.in rpm.spec @ONLY) add_executable(txt2c txt2c.c) +add_executable(bin2c bin2c.c) diff --git a/extra/bin2c.c b/extra/bin2c.c new file mode 100644 index 0000000000..9776d55224 --- /dev/null +++ b/extra/bin2c.c @@ -0,0 +1,73 @@ +/* + * txt2c: Converts text files to C strings + * + * Compile with: + * gcc txt2cs.c -o txt2cs + * + * Public domain. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int main(int argc, char** argv) { + const char *prefix = ""; + const char *suffix = "\n"; + int no_quote = 0; /* if 1, do not prepend and append quotation marks (") */ + FILE *in = stdin; + FILE *out = stdout; + + int c; + while ((c = getopt(argc, argv, "np:s:h")) != -1) { + switch (c) { + case 'p': + prefix = optarg; + break; + case 's': + suffix = optarg; + break; + case 'h': + printf("Usage: %s [-n] [-p prefix] [-s suffix] [infile] [outfile]\n", argv[0]); + exit(0); + break; + } + } + + if (optind < argc) { + if (strcmp(argv[optind], "-") != 0) { + if (!(in = fopen(argv[optind], "r"))) { + fprintf(stderr, "Can't open %s\n", + argv[optind]); + perror(argv[0]); + exit(1); + } + } + if (optind + 1 < argc) { + if (strcmp(argv[optind + 1], "-") != 0) { + if (!(out = fopen(argv[optind + 1], "w"))) { + fprintf(stderr, "Can't open %s\n", + argv[optind + 1]); + perror(argv[0]); + exit(1); + } + } + } + } + + fputs(prefix, out); + int col = 1; + + while ((c = fgetc(in)) != -1) { + if (col >= 78 - 6) + { + fputs("\n", out); + col = 0; + } + fprintf(out, " 0x%.2x,", c); + col += 6; + } + fputs(suffix, out); + return 0; +} + diff --git a/include/box/box.h b/include/box/box.h index e366696013..a019d61154 100644 --- a/include/box/box.h +++ b/include/box/box.h @@ -49,7 +49,7 @@ struct tarantool_cfg; struct lua_State; /** To be called at program start. */ -void box_init(bool init_storage); +void box_init(); /** To be called at program end. */ void box_free(void); @@ -96,12 +96,6 @@ const char *box_status(void); void box_leave_local_standby_mode(void *data __attribute__((unused))); -enum { - BOX_SPACE_MAX = UINT32_MAX, - BOX_INDEX_MAX = 10, - BOX_FIELD_MAX = UINT32_MAX -}; - #if defined(__cplusplus) } #endif /* defined(__cplusplus) */ diff --git a/include/recovery.h b/include/recovery.h index 1757593728..816f4f2d56 100644 --- a/include/recovery.h +++ b/include/recovery.h @@ -41,8 +41,6 @@ extern "C" { struct fiber; struct tbuf; -#define RECOVER_READONLY 1 - typedef int (row_handler)(void *, const char *, uint32_t); /** A "condition variable" that allows fibers to wait when a given @@ -100,7 +98,6 @@ struct recovery_state { void *row_handler_param; int snap_io_rate_limit; int rows_per_wal; - int flags; double wal_fsync_delay; struct wait_lsn wait_lsn; enum wal_mode wal_mode; @@ -112,7 +109,7 @@ extern struct recovery_state *recovery_state; void recovery_init(const char *snap_dirname, const char *xlog_dirname, row_handler row_handler, void *row_handler_param, - int rows_per_wal, int flags); + int rows_per_wal); void recovery_update_mode(struct recovery_state *r, const char *wal_mode, double fsync_delay); void recovery_update_io_rate_limit(struct recovery_state *r, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f650d5179..76ddcbd2cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,8 @@ set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM true) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src/lua) set(lua_sources) lua_source(lua_sources lua/uuid.lua) +set(bin_sources) +bin_source(bin_sources bootstrap.snap bootstrap.h) add_custom_target(generate_lua_sources WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/box @@ -120,6 +122,7 @@ set (common_sources lua/session.cc lua/cjson.cc ${lua_sources} + ${bin_sources} ) if (ENABLE_TRACE) diff --git a/src/bootstrap.snap b/src/bootstrap.snap new file mode 100644 index 0000000000000000000000000000000000000000..8f8d8ac5b4c8634e2099b9d6671560db48518960 GIT binary patch literal 15 WcmWIca}3}z&@(jT;*wjvRsaASSp$~< literal 0 HcmV?d00001 diff --git a/src/box/box.cc b/src/box/box.cc index c3569e67bf..901fa3cafe 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -316,7 +316,7 @@ box_free(void) } void -box_init(bool init_storage) +box_init() { title("loading"); atexit(box_free); @@ -328,17 +328,12 @@ box_init(bool init_storage) /* recovery initialization */ recovery_init(cfg.snap_dir, cfg.wal_dir, - recover_row, NULL, - cfg.rows_per_wal, - init_storage ? RECOVER_READONLY : 0); + recover_row, NULL, cfg.rows_per_wal); recovery_update_io_rate_limit(recovery_state, cfg.snap_io_rate_limit); recovery_setup_panic(recovery_state, cfg.panic_on_snap_error, cfg.panic_on_wal_error); stat_base = stat_register(requests_strs, requests_MAX); - if (init_storage) - return; - begin_build_primary_indexes(); recover_snap(recovery_state); end_build_primary_indexes(); @@ -383,7 +378,7 @@ snapshot_space(struct space *sp, void *udata) struct tuple *tuple; struct snapshot_space_param *ud = (struct snapshot_space_param *) udata; Index *pk = space_index(sp, 0); - struct iterator *it = pk->position();; + struct iterator *it = pk->position(); pk->initIterator(it, ITER_ALL, NULL, 0); while ((tuple = it->next(it))) diff --git a/src/box/key_def.h b/src/box/key_def.h index 9bb22513f1..03939f7e8e 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -29,6 +29,14 @@ * SUCH DAMAGE. */ #include "tarantool/util.h" +#include "rlist.h" + +enum { + BOX_SPACE_MAX = INT32_MAX, + BOX_INDEX_MAX = 10, + BOX_FIELD_MAX = UINT32_MAX +}; + /* * Possible field data types. Can't use STRS/ENUM macros for them, * since there is a mismatch between enum name (STRING) and type diff --git a/src/recovery.cc b/src/recovery.cc index 4e85b95ddc..f1d5eaf271 100644 --- a/src/recovery.cc +++ b/src/recovery.cc @@ -202,7 +202,7 @@ recovery_stop_local(struct recovery_state *r); void recovery_init(const char *snap_dirname, const char *wal_dirname, row_handler row_handler, void *row_handler_param, - int rows_per_wal, int flags) + int rows_per_wal) { assert(recovery_state == NULL); recovery_state = (struct recovery_state *) p0alloc(eter_pool, sizeof(struct recovery_state)); @@ -222,7 +222,6 @@ recovery_init(const char *snap_dirname, const char *wal_dirname, r->wal_dir->open_wflags = r->wal_mode == WAL_FSYNC ? WAL_SYNC_FLAG : 0; r->rows_per_wal = rows_per_wal; wait_lsn_clear(&r->wait_lsn); - r->flags = flags; } void @@ -564,8 +563,7 @@ recovery_finalize(struct recovery_state *r) log_io_close(&r->current_wal); } - if ((r->flags & RECOVER_READONLY) == 0) - wal_writer_start(r); + wal_writer_start(r); } diff --git a/src/replication.cc b/src/replication.cc index 747a7d4ddc..fbd4bb3568 100644 --- a/src/replication.cc +++ b/src/replication.cc @@ -683,7 +683,7 @@ replication_relay_loop(int client_sock) /* Initialize the recovery process */ recovery_init(cfg.snap_dir, cfg.wal_dir, replication_relay_send_row, (void *)(intptr_t) client_sock, - INT32_MAX, RECOVER_READONLY); + INT32_MAX); /* * Note that recovery starts with lsn _NEXT_ to * the confirmed one. diff --git a/src/tarantool.cc b/src/tarantool.cc index c188064b0c..8e36e525c5 100644 --- a/src/tarantool.cc +++ b/src/tarantool.cc @@ -52,6 +52,7 @@ #include <iproto.h> #include "mutex.h" #include <recovery.h> +#include "log_io.h" #include <crc32.h> #include <palloc.h> #include <salloc.h> @@ -69,6 +70,7 @@ extern "C" { #include "memcached.h" #include "session.h" #include "box/box.h" +#include "bootstrap.h" #include "scoped_guard.h" @@ -619,20 +621,26 @@ tarantool_free(void) #endif } -static void -initialize_minimal() -{ - if (!salloc_init(64 * 1000 * 1000, 4, 2)) - panic_syserror("can't initialize slab allocator"); - fiber_init(); - coeio_init(); -} - -/** Callback of snapshot_save() when doing --init-storage */ +/** Create the initial snapshot file in the storage. */ void -init_storage(struct log_io * /* l */, struct fio_batch * /* batch */) +init_storage() { - /* Nothing. */ + struct log_dir dir = snap_dir; + dir.dirname = cfg.snap_dir; + const char *filename = format_filename(&dir, 1 /* lsn */, NONE); + int fd = open(filename, O_EXCL|O_CREAT|O_WRONLY, dir.mode); + say_info("saving snapshot `%s'", filename); + if (fd == -1) { + panic_syserror("failed to open snapshot file `%s' for " + "writing", filename); + } + if (write(fd, bootstrap_bin, sizeof(bootstrap_bin)) != + sizeof(bootstrap_bin)) { + panic_syserror("failed to write to snapshot file `%s'", + filename); + } + close(fd); + say_info("done"); } int @@ -803,11 +811,7 @@ main(int argc, char **argv) } if (gopt(opt, 'I')) { - initialize_minimal(); - tarantool_L = tarantool_lua_init(); /* box.space[] */ - box_init(true); - set_lsn(recovery_state, 1); - snapshot_save(recovery_state, init_storage); + init_storage(); exit(EXIT_SUCCESS); } @@ -851,7 +855,7 @@ main(int argc, char **argv) try { tarantool_L = tarantool_lua_init(); - box_init(false); + box_init(); atexit(tarantool_lua_free); memcached_init(cfg.bind_ipaddr, cfg.memcached_port); tarantool_lua_load_cfg(tarantool_L, &cfg); diff --git a/test/box/args.result b/test/box/args.result index 5d0b6846ea..5f7b4bedf6 100644 --- a/test/box/args.result +++ b/test/box/args.result @@ -95,8 +95,6 @@ CXX_FLAGS: flags # can be relative to work_dir. tarantool_box --config=bug726778.cfg --init-storage -tarantool_box: space 0 successfully configured -tarantool_box: creating `snapshots/00000000000000000001.snap.inprogress' tarantool_box: saving snapshot `snapshots/00000000000000000001.snap' tarantool_box: done -- GitLab