From 10f492857d99ca7e4bf5ddc0ad20d2caf8e35956 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja.osipov@gmail.com> Date: Wed, 15 Jun 2011 13:48:51 +0400 Subject: [PATCH] Merge master -> box-switch_mode --- README | 6 +- cfg/core_cfg.cfg_tmpl | 13 +- cfg/tarantool_feeder_cfg.cfg | 13 +- cfg/tarantool_feeder_cfg.h | 17 +- {mod/box/client => connector}/perl/MANIFEST | 0 .../box/client => connector}/perl/Makefile.PL | 0 .../perl/lib/MR/IProto.pm | 0 .../perl/lib/MR/SilverBox.pm | 0 .../perl/lib/MR/Storage/Const.pm | 0 {mod/box => connector/perl}/t/TBox.pm | 0 {mod/box => connector/perl}/t/box.pl | 0 {mod/box => connector/perl}/t/box_tree.pl | 0 {mod/box/client => connector}/ruby/README | 0 {mod/box/client => connector}/ruby/box.rb | 0 {mod/box/client => connector}/ruby/iproto.rb | 0 core/admin.m | 7 +- core/admin.rl | 7 +- core/log_io.m | 2 +- core/salloc.m | 6 +- core/tbuf.m | 12 + doc/developer/CMakeLists.txt | 10 +- doc/developer/developer.xml | 41 +- doc/sql.txt | 53 ++ doc/user/CMakeLists.txt | 41 +- doc/user/configuration-reference.xml | 685 +++++++++++++++++- doc/user/connectors.xml | 265 +++++++ doc/user/data-model.xml | 2 +- doc/user/errcode.xml | 77 ++ doc/user/html-highlight.xsl | 73 ++ doc/user/language-reference.xml | 298 +++++++- doc/user/namespace.xml | 108 +++ doc/user/preface.xml | 17 +- doc/user/proctitle.xml | 74 ++ doc/user/replication.xml | 164 +++++ doc/user/target.db | 2 +- doc/user/tnt-fo.xsl | 14 + doc/user/tnt-html.xsl | 25 +- doc/user/tnt.css | 10 + doc/user/tutorial.xml | 14 +- doc/user/user.xml | 58 +- include/errcode.h | 21 +- include/tbuf.h | 10 + mod/box/box.m | 28 +- mod/box/box_cfg.cfg_tmpl | 33 +- mod/box/index.m | 2 +- mod/feeder/feeder.m | 4 +- test/box/sql.result | 8 + test/box/sql.test | 6 + test/lib/tarantool_server.py | 2 +- third_party/proctitle.c | 14 +- 50 files changed, 2051 insertions(+), 191 deletions(-) rename {mod/box/client => connector}/perl/MANIFEST (100%) mode change 100755 => 100644 rename {mod/box/client => connector}/perl/Makefile.PL (100%) mode change 100755 => 100644 rename {mod/box/client => connector}/perl/lib/MR/IProto.pm (100%) rename {mod/box/client => connector}/perl/lib/MR/SilverBox.pm (100%) rename {mod/box/client => connector}/perl/lib/MR/Storage/Const.pm (100%) rename {mod/box => connector/perl}/t/TBox.pm (100%) rename {mod/box => connector/perl}/t/box.pl (100%) rename {mod/box => connector/perl}/t/box_tree.pl (100%) rename {mod/box/client => connector}/ruby/README (100%) rename {mod/box/client => connector}/ruby/box.rb (100%) rename {mod/box/client => connector}/ruby/iproto.rb (100%) create mode 100644 doc/sql.txt create mode 100644 doc/user/connectors.xml create mode 100644 doc/user/errcode.xml create mode 100644 doc/user/html-highlight.xsl create mode 100644 doc/user/namespace.xml create mode 100644 doc/user/proctitle.xml create mode 100644 doc/user/replication.xml create mode 100644 doc/user/tnt-fo.xsl diff --git a/README b/README index acbc1529f3..bb01f41d7c 100644 --- a/README +++ b/README @@ -17,7 +17,11 @@ Caveats: COMPILATION AND INSTALL -Tarantool uses CMake for configuration management. +Tarantool is written in C and Objective C. +To build, you will need GCC Objective C frontend or +Apple CLang compiler. + +CMake is used for configuration management. 3 standard CMake build types are supported: * Debug -- used by project maintainers * RelWithDebugInfo -- the most common release configuration, diff --git a/cfg/core_cfg.cfg_tmpl b/cfg/core_cfg.cfg_tmpl index e316da8863..ca18e226b7 100644 --- a/cfg/core_cfg.cfg_tmpl +++ b/cfg/core_cfg.cfg_tmpl @@ -2,6 +2,7 @@ username=NULL, ro # save core on abort/assert +# deprecated; use ulimit instead coredump=0, ro # admin port @@ -11,11 +12,11 @@ admin_port=0, ro # Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5 log_level=4 -# Size of slab arena in GiBs +# Size of slab arena in GB slab_alloc_arena=1.0, ro # Size of minimal allocation unit slab_alloc_minimal=64, ro -# Growth factor, each subsecuent unit size is factor * prev unit size +# Growth factor, each subsequent unit size is factor * prev unit size slab_alloc_factor=2.0, ro # working directory (daemon will chdir(2) to it) @@ -25,15 +26,15 @@ work_dir=NULL, ro pid_file="tarantool.pid", ro # logger command will be executed via /bin/sh -c {} -# example: 'exec cronolog /var/log/taranul/%Y-%m/%Y-%m-%d/tarantool.log' -# example: 'exec extra/logger.pl /var/log/taranul/tarantool.log' +# example: 'exec cronolog /var/log/tarantool/%Y-%m/%Y-%m-%d/tarantool.log' +# example: 'exec extra/logger.pl /var/log/tarantool/tarantool.log' # when logger is not configured all logging going to STDERR logger=NULL, ro -# make logging nonblocking, this potentially can loss some logging data +# make logging nonblocking, this potentially can lose some logging data logger_nonblock=1, ro -# delay between loop iteraions +# delay between loop iterations io_collect_interval=0.0, ro # size of listen backlog diff --git a/cfg/tarantool_feeder_cfg.cfg b/cfg/tarantool_feeder_cfg.cfg index f6c7690bdd..c8407c3fb5 100644 --- a/cfg/tarantool_feeder_cfg.cfg +++ b/cfg/tarantool_feeder_cfg.cfg @@ -3,6 +3,7 @@ username = NULL # save core on abort/assert +# deprecated; use ulimit instead coredump = 0 # admin port @@ -12,13 +13,13 @@ admin_port = 0 # Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5 log_level = 4 -# Size of slab arena in GiBs +# Size of slab arena in GB slab_alloc_arena = 1 # Size of minimal allocation unit slab_alloc_minimal = 64 -# Growth factor, each subsecuent unit size is factor * prev unit size +# Growth factor, each subsequent unit size is factor * prev unit size slab_alloc_factor = 2 # working directory (daemon will chdir(2) to it) @@ -28,15 +29,15 @@ work_dir = NULL pid_file = "tarantool.pid" # logger command will be executed via /bin/sh -c {} -# example: 'exec cronolog /var/log/taranul/%Y-%m/%Y-%m-%d/tarantool.log' -# example: 'exec extra/logger.pl /var/log/taranul/tarantool.log' +# example: 'exec cronolog /var/log/tarantool/%Y-%m/%Y-%m-%d/tarantool.log' +# example: 'exec extra/logger.pl /var/log/tarantool/tarantool.log' # when logger is not configured all logging going to STDERR logger = NULL -# make logging nonblocking, this potentially can loss some logging data +# make logging nonblocking, this potentially can lose some logging data logger_nonblock = 1 -# delay between loop iteraions +# delay between loop iterations io_collect_interval = 0 # size of listen backlog diff --git a/cfg/tarantool_feeder_cfg.h b/cfg/tarantool_feeder_cfg.h index 8296b42de4..5ac2d0a5f3 100644 --- a/cfg/tarantool_feeder_cfg.h +++ b/cfg/tarantool_feeder_cfg.h @@ -15,7 +15,10 @@ typedef struct tarantool_cfg { /* username to switch to */ char* username; - /* save core on abort/assert */ + /* + * save core on abort/assert + * deprecated; use ulimit instead + */ int32_t coredump; /* @@ -27,13 +30,13 @@ typedef struct tarantool_cfg { /* Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5 */ int32_t log_level; - /* Size of slab arena in GiBs */ + /* Size of slab arena in GB */ double slab_alloc_arena; /* Size of minimal allocation unit */ int32_t slab_alloc_minimal; - /* Growth factor, each subsecuent unit size is factor * prev unit size */ + /* Growth factor, each subsequent unit size is factor * prev unit size */ double slab_alloc_factor; /* working directory (daemon will chdir(2) to it) */ @@ -44,16 +47,16 @@ typedef struct tarantool_cfg { /* * logger command will be executed via /bin/sh -c {} - * example: 'exec cronolog /var/log/taranul/%Y-%m/%Y-%m-%d/tarantool.log' - * example: 'exec extra/logger.pl /var/log/taranul/tarantool.log' + * example: 'exec cronolog /var/log/tarantool/%Y-%m/%Y-%m-%d/tarantool.log' + * example: 'exec extra/logger.pl /var/log/tarantool/tarantool.log' * when logger is not configured all logging going to STDERR */ char* logger; - /* make logging nonblocking, this potentially can loss some logging data */ + /* make logging nonblocking, this potentially can lose some logging data */ int32_t logger_nonblock; - /* delay between loop iteraions */ + /* delay between loop iterations */ double io_collect_interval; /* size of listen backlog */ diff --git a/mod/box/client/perl/MANIFEST b/connector/perl/MANIFEST old mode 100755 new mode 100644 similarity index 100% rename from mod/box/client/perl/MANIFEST rename to connector/perl/MANIFEST diff --git a/mod/box/client/perl/Makefile.PL b/connector/perl/Makefile.PL old mode 100755 new mode 100644 similarity index 100% rename from mod/box/client/perl/Makefile.PL rename to connector/perl/Makefile.PL diff --git a/mod/box/client/perl/lib/MR/IProto.pm b/connector/perl/lib/MR/IProto.pm similarity index 100% rename from mod/box/client/perl/lib/MR/IProto.pm rename to connector/perl/lib/MR/IProto.pm diff --git a/mod/box/client/perl/lib/MR/SilverBox.pm b/connector/perl/lib/MR/SilverBox.pm similarity index 100% rename from mod/box/client/perl/lib/MR/SilverBox.pm rename to connector/perl/lib/MR/SilverBox.pm diff --git a/mod/box/client/perl/lib/MR/Storage/Const.pm b/connector/perl/lib/MR/Storage/Const.pm similarity index 100% rename from mod/box/client/perl/lib/MR/Storage/Const.pm rename to connector/perl/lib/MR/Storage/Const.pm diff --git a/mod/box/t/TBox.pm b/connector/perl/t/TBox.pm similarity index 100% rename from mod/box/t/TBox.pm rename to connector/perl/t/TBox.pm diff --git a/mod/box/t/box.pl b/connector/perl/t/box.pl similarity index 100% rename from mod/box/t/box.pl rename to connector/perl/t/box.pl diff --git a/mod/box/t/box_tree.pl b/connector/perl/t/box_tree.pl similarity index 100% rename from mod/box/t/box_tree.pl rename to connector/perl/t/box_tree.pl diff --git a/mod/box/client/ruby/README b/connector/ruby/README similarity index 100% rename from mod/box/client/ruby/README rename to connector/ruby/README diff --git a/mod/box/client/ruby/box.rb b/connector/ruby/box.rb similarity index 100% rename from mod/box/client/ruby/box.rb rename to connector/ruby/box.rb diff --git a/mod/box/client/ruby/iproto.rb b/connector/ruby/iproto.rb similarity index 100% rename from mod/box/client/ruby/iproto.rb rename to connector/ruby/iproto.rb diff --git a/core/admin.m b/core/admin.m index a41c65b920..73fb165414 100644 --- a/core/admin.m +++ b/core/admin.m @@ -58,7 +58,7 @@ static const char *help = " - reload configuration" CRLF; -static const char unknown_command[] = "unknown command. try typing help." CRLF; +static const char *unknown_command = "unknown command. try typing help." CRLF; #line 65 "core/admin.c" @@ -1452,12 +1452,11 @@ case 107: #line 199 "core/admin.rl" - fiber->rbuf->len -= (void *)pe - (void *)fiber->rbuf->data; - fiber->rbuf->data = pe; + tbuf_ltrim(fiber->rbuf, (void *)pe - (void *)fiber->rbuf->data); if (p != pe) { start(out); - tbuf_append(out, unknown_command, sizeof(unknown_command)); + tbuf_append(out, unknown_command, strlen(unknown_command)); end(out); } diff --git a/core/admin.rl b/core/admin.rl index 277b8efcb9..2e10c8968c 100644 --- a/core/admin.rl +++ b/core/admin.rl @@ -56,7 +56,7 @@ static const char *help = " - reload configuration" CRLF; -static const char unknown_command[] = "unknown command. try typing help." CRLF; +static const char *unknown_command = "unknown command. try typing help." CRLF; %%{ machine admin; @@ -198,12 +198,11 @@ admin_dispatch(void) write exec; }%% - fiber->rbuf->len -= (void *)pe - (void *)fiber->rbuf->data; - fiber->rbuf->data = pe; + tbuf_ltrim(fiber->rbuf, (void *)pe - (void *)fiber->rbuf->data); if (p != pe) { start(out); - tbuf_append(out, unknown_command, sizeof(unknown_command)); + tbuf_append(out, unknown_command, strlen(unknown_command)); end(out); } diff --git a/core/log_io.m b/core/log_io.m index 718696e539..1bb065d27b 100644 --- a/core/log_io.m +++ b/core/log_io.m @@ -1399,7 +1399,7 @@ recover_init(const char *snap_dirname, const char *wal_dirname, struct recovery_state *r = p0alloc(eter_pool, sizeof(*r)); if (rows_per_file <= 1) - panic("inacceptable value of 'rows_per_file'"); + panic("unacceptable value of 'rows_per_file'"); r->wal_timer.data = r; r->row_handler = row_handler; diff --git a/core/salloc.m b/core/salloc.m index e9a8e52262..c8195ce865 100644 --- a/core/salloc.m +++ b/core/salloc.m @@ -191,7 +191,7 @@ format_slab(struct slab_class *class, struct slab *slab) } static bool -full_formated(struct slab *slab) +fully_formatted(struct slab *slab) { return slab->brk + slab->class->item_size >= (void *)slab + SLAB_SIZE; } @@ -284,7 +284,7 @@ salloc(size_t size) VALGRIND_MAKE_MEM_UNDEFINED(item, sizeof(void *)); } - if (full_formated(slab) && slab->free == NULL) + if (fully_formatted(slab) && slab->free == NULL) TAILQ_REMOVE(&class->free_slabs, slab, class_free_link); slab->used += class->item_size + sizeof(red_zone); @@ -302,7 +302,7 @@ sfree(void *ptr) struct slab_class *class = slab->class; struct slab_item *item = ptr; - if (full_formated(slab) && slab->free == NULL) + if (fully_formatted(slab) && slab->free == NULL) TAILQ_INSERT_TAIL(&class->free_slabs, slab, class_free_link); assert(valid_item(slab, item)); diff --git a/core/tbuf.m b/core/tbuf.m index baf47ab863..64031e6b2e 100644 --- a/core/tbuf.m +++ b/core/tbuf.m @@ -125,6 +125,18 @@ tbuf_peek(struct tbuf *b, size_t count) return NULL; } +/** Remove first count bytes from the beginning. */ + +void +tbuf_ltrim(struct tbuf *b, size_t count) +{ + tbuf_assert(b); + assert(count <= b->len); + + memmove(b->data, b->data + count, b->len - count); + b->len -= count; +} + size_t tbuf_reserve(struct tbuf *b, size_t count) { diff --git a/doc/developer/CMakeLists.txt b/doc/developer/CMakeLists.txt index 52ba4d5e1f..691e16c82e 100644 --- a/doc/developer/CMakeLists.txt +++ b/doc/developer/CMakeLists.txt @@ -1,6 +1,8 @@ -add_custom_command(OUTPUT tarantool_user_guide.html - COMMAND ${XSLTPROC} --xinclude -o tarantool_user_guide.html - http://docbook.sourceforge.net/release/xsl-ns/current/html/docbook.xsl - user.xml) +add_custom_target(dev-html ALL + COMMAND ${XSLTPROC} --nonet + --stringparam collect.xref.targets "all" + --xinclude -o tarantool_developer_guide.html + ${CMAKE_SOURCE_DIR}/doc/user/tnt-html.xsl + developer.xml) diff --git a/doc/developer/developer.xml b/doc/developer/developer.xml index 64713736d2..f761f76ec6 100644 --- a/doc/developer/developer.xml +++ b/doc/developer/developer.xml @@ -1,8 +1,40 @@ <?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE book [ +<!ENTITY % tnt SYSTEM "../tnt.ent"> +%tnt; +]> <book xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0"> -<title>Tarantool/Box User Guide, version 1.3.5</title> -<xi:include href="./intro.xml"/> +<title>Tarantool/Box Developer Guide</title> +<chapter> +<title>Compiling</title> +<section> +<title>How to fix the compile time error about missing confetti</title> +<para> + An error about missing confetti: +<programlisting> +Generating prscfg.h, prscfg.c... +[ 13%] Generating prscfg.h, prscfg.c +/bin/sh: CONFETTI-NOTFOUND: not found +</programlisting> +This error is caused by cmake, trying to re-create generated files +prscfg.h, prscfg.c in <filename>cfg/</filename> directory. +These files are under revision control and normally need not to be +regenerated. +The fix is to +<programlisting> +<prompt>$ </prompt>git checkout cfg/prscfg.h +<prompt>$ </prompt>git checkout cfg/prscfg.c +<prompt>$ </prompt>touch cfg/prscfg.[hc] +</programlisting> +The other alternative, if you have actually modified +<filename>core_cfg.cfg_tmpl</filename> is to install confetti from +<link xlink:href="http://github.com/mailru/confetti"/> and let cmake use it. + + </para> +</section> +</chapter> <!-- TOC: @@ -45,3 +77,8 @@ Glossary of terms --> </book> + +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/sql.txt b/doc/sql.txt new file mode 100644 index 0000000000..9cbbd9a7de --- /dev/null +++ b/doc/sql.txt @@ -0,0 +1,53 @@ +; +; Tarantool SQL parser is implemented entirely on the client side. +; This BNF provides a reference of the supported subset of +; the standard SQL, to which all clients are strongly encouraged +; to stick. +; +; Convention: UPPERCASE letters are used for terminals and literals. +; Lowercase letters are used for <non-terminals>. SQL is +; case-insensitive, so this convention is present only to imporve +; legibility of the BNF. + +<sql> ::= <insert> | <update> | <delete> | <select> + +<insert> ::= INSERT [INTO] <ident> VALUES <value_list> + +<update> ::= UPDATE <ident> SET <update_list> <simple_where> + +<delete> ::= DELETE FROM <ident> <simple_where> + +; It's only possible to select all fields of a tuple (* for field list) +<select> ::= SELECT * FROM <ident> <where> <opt_limit> + +<simple_where> ::= WHERE <predicate> + +<where> ::= WHERE <disjunction> + +<predicate> ::= <ident> = <constant> + +<disjunction> ::= <predicate> [{OR <predicate>}+] + +; LIMIT is optional +<opt_limit> ::= | LIMIT NUM[, NUM] + +<value_list> ::= (<constant> [{, <constant>}+]) + +<update_list> ::= <ident> = <constant> [{, <ident> = <constant>}+] + +<constant> ::= STR | NUM + +<ident> ::= ID + +; Only integer numbers, optionally signed, are supported +NUM ::= [+-]?[0-9]+ + +; Strings must be single-quoted +STR ::= '.*' + +; Identifiers must be standard SQL, but end with digits. +; These digits are used to infer the namespace or index id. + +ID ::= [a-z_]+[0-9]+ + +; vim: syntax=bnf diff --git a/doc/user/CMakeLists.txt b/doc/user/CMakeLists.txt index d6059029be..54df67d597 100644 --- a/doc/user/CMakeLists.txt +++ b/doc/user/CMakeLists.txt @@ -1,9 +1,48 @@ add_custom_target(html ALL - COMMAND ${XSLTPROC} + COMMAND ${XSLTPROC} --nonet --stringparam collect.xref.targets "all" --xinclude -o tarantool_user_guide.html tnt-html.xsl user.xml) + +add_custom_target(pdf + COMMAND ${XSLTPROC} --nonet + --stringparam collect.xref.targets "all" + --xinclude -o tarantool_user_guide.fo + tnt-fo.xsl + user.xml + COMMAND fop tarantool_user_guide.fo tarantool_user_guide.pdf) + +add_custom_target(relink + COMMAND ${XSLTPROC} --nonet + --stringparam collect.xref.targets "only" + --xinclude -o tarantool_user_guide.html + tnt-html.xsl + user.xml) + +add_custom_target(html-saxon + COMMAND java -cp "/usr/share/java/saxon.jar:/usr/share/java/xml-commons-resolver-1.1.jar:/usr/share/java/docbook-xsl-saxon.jar:/usr/share/java/xercesImpl.jar:/etc/xml/resolver:/usr/share/java/xslthl.jar" + -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl + -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl + -Dorg.apache.xerces.xni.parser.XMLParserConfiguration=org.apache.xerces.parsers.XIncludeParserConfiguration + com.icl.saxon.StyleSheet + -x org.apache.xml.resolver.tools.ResolvingXMLReader + -y org.apache.xml.resolver.tools.ResolvingXMLReader + -r org.apache.xml.resolver.tools.CatalogResolver + -u -o tarantool_user_guide.html user.xml tnt-html.xsl) + +add_custom_target(pdf-saxon + COMMAND java -cp "/usr/share/java/saxon.jar:/usr/share/java/xml-commons-resolver-1.1.jar:/usr/share/java/docbook-xsl-saxon.jar:/usr/share/java/xercesImpl.jar:/etc/xml/resolver:/usr/share/java/xslthl.jar" + -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl + -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl + -Dorg.apache.xerces.xni.parser.XMLParserConfiguration=org.apache.xerces.parsers.XIncludeParserConfiguration + com.icl.saxon.StyleSheet + -x org.apache.xml.resolver.tools.ResolvingXMLReader + -y org.apache.xml.resolver.tools.ResolvingXMLReader + -r org.apache.xml.resolver.tools.CatalogResolver + -u -o tarantool_user_guide.fo user.xml tnt-fo.xsl + COMMAND fop tarantool_user_guide.fo tarantool_user_guide.pdf) + # XMLLINT is not able to validate SCHEMATRON constraints, and # therefore is not a good validation tool for DocBook 5. However, # it can validate the entire document, following xinclude diff --git a/doc/user/configuration-reference.xml b/doc/user/configuration-reference.xml index 56834c4a20..cba6c0934f 100644 --- a/doc/user/configuration-reference.xml +++ b/doc/user/configuration-reference.xml @@ -3,6 +3,7 @@ %tnt; ]> <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="configuration-reference"> @@ -20,7 +21,7 @@ are provided for the most basic properties only: the rest must be set in the configuration file. At runtime, this allows to disambiguate the source of a configuration setting: it unequivocally comes either from -the command line, or from the options file, but never from +the command line, or from the configuration file, but never from both. </para> @@ -122,7 +123,11 @@ Tarantool/Box 1.4.0-69-g45551dd </para> </listitem> <listitem> - <para><option>--init-storage</option></para> + <para> + <option xml:id="init-storage-option" + xreflabel="--init-storage"> + --init-storage + </option></para> <para>Initialize the directory, specified in <emphasis>vardir</emphasis> configuration option by creating an empty snapshot file in it. If <filename>vardir</filename> doesn't contain at @@ -139,7 +144,8 @@ Tarantool/Box 1.4.0-69-g45551dd </listitem> <listitem> - <para><option>--cat</option> <userinput>snapshot.file</userinput></para> + <para><option xml:id="cat-option" xreflabel="--cat">--cat</option> + <userinput>snapshot.file</userinput></para> <para>Print the snapshot file, pointed to by the argument, in a human-readable form. For each log record, log sequence number, time of entry, operation type and arguments are @@ -179,12 +185,12 @@ lsn:4 tm:1301572313.691 t:65534 127.0.0.1:52728 UPDATE_FIELDS n:0flags:00000000 </itemizedlist> </section> -<section> +<section xml:id="option-file" xreflabel="option file"> <title>The option file</title> <para> - All advanced configuration parameters must be specified in an - option file, which is required for server start. If no path to - option file is specified on the command line (see + All advanced configuration parameters must be specified in a + configuration file, which is required for server start. If no path to + the configuration file is specified on the command line (see <option xlink:href="#config-option" xlink:title="--config=...">--config</option>), the server looks for a file named <filename>tarantool.cfg</filename> @@ -193,11 +199,8 @@ lsn:4 tm:1301572313.691 t:65534 127.0.0.1:52728 UPDATE_FIELDS n:0flags:00000000 <para> To facilitate centralized and automated configuration management, runtime configuration modifications are supported - solely through <emphasis role="tntadmin" - xlink:href="tarantool-user-guide#reload-configuration" - xlink:title="reload configuration" - xlink:role="http://docbook.org/xlink/role/olink">reload - configuration</emphasis> administrative statement. Thus, the + solely through <olink targetptr="reload-configuration"/> + administrative statement. Thus, the procedure to change Tarantool configuration at runtime is to edit the configuration file. This ensures that, should the server get killed or restart, no unexpected changes to @@ -206,6 +209,11 @@ lsn:4 tm:1301572313.691 t:65534 127.0.0.1:52728 UPDATE_FIELDS n:0flags:00000000 <para> Not all configuration file settings are changeable at runtime: such settings will be highlighted in this reference. + If the same setting is given more than once, the latest occurrence + takes effect. + You can always invoke <olink targetptr="show-configuration"/> + from the administrative console to show the current + configuration. </para> <para> Tarantool maintains a set of all allowed configuration @@ -221,10 +229,657 @@ lsn:4 tm:1301572313.691 t:65534 127.0.0.1:52728 UPDATE_FIELDS n:0flags:00000000 <filename xlink:href="https://github.com/mailru/tarantool/blob/master/test/box/tarantool.cfg">test/box/tarantool.cfg</filename>, <filename xlink:href="https://github.com/mailru/tarantool/blob/master/test/box_big/tarantool.cfg">test/box_big/tarantool.cfg</filename>. </para> - <section> + + <table frame='all' pgwide='1'> <title>Basic parameters</title> - <para>Parameter1</para> - </section> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>username</entry> + <entry>string</entry> + <entry>""</entry> + <entry>no</entry> + <entry>no</entry> + <entry>UNIX user name to switch to after start.</entry> + </row> + + <row> + <entry>work_dir</entry> + <entry>string</entry> + <entry>""</entry> + <entry>no</entry> + <entry>no</entry> + <entry>A directory to switch to with chdir(2) after + start. Can be relative to the starting directory. + If not specified, the current working directory + of the server is the same as starting + directory.</entry> + </row> + + <row> + <entry xml:id="wal_dir" xreflabel="wal_dir">wal_dir</entry> + <entry>string</entry> + <entry>""</entry> + <entry>no</entry> + <entry>no</entry> + <entry>A directory to store the write ahead log files + (WAL) in. Can be relative to work_dir. You may choose + to separate your snapshots and logs and store them + on separate disks. This is how this parameter is most + commonly used. If not specified, defaults to work_dir.</entry> + </row> + + <row> + <entry xml:id="snap_dir" xreflabel="snap_dir">snap_dir</entry> + <entry>string</entry> + <entry>""</entry> + <entry>no</entry> + <entry>no</entry> + <entry>A directory to store snapshots in. Can be + relative to work_dir. If not specified, defaults to + work_dir. See also <olink targetptr="wal_dir"/>.</entry> + </row> +<!-- + <row> + <entry>coredump</entry><entry>0 or 1</entry><entry>0</entry> + <entry>Deprecated. Save core on abort/assert? You may + turn off the coredump off when using ulimit</entry> + </row> +--> + <row> + <entry xml:id="primary_port" xreflabel="primary_port">primary_port</entry> + <entry>integer</entry> + <entry><emphasis role="strong">none</emphasis></entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>no</entry> + <entry>The read/write data port. + Has no default value, so <emphasis + role="strong">must be specified</emphasis> + in the configuration file. Normally set to 33013. + Note: a replica also binds to this port, accepts + connections, but these connections can only serve + reads until the replica becomes a master.</entry> + </row> + + <row> + <entry xml:id="secondary_port" + xreflabel="secondary_port">secondary_port</entry> + <entry>integer</entry> + <entry>none</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Additional, read-only port. Normally set to + 33014. Not used unless is set.</entry> + </row> + + <row> + <entry xml:id="admin_port" xreflabel="admin_port">admin_port</entry> + <entry>integer</entry> + <entry>none</entry> + <entry>no</entry> + <entry>no</entry> + <entry>The TCP port to listen on for administrative + connections. Has no default value. Not used unless + assigned a value. Normally set to 33015.</entry> + </row> + + <row> + <entry>pid_file</entry> + <entry>string</entry> + <entry>tarantool.pid</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Store the process id in this file. Can be + relative to work_dir.</entry> + </row> + + <row> + <entry xml:id="custom_proc_title" + xreflabel="custom_proc_title"> + custom_proc_title + </entry> + <entry>string</entry> + <entry>""</entry> + <entry>no</entry> + <entry>no</entry> + <entry> + <para>Inject the given string into <olink + targetptr="proctitle">server process title</olink> + (what's shown in COMMAND column of <command>ps</command> + and <command>top</command> commands). For example, + an unmodified Tarantool/Box process group looks like: + </para> +<programlisting>kostja@shmita:~$ ps -a -o command | grep box +tarantool_box: primary pri:33013 sec:33014 adm:33015</programlisting> + <para>After "sessions" custom_proc_title is injected it + looks like:</para> +<programlisting>kostja@shmita:~$ ps -a -o command | grep box +tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> + </entry> + </row> + + </tbody> + </tgroup> + </table> + + <table frame='all' pgwide='1'> + <title>Configuring the storage</title> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>slab_alloc_arena</entry> + <entry>float</entry> + <entry>1.0</entry> + <entry>no</entry> + <entry>no</entry> + <entry> + <anchor xml:id="slab_alloc_arena" xreflabel="slab_alloc_arena"/> + How much memory Tarantool + allocates to actually + store tuples, <emphasis role="strong">in + gigabytes</emphasis>. When the limit is reached, INSERT + or UPDATE requests begin failing with error + <olink targetptr="ERR_CODE_MEMORY_ISSUE"/>. + While the server does not go + beyond the defined limit to allocate tuples, there is + additional memory used to store indexes and connection + information. Depending on actual configuration and + workload, Tarantool can consume up to 20-40% of the + limit set here.</entry> + </row> + + <row> + <entry>slab_alloc_minimal</entry> + <entry>integer</entry> + <entry>64</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Size of the smallest allocation unit. It can be + tuned down if most of the tuples are very small.</entry> + </row> + + <row> + <entry>slab_alloc_factor</entry> + <entry>float</entry> + <entry>2.0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Use slab_alloc_factor as the multiplier for + computing the sizes of memory chunks that tuples are + stored in. A lower value may result in less wasted + memory depending on the total amount of memory available + and the distribution of item sizes.</entry> + </row> + + <row> + <entry>namespace</entry> + <entry>array of objects</entry> + <entry>none</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry><emphasis role="strong">no</emphasis></entry> + <entry>This is the main Tarantool parameter, describing + the data structure that users get access to via + client/server protocol. It holds an array of + entries, and each entry represents a tuple set + served by the server. Every entry is a composite object, + best seen as a C programming language "struct" + <footnote><xi:include href="namespace.xml"/></footnote>. + </entry> + </row> + + </tbody> + </tgroup> + </table> + + <table frame='all' pgwide='1'> + <title>Binary logging and snapshots</title> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>panic_on_snap_error</entry> + <entry>boolean</entry> + <entry>1</entry> + <entry>no</entry> + <entry>no</entry> + <entry>If there is an error reading the snapshot (at + server start), abort.</entry> + </row> + + <row> + <entry>panic_on_wal_error</entry> + <entry>boolean</entry> + <entry>0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>If there is an error reading from a write ahead + log (at server start), abort.</entry> + </row> + + <row> + <entry>rows_per_wal</entry> + <entry>integer</entry> + <entry>500000</entry> + <entry>no</entry> + <entry>no</entry> + <entry>How many log records to store in a single write + ahead log file. When this limit is reached, Tarantool + creates another WAL file named + <filename><first-lsn-in-wal>.wal</filename> + This can be useful for simple rsync-based backups. + </entry> + </row> + + <row> + <entry>snap_io_rate_limit</entry> + <entry>float</entry> + <entry>0.0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Reduce the throttling effect of <olink + targetptr="save-snapshot"/> on the INSERT/UPDATE/DELETE + performance by setting a limit on + how many megabytes per second it can write to disk. + The same can be achieved by splitting <olink + targetptr="wal_dir"/> and <olink targetptr="snap_dir"/> + locations and moving snapshots to a separate disk.</entry> + </row> + + <row> + <entry>wal_writer_inbox_size</entry> + <entry>integer</entry> + <entry>128</entry> + <entry>no</entry> + <entry>no</entry> + <entry>WAL writer is a separate process whose sole + purpose is to write the change log to disk. Every + incoming data change is sent to this process and + queued for write. This parameter affects the size of the + user space buffer that WAL writer uses to queue + write requests. By default, up to 128 client + connections can have pending updates waiting on disk. + </entry> + </row> + + <row> + <entry>wal_fsync_delay</entry> + <entry>integer</entry> + <entry>0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Do not flush the write ahead log to disk more often + than once in wal_fsync_delay seconds. By default the + delay is zero, + that is, the write ahead log is flushed after every write. + Setting the delay may be necessary to increase write + throughput, but may lead to several last updates being + lost in case of a power failure. Such failure, however, + does not read to data corruption: all WAL records have a + checksum, and only complete records are processed during + recovery.</entry> + </row> + + </tbody> + </tgroup> + </table> + + <table frame='all' pgwide='1'> + <title>Replication</title> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry xml:id="replication_port" + xreflabel="replication_port">replication_port</entry> + <entry>integer</entry> + <entry>0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>Replication port. If non-zero, Tarantool listens + on the given port for incoming connections from + replicas. See also <olink + targetptr="replication_source_port"/>, which complements + this setting on the replica side.</entry> + </row> + + <row> + <entry xml:id="replication_source_port" + xreflabel="replication_source_port">replication_source_port</entry> + <entry>integer</entry> + <entry>0</entry> + <entry>no</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>Remote port of the master. If non-zero, + replication is on, and Tarantool does not accept updates + on <olink targetptr="primary_port"/>. This parameter is + dynamic, that is, to enter master mode, simply set the + port value to 0 and issue <olink + targetptr="reload-configuration"/>.</entry> + </row> + + <row> + <entry xml:id="replication_source_ipaddr" + xreflabel="replication_source_ipaddr"> + replication_source_ipaddr + </entry> + <entry>string</entry> + <entry>0</entry> + <entry>no</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>IP address of replication master.</entry> + </row> + + </tbody> + </tgroup> + </table> + + <table frame='all' pgwide='1'> + <title>Networking</title> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>io_collect_interval</entry> + <entry>float</entry> + <entry>0.0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>If non-zero, a sleep given duration is + injected between iterations of the event loop. Can be + used to reduce CPU load in deployments in which the + number of client connections is large, but requests are + not so frequent (for example, each connection issuing + just a handful of requests per second). </entry> + </row> + + <row> + <entry>readahead</entry> + <entry>integer</entry> + <entry>16384</entry> + <entry>no</entry> + <entry>no</entry> + <entry>The size of read-ahead buffer associated with + a client connection.</entry> + </row> + + <row> + <entry>backlog</entry> + <entry>integer</entry> + <entry>1024</entry> + <entry>no</entry> + <entry>no</entry> + <entry>The size of listen backlog.</entry> + </row> + + </tbody> + </tgroup> + </table> + + <table frame='all' pgwide='1'> + <title>Logging</title> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>log_level</entry> + <entry>integer</entry> + <entry>4</entry> + <entry>no</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>How verbose the logging is. There are 5 log + verbosity classes: 1 -- ERROR, 2 -- CRITICAL, 3 -- + WARNING, 4 -- INFO, 5 -- DEBUG. By setting log_level, + you can enable logging of all classes below or equal + to the given level. Tarantool prints its logs to the + standard error stream by default, but this can be + changed with "logger" configuration parameter. + </entry> + </row> + + <row> + <entry>logger</entry> + <entry>string</entry> + <entry>""</entry> + <entry>no</entry> + <entry>no</entry> + <entry>By default, the log is sent to the standard + error stream (<filename>stderr</filename>). If this + option is given, Tarantool creates a child process, + executes the given command in it, and pipes its standard + output to the standard input of the created process. + Example setting: <command>tee --append + tarantool.log</command> (this will duplicate log output + to <filename>stdout</filename> and a log file). + </entry> + </row> + + <row> + <entry>logger_nonblock</entry> + <entry>integer</entry> + <entry>0</entry> + <entry>no</entry> + <entry>no</entry> + <entry>If this option is given, Tarantool does not + block on the log file descriptor when it's not + ready for write, and drops the message instead. If + log_level is high, and a lot of messages go to the log + file, setting this option to 1 may improve logging + performance at the cost of some log messages getting + lost.</entry> + </row> + + <row> + <entry>too_long_threshold</entry> + <entry>float</entry> + <entry>0.5</entry> + <entry>no</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>If processing a request takes longer than the + given value (in seconds), warn about it in the log. + Has effect only if log_level is no less than 3 + (WARNING).</entry> + </row> + + </tbody> + </tgroup> + </table> + + <table frame='all' pgwide='1'> + <title>Memcached protocol support</title> + <tgroup cols='6' colsep='1' rowsep='1'> + <colspec colnum="1" colname="col1" colwidth="2*"/> + <colspec colnum="6" colname="col4" colwidth="6*"/> + + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Default</entry> + <entry>Required?</entry> + <entry>Dynamic?</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>memcached_port</entry> + <entry>integer</entry> + <entry>0</entry> + <entry>no</entry> + <entry>no</entry> + <entry> + <anchor xml:id="memcached_port" xreflabel="memcached_port"/> + + Turn on Memcached protocol support on the given + port. All requests on this port are directed to + a dedicated namespace, set in <olink + targetptr="memcached_namespace"/>. + Memcached-style flags are supported and stored + along with the value. The expiration time can also be + set and is persistent, but is ignored, unless <olink + targetptr="memcached_expire"/> is turned on. + Unlike Memcached, all data still goes to the binary + log and to the replica, if latter one is set up, which + means that power outage does not lead to loss of all + data. Thanks to data persistence, cache warm up time + is also very short. + </entry> + </row> + + <row> + <entry>memcached_namespace</entry> + <entry>integer</entry> + <entry>23</entry> + <entry>no</entry> + <entry>no</entry> + <entry> + <anchor xml:id="memcached_namespace" + xreflabel="memcached_namespace"/> + Namespace id to store memcached data in. The + format of tuple is [key, metadata, value], with a HASH + index based on the key. Since the namespace format + is defined by Memcached data model, it must not be + previously configured.</entry> + </row> + + <row> + <entry>memcached_expire</entry> + <entry>boolean</entry> + <entry>0</entry> + <entry>no</entry> + <entry>no</entry> + <entry> + <anchor xml:id="memcached_expire" + xreflabel="memcached_expire"/> + Turn on tuple time-to-live support in + <olink targetptr="memcached_namespace"/>. This + effectively turns Tarantool into a "persistent" implementation + of Memcached. Since a caching server has + significantly different purpose than a data server, in + this mode Tarantool turns off replication and does not + bind to <olink targetptr="primary_port"/> or <olink + targetptr="secondary_port"/>. + </entry> + </row> + + <row> + <entry>memcached_expire_per_loop</entry> + <entry>integer</entry> + <entry>1024</entry> + <entry>no</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>How many records to consider per iteration of the + expiration loop. Tuple expiration is performed in a separate + <quote>green</quote> thread within our cooperative multitasking + framework and this setting effectively limits how long + the expiration loop stays on CPU uninterrupted. + </entry> + </row> + + <row> + <entry>memcached_expire_full_sweep</entry> + <entry>integer</entry> + <entry>3600</entry> + <entry>no</entry> + <entry><emphasis role="strong">yes</emphasis></entry> + <entry>Try to make sure that every tuple is considered + for expiration within this time frame (in seconds). + Together with memcached_expire_per_loop this defines + how often the expiration <quote>green</quote> thread + is scheduled on CPU. + </entry> + </row> + + </tbody> + </tgroup> + </table> </section> </chapter> diff --git a/doc/user/connectors.xml b/doc/user/connectors.xml new file mode 100644 index 0000000000..c150d64627 --- /dev/null +++ b/doc/user/connectors.xml @@ -0,0 +1,265 @@ +<!DOCTYPE book [ +<!ENTITY % tnt SYSTEM "../tnt.ent"> +%tnt; +]> +<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml:id="connectors"> + +<title>Connectors</title> +<blockquote><para> + This chapter documents APIs for various programming languages -- + C, Perl, Ruby, PHP and Python. +</para></blockquote> + +<para>All connectors are located in srcdir/connector directory. Apart from the native Tarantool client driver, you can always use a <emphasis role="strong">Memcached</emphasis> driver of your choice, after enabling Memcached protocol in the configuration file.</para> + + <section> + <title>C</title> + <para> + Please see <link + xlink:href="https://github.com/mailru/tarantool/blob/master/connector/c/client.h"><filename>connector/c/client.h</filename></link> in the source tree. + </para> + </section> + + <section> + <title>Perl</title> + <para> + The perl client is located in <link + xlink:href="https://github.com/mailru/tarantool/blob/master/connector/perl/lib/"><filename>connector/perl/lib/</filename></link>. + <orderedlist> + + <listitem> + <simpara><emphasis role="strong">new</emphasis></simpara> +<programlisting language="perl"><![CDATA[ + my $box = MR::SilverBox->new({ + namespaces => [ { + indexes => [ { + index_name => 'primary_id', + keys => [0], + }, { + index_name => 'primary_email', + keys => [1], + }, ], + namespace => 0, + format => 'l& SSLL', + default_index => 'primary_id', + } ], + }, + servers => $server}) +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Insert</emphasis></simpara> +<programlisting language="perl"> + $box->Insert(@tuple); +</programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Select</emphasis></simpara> +<programlisting language="perl"><![CDATA[ + [\%tuple1, \%tuple2, ...] = $box->Select(@id); + \%tuple = $box->Select($id); + [\@tuple1, \@tuple2, ...] = $box->Select(@id, {raw => 1}); + \@tuple = $box->Select($id, {raw => 1}); + $box->Select($email, {use_index => 1}); +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Update</emphasis> + accepts parameters in the last argument just like Select:</simpara> +<programlisting language="perl"><![CDATA[ + $key = 1; # key, ID of user by default + $field_num = 2; # posititon in tuple, starts from 0, must be >= 1 + $value = pack('L', 123); # integer values must be packed + $box->Update($key, $field_num, $value); +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Delete</emphasis></simpara> +<programlisting language="perl"><![CDATA[ + $box->Delete($key); +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">AndXorAdd</emphasis> + transforms the tuple field at position <quote>$field_num</quote> + according to formula <quote>field= ((field & $and_mask) ^ $xor_mask) + $add_value</quote>. + </simpara> +<programlisting language="perl"><![CDATA[ + $box->AndXorAdd($key, $field_num, $and_mask, $xor_mask, $add_value); +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Bit</emphasis> + performs a bitwise operation on field at position + <quote>$field_num</quote>. Unused arguments can be omitted. + Note: <quote>set</quote> has a higher precedence than + <quote>bit_set</quote> and <quote>bit_clear</quote>. + </simpara> +<programlisting language="perl"><![CDATA[ + $box->Bit($key, $field_num, bit_clear => $clear_mask, bit_set => $set_mask, set => $set_value); + $box->Bit($key, $field_num, bit_set => $set_mask); +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Num</emphasis> + performs a numeric update operation on field at position + <quote>$field_num</quote>. Unused arguments can be omitted. + Note: again, <quote>set</quote> has a higher precedence than + <quote>num_add</quote> and <quote>num_sub</quote>. + </simpara> +<programlisting language="perl"><![CDATA[ + $box->Num($key, $field_num, set => $set_value, num_add => $add_value, num_sub => $sub_value); +]]></programlisting> + </listitem> + + <listitem> + <simpara><emphasis role="strong">Flag</emphasis> + sets or clears flags on a tuple, the calling convention + is the same as for <quote>Bit</quote> and <quote>Num</quote> + operations. + </simpara> +<programlisting language="perl"><![CDATA[ + $box->Flags(bit_set => $set_mask, bit_clear => $clear_mask); +]]></programlisting> + </listitem> + + </orderedlist> + + </para> + </section> + + <section> + <title>PHP</title> + <para> + @tba + </para> + </section> + + <section> + <title>Python</title> + <para> + @tba + </para> + </section> + + <section> + <title>Ruby</title> + <para> + You need <emphasis role="strong">Ruby 1.9</emphasis> or later + to use this connector. Connector sources are located in <link + xlink:href="https://github.com/mailru/tarantool/blob/master/connector/ruby/box.rb"><filename>connector/ruby/box.rb</filename></link>. + </para> + <para> + Assume, for the sake of example, that Tarantool has the + following namespace configuration: +<programlisting language="c"> +primary_port = 33013 +admin_port = 33015 +log_level = 3 +slab_alloc_arena = 0.1 + +namespace[0].enabled = 1 +namespace[0].index[0].type = "NUM" +namespace[0].index[0].key_fields[0].fieldno = 0 + +namespace[0].index[1].type = "STR" +namespace[0].index[1].key_fields[0].fieldno = 1 +</programlisting> + The only defined namespace will be used to store user + account information, such as id, name, email, and other + properties. User ID is used for the primary key, but + it's also possible to find a user by name. + </para> + <para>In Ruby, a helper class is defined to present + Tarantool to the rest of the application as a typical object + container. +<example> +<title>userbox.rb</title> +<programlisting language="ruby"><![CDATA[require 'box' + +class UserBox < Box + def initialize(host) + super(host, :namespace => 0) + end + + def insert(user) + case user + when Hash then super [user[:uid], user[:email], user[:name], user[:apple_count]] + when Array then super user + else fail "don't know what to do with #{user.class}" + end + end + + def update_fields(key, *ops) + mapping = {:uid => 0, :email => 1, :name => 2, :apple_count => 3} + ops.map do |op| + op[0] = mapping[op[0]] if op.is_a? Array + end + + super key, *ops + end + + def unpack_tuple!(data) + tuple = super data + { :uid => tuple[0].unpack(?L)[0], + :email => tuple[1], + :name => tuple[2], + :apple_count => tuple[3].unpack(?L)[0] + } + end +end]]></programlisting></example> + Here's how this helper class can be used: +<programlisting><prompt>kostja@shmita:~$ </prompt><command>irb</command> +<![CDATA[>> # Connect to the server +>> require 'userbox' +=> true +>> b = UserBox.new 'localhost:33013' +=> #<UserBox:0x870fd48 @namespace=1, @end_point=["localhost", 33013], @sock=#<TCPSocket:0x870f85c> +>> # Insert a few users +>> b.insert :uid => 1, :email => 'pupkin@mail.ru', :name => 'Vasya', :apple_count => 1 +=> 1 +>> b.insert :uid => 2, :email => 'masha@mail.ru', :name => 'Masha', :apple_count => 0 +=> 1 +>> b.insert :uid => 3, :email => 'petya@mail.ru', :name => 'Petya', :apple_count => 3 +=> 1 +>> # Perform selects +>> b.select 1 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>1}] +>> b.select 1,2,3 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>1}, {:uid=>2, :email=>"masha@mail.ru", :name=>"Masha", :apple_count=>0}, {:uid=>3, :email=>"petya@mail.ru", :name=>"Petya", :apple_count=>3}] +>> # It's possible to retrieve records by email using second index +>> b.select 'pupkin@mail.ru', 'petya@mail.ru', :index => 1 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>1}, {:uid=>3, :email=>"petya@mail.ru", :name=>"Petya", :apple_count=>3}] +Delete +>> b.delete 2 +=> 1 +>> # Update values +>> b.update_fields 1, [:apple_count, :add, 2 ] +=> 1 +>> b.select 1 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>3}] +>> # It's possible to do several updates in a single atomic command +>> b.update_fields 3, [:apple_count, :add, 10], [:name, :set, "foobar"] +=> 1 +>> b.select 3 +=> [{:uid=>3, :email=>"petya@mail.ru", :name=>"foobar", :apple_count=>13}] +]]> +</programlisting> + </para> + </section> + +</chapter> + +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/user/data-model.xml b/doc/user/data-model.xml index 1e00090e35..0eee0b8764 100644 --- a/doc/user/data-model.xml +++ b/doc/user/data-model.xml @@ -109,7 +109,7 @@ <para> Since not all NoSQL operations can be expressed in SQL, to gain complete access to data manipulation functionality one must use - a Perl, Python, Ruby or C connector. The client/server protocol + a <olink targetptr="connectors">Perl, Python, Ruby or C connector</olink>. The client/server protocol is open and documented: an annotated BNF can be found in the source tree, file <filename xlink:href="https://github.com/mailru/tarantool/blob/master/doc/box-protocol.txt" xlink:title="A complete BNF of Tarantool client/server protocol">doc/protocol.txt</filename>. diff --git a/doc/user/errcode.xml b/doc/user/errcode.xml new file mode 100644 index 0000000000..1f55d388d0 --- /dev/null +++ b/doc/user/errcode.xml @@ -0,0 +1,77 @@ +<appendix xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml:id="errcode"> + +<title>List of error codes</title> + +<para>In the current version of the binary protocol, error message, +which is normally more descriptive than error code, +is not present in server response. The actual message may contain +a file name, a detailed reason or operating system error code. +All such messages, however, are logged in the error log. When +using <emphasis role="strong">Memcached</emphasis> protocol, the error message is sent to the +client along with the code. Below follow only general descriptions +of existing codes.</para> +<variablelist> +<title>List of error codes</title> + + <varlistentry> + <term xml:id="ERR_CODE_NONMASTER" xreflabel="ERR_CODE_NONMASTER">ERR_CODE_NONMASTER</term> + <listitem><para>Attempt to execute an update over the + secondary (read-only) port or on a running replica. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_ILLEGAL_PARAMS" xreflabel="ERR_CODE_ILLEGAL_PARAMS">ERR_CODE_ILLEGAL_PARAMS</term> + <listitem><para>Illegal parameters. Malformed protocol + message. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_NODE_IS_RO" xreflabel="ERR_CODE_NODE_IS_RO">ERR_CODE_NODE_IS_RO</term> + <listitem><para>A parallel update of a tuple is in progress. Try again. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_MEMORY_ISSUE" xreflabel="ERR_CODE_MEMORY_ISSUE">ERR_CODE_MEMORY_ISSUE</term> + <listitem><para>Out of memory: <olink targetptr="slab_alloc_arena"/> limit is reached. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_WAL_IO" xreflabel="ERR_CODE_WAL_IO">ERR_CODE_WAL_IO</term> + <listitem><para>Failed to record the change in the write ahead + log. Some sort of disk error. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_INDEX_VIOLATION" xreflabel="ERR_CODE_INDEX_VIOLATION">ERR_CODE_INDEX_VIOLATION</term> + <listitem><para>A unique index constraint violation: a tuple with the same + key is already present in the index. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_NO_SUCH_NAMESPACE" xreflabel="ERR_CODE_NO_SUCH_NAMESPACE">ERR_CODE_NO_SUCH_NAMESPACE</term> + <listitem><para>Attempt to access a namespace that is not + configured (doesn't exist). + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="ERR_CODE_NO_SUCH_INDEX" xreflabel="ERR_CODE_NO_SUCH_INDEX">ERR_CODE_NO_SUCH_INDEX</term> + <listitem><para>No index with the given id exists. + </para></listitem> + </varlistentry> + +</variablelist> +</appendix> + +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/user/html-highlight.xsl b/doc/user/html-highlight.xsl new file mode 100644 index 0000000000..02cb8b611b --- /dev/null +++ b/doc/user/html-highlight.xsl @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="ASCII"?> +<!--This file was created automatically by html2xhtml--> +<!--from the HTML stylesheets.--> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:d="http://docbook.org/ns/docbook" +xmlns:xslthl="http://xslthl.sf.net" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xslthl d" version="1.0"> + +<!-- ******************************************************************** + $Id: highlight.xsl 8419 2009-04-29 20:37:52Z kosek $ + ******************************************************************** + + This file is part of the XSL DocBook Stylesheet distribution. + See ../README or http://docbook.sf.net/release/xsl/current/ for + and other information. + + ******************************************************************** --> + +<xsl:import href="http://docbook.sourceforge.net/release/xsl-ns/current/highlighting/common.xsl"/> + +<xsl:template match="xslthl:keyword" mode="xslthl"> + <b class="hl-keyword"><xsl:apply-templates mode="xslthl"/></b> +</xsl:template> + +<xsl:template match="xslthl:string" mode="xslthl"> + <b class="hl-string"><i style="color:red"><xsl:apply-templates mode="xslthl"/></i></b> +</xsl:template> + +<xsl:template match="xslthl:comment" mode="xslthl"> + <i class="hl-comment" style="color: silver"><xsl:apply-templates mode="xslthl"/></i> +</xsl:template> + +<xsl:template match="xslthl:directive" mode="xslthl"> + <span class="hl-directive" style="color: maroon"><xsl:apply-templates mode="xslthl"/></span> +</xsl:template> + +<xsl:template match="xslthl:tag" mode="xslthl"> + <b class="hl-tag" style="color: #000096"><xsl:apply-templates mode="xslthl"/></b> +</xsl:template> + +<xsl:template match="xslthl:attribute" mode="xslthl"> + <span class="hl-attribute" style="color: #F5844C"><xsl:apply-templates mode="xslthl"/></span> +</xsl:template> + +<xsl:template match="xslthl:value" mode="xslthl"> + <span class="hl-value" style="color: #993300"><xsl:apply-templates mode="xslthl"/></span> +</xsl:template> + +<xsl:template match="xslthl:html" mode="xslthl"> + <b><i style="color: red"><xsl:apply-templates mode="xslthl"/></i></b> +</xsl:template> + +<xsl:template match="xslthl:xslt" mode="xslthl"> + <b style="color: #0066FF"><xsl:apply-templates mode="xslthl"/></b> +</xsl:template> + +<!-- Not emitted since XSLTHL 2.0 --> +<xsl:template match="xslthl:section" mode="xslthl"> + <b><xsl:apply-templates mode="xslthl"/></b> +</xsl:template> + +<xsl:template match="xslthl:number" mode="xslthl"> + <span class="hl-number"><xsl:apply-templates mode="xslthl"/></span> +</xsl:template> + +<xsl:template match="xslthl:annotation" mode="xslthl"> + <i><span class="hl-annotation" style="color: gray"><xsl:apply-templates mode="xslthl"/></span></i> +</xsl:template> + +<!-- Not sure which element will be in final XSLTHL 2.0 --> +<xsl:template match="xslthl:doccomment|xslthl:doctype" mode="xslthl"> + <b class="hl-tag" style="color: blue"><xsl:apply-templates mode="xslthl"/></b> +</xsl:template> + +</xsl:stylesheet> diff --git a/doc/user/language-reference.xml b/doc/user/language-reference.xml index 89036005ff..5163f54e41 100644 --- a/doc/user/language-reference.xml +++ b/doc/user/language-reference.xml @@ -16,63 +16,303 @@ Unlike many other key/value servers, Tarantool uses different TCP ports and client/server protocols for data manipulation and administrative statements. - On start up, the server connects to three TCP ports: + On start up, the server can connect to up to five TCP ports: <itemizedlist> <listitem><para> Read/write data port, to handle INSERTs, UPDATEs, - DELETEs and SELECTs. + DELETEs and SELECTs. This port speaks the native + Tarantool protocol, and provides full access to the server. </para> <para> The default value of the port is <literal>33013</literal>, - as defined in <emphasis>primary_port</emphasis> + as defined in <olink targetptr="primary_port"/> configuration option. </para></listitem> <listitem><para> Read only port, which only accepts SELECTs, port number <literal>33014</literal>, as defined in - <emphasis>secondary_port</emphasis> configuration option. + <olink targetptr="secondary_port"/> configuration option. </para></listitem> <listitem><para> Administrative port, which defaults to <literal>33015</literal>, - and is defined in <emphasis>admin_port</emphasis> + and is defined in <olink targetptr="admin_port"/> configuration option. </para></listitem> + <listitem><para>Replication port (see <olink + targetptr="replication_port"/>), by default set to + <literal>33016</literal>, used to send updates to + replicas. Replication is optional, and if this port is not + set in the option file, the corresponding server process + is not started. + </para></listitem> + <listitem><para>Memcached port. Optional, read-write data port + that speaks Memcached protocol. This port is off by default. + </para></listitem> </itemizedlist> - - The data protocol is binary; a complete description is - provided in doc/box-protocol.txt. - -</para> -<para> - separation of ports is done in part to allow system - administrators to secure the read/write port or the - administrative port. The values of read-only, read-write and - administrative ports can be specified in the configuration file. -</para> -<para> - How command line client understands what port to use. + In absence of authentication, this approach allows system + administrators to restrict access to read/write or + administrative ports. The client, however, has to be aware of + the separation, and <command>tarantool</command> command line + client automatically selects the correct port for you + with help of a simple regular expression. SELECTs, UPDATEs, + INSERTs and DELETEs are sent to the primary port, whereas SHOW, + RELOAD, SAVE and others -- to the administrative port. </para> -<!-- <section> + <title>Data manipulation</title> - <title>Data console</title> - - <para>The default data port is 33014. It can be set in the - configuration file. Data console supports asynchronous I/O. - Four commands are supported. For a complete protocol manual, see - developers guide. + <para>Tarantool protocol was designed with focus on asynchronous + I/O and easy integration with proxies. Each client + request starts with a simple binary header, containing three + fields: request type, length, and a numeric id. + </para> + <para> + Four basic request types are supported: INSERT, UPDATE, DELETE + and SELECT. The mandatory length, present in the header, + allows to simplify client or proxy I/O. + The server response to a request always carries in its header + the same command type and request id. + The id makes it possible to always match request to a + response, even if the latter arrived out of order. + </para> + <para>Request type defines the format of the payload. + INSERTs and DELETEs can only be made by the primary key, so + an index id and key value are always present in these requests. + SELECTs and UPDATEs can use secondary keys. UPDATE only needs to + list the fields that are actually changed. With this one + exception, all commands operate on whole tuple(s). </para> + <para>Unless implementing a client driver, one needn't + concern him or her self with the complications of the binary + protocol. <olink targetptr="connectors">Language-specific + drivers</olink> provide a friendly way to store domain + language data structures in Tarantool, and the command line + client supports a subset of the standard SQL. + A complete description of both, the binary protocol and + the supported SQL, is maintained in annotated Backus-Naur + form in the source tree: please see + <link xlink:href="https://github.com/mailru/tarantool/blob/master/doc/box-protocol.txt"><filename>doc/box-protocol.txt</filename></link> + and + <link xlink:href="https://github.com/mailru/tarantool/blob/master/doc/sql.txt"><filename>doc/sql.txt</filename></link> respectively. + </para> + <section> + <title>Memcached protocol</title> + <para>If full access to Tarantool functionality is not needed, + or there is no readily available connector for the + programming language in use, any existing client driver for + Memcached will make do as a Tarantool connector. + To enable Memcached protocol, turn on + <olink targetptr="memcached_port"/> in the option file. + Since Memcached has no notion of namespaces or secondary + indexes, this port only makes it possible to access one + dedicated namespace (see <olink + targetptr="memcached_namespace"/>) via its primary key. + Unless tuple expiration is enabled with <olink + targetptr="memcached_expire"/>, TTL part of the message is + stored but ignored. + </para> + </section> +</section> +<section> + <title>Writing stored procedures in Lua</title> + <para> + Lua. + </para> </section> ---> <section> <title>Administrative console</title> - <para>YAML output. Provide command reference</para> - <para><emphasis xml:id="reload-configuration" role="tntadmin">reload - configuration</emphasis></para> + <para> + The administrative console uses a simple text protocol. + All commands are case-insensitive. + You can connect to the administrative port using any + <command>telnet</command> client, or a tool like + <command>rlwrap</command>, if access to readline features is + desired. Additionally, <command>tarantool</command>, the + SQL-capable command line client, + understands all administrative statements + and automatically directs them to the administrative port. + The server response to an administrative command, even though + is always in plain text, can be quite complex. + It is encoded using YAML markup to simplify automated parsing. + </para> + <para>To learn about all supported administrative commands, you + can type <emphasis role="tntadmin">help</emphasis> in the + administrative console. A reference description also follows + below:</para> + + <variablelist> + + <varlistentry> + <term xml:id="save-snapshot" xreflabel="SAVE SNAPSHOT"> + <emphasis role="tntadmin">save snapshot</emphasis> + </term> + <listitem><para> + Take a snapshot of all data and store it in + <filename><olink + targetptr="snap_dir"/>/<latest-lsn>.snap</filename>. + To take a snapshot, Tarantool forks and quickly + <function>munmap(2)</function>s all memory except one that + stores tuples. Since all modern operating systems support + virtual memory copy-on-write, this effectively creates a + consistent snapshot of all tuples in the child process, + which is then written to disk tuple by tuple. Since a + snapshot is written sequentially, you can expect a very + high write performance (averaging to 70MB/second on modern + disks), which means an average database instance gets + saved in a matter of minutes. Note, that as long as there + are any changes to the parent memory through concurrent + updates, there are going to be page splits, and therefore + you need to have some extra free memory to run this + command. 15%-30% of <olink targetptr="slab_alloc_arena"/> + is, on average, sufficient. + </para></listitem> + </varlistentry> + + + <varlistentry> + <term xml:id="reload-configuration" xreflabel="RELOAD CONFIGURATION"> + <emphasis role="tntadmin">reload configuration</emphasis> + </term> + <listitem><para> + Re-read the configuration file. If the file contains + changes to dynamic parameters, update the runtime + settings. If configuration syntax is incorrect, or a + read-only parameter is changed, produce an error and do + nothing. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="show-configuration" xreflabel="SHOW CONFIGURATION"> + <emphasis role="tntadmin">show configuration</emphasis> + </term> + <listitem><para> + Show the current settings. Displays all settings, + including those that have default values and thus are not + necessarily present in the configuration file. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="show-info" xreflabel="SHOW INFO"> + <emphasis role="tntadmin">show info</emphasis> + </term> + <listitem><para> +<programlisting> +tarantool> show info +--- +info: + version: "1.4.0-30-ge500b95" + uptime: 441524 + pid: 16180 + wal_writer_pid: 16182 + lsn: 15481913304 + recovery_lag: 0.000 + recovery_last_update: 1306964594.980 + status: primary +</programlisting> + </para> + <para> + <emphasis role="strong">recovery_lag</emphasis> holds the + difference (in seconds) between the current time on the + machine (wall clock time) and the time stamp of the last + applied record. In replication setup, this difference can + indicate the delay taking place before a change is + applied to a replica. + </para> + <para> + <emphasis role="strong">recovery_last_update</emphasis> is + the wall clock time of the last change recorded in the + write ahead log. + </para> + <para> + <emphasis role="strong">status</emphasis> is + either "primary" or "hot_standby/<hostname>". + </para> + + </listitem> + </varlistentry> + + <varlistentry> + <term xml:id="show-stat" xreflabel="SHOW STAT"> + <emphasis role="tntadmin">show stat</emphasis> + </term> + <listitem><para> +<programlisting> +tarantool> show stat +--- +statistics: + INSERT: { rps: 139 , total: 48207694 } + SELECT_LIMIT: { rps: 0 , total: 0 } + SELECT: { rps: 1246 , total: 388322317 } + UPDATE_FIELDS: { rps: 1874 , total: 743350520 } + DELETE: { rps: 147 , total: 48902544 } +</programlisting> + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="show-slab" xreflabel="SHOW SLAB"> + <emphasis role="tntadmin">show slab</emphasis> + </term> + <listitem> + <para> + Show the statistics of the slab allocator. The slab + allocator is the main allocator used to store tuples. + This can be used to monitor the total memory use and + memory fragmentation. + </para> + <para> + <emphasis role="strong">items_used</emphasis> contains + the % of <olink targetptr="slab_alloc_arena"/> already + used to store tuples. + </para> + <para> + <emphasis role="strong">arena_used</emphasis> contains + the % of <olink targetptr="slab_alloc_arena"/> that is + already distributed to the slab allocator. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term xml:id="show-palloc" xreflabel="SHOW PALLOC"> + <emphasis role="tntadmin">show palloc</emphasis> + </term> + <listitem><para> + A pool allocator is used for temporary memory, when + serving client requests. Every fiber has an own + pool. Shows the current state of pools of all fibers. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="save-coredump" xreflabel="SAVE COREDUMP"> + <emphasis role="tntadmin">SAVE COREDUMP</emphasis> + </term> + <listitem><para> + Fork and dump a core. Since Tarantool stores all tuples + in memory, it can take some time. Mainly useful for + debugging. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="show-fiber" xreflabel="SHOW FIBER"> + <emphasis role="tntadmin">show fiber</emphasis> + </term> + <listitem><para> + Show all running fibers, with their stack. + Mainly useful for debugging. + </para></listitem> + </varlistentry> + + </variablelist> + </section> </chapter> diff --git a/doc/user/namespace.xml b/doc/user/namespace.xml new file mode 100644 index 0000000000..781a800174 --- /dev/null +++ b/doc/user/namespace.xml @@ -0,0 +1,108 @@ +<para xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xi="http://www.w3.org/2001/XInclude" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml:id="namespace"> +<bridgehead>Namespace settings explained</bridgehead> +Namespace is a composite parameter, i.e. it has properties. +<programlisting language="cpp"> +/* + * Each tuple consists of fields. Three field types are + * supported. + */ + +enum { STR, NUM, NUM64 } field_type; + +/* + * Tarantool is interested in field types only inasmuch as + * it needs to build indexes on fields. An index + * can cover one or more fields. + */ + +struct index_field_t { + unsigned int fieldno; + enum field_type type; +}; + +/* + * HASH and TREE index types are supported. + */ + +enum { HASH, TREE } index_type; + +struct index_t { + index_field_t key_field[]; + enum index_type type; + /* Secondary index may be non-unique */ + bool unique; +}; + +struct namespace_t +{ + /* A namespace can be quickly disabled and re-enabled at run time. */ + bool enabled; + /* + * A limit on tuple cardinality can be set, to prevent too large tuples + * from coming in. + */ + unsigned int cardinality; + /* Only used for HASH indexes, to preallocate memory. */ + unsigned int estimated_rows; + struct index_t index[]; +}; + +/* You can define up to 255 namespaces. */ +struct namespace_t namespace[]; +</programlisting> +The way a namespace is defined in a configuration file is similar to how +you would initialize a C structure in a program. For example, +a minimal storage configuration looks like below: +<programlisting language="c"> +namespace[0].enabled = 1 +namespace[0].index[0].type = HASH +namespace[0].index[0].unique = 1 +namespace[0].index[0].key_field[0].fieldno = 0 +namespace[0].index[0].key_field[0].type = NUM64 +</programlisting> +The parameters listed above are mandatory. Other namespace +properties are set in the same way. +An alternative syntax, mainly useful when defining large namespaces, exists: +<programlisting language="c"> +namespace[0] = { + enabled = 1, + index = [ + { + type = HASH, + key_field = [ + { + fieldno = 0, + type = NUM64 + } + ] + } + ] +} +</programlisting> +When defining a namespace, +please be aware of these restrictions: +<itemizedlist> + <listitem><simpara>at least one namespace must be + configured,</simpara></listitem> + <listitem><simpara>each configured namespace needs at least one + unique index of type HASH, + </simpara></listitem> + <listitem><simpara>"unique" property doesn't have a default, and + must be set explicitly, + </simpara></listitem> + <listitem><simpara>namespace configuration can not be changed + dynamically, currently you need to restart the server even to + disable or enable a namespace, + </simpara></listitem> + <listitem><simpara>HASH indexes may cover only one field and can + not be non-unique. + </simpara></listitem> +</itemizedlist> +</para> +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/user/preface.xml b/doc/user/preface.xml index bbe0106d35..09b6362682 100644 --- a/doc/user/preface.xml +++ b/doc/user/preface.xml @@ -74,7 +74,8 @@ one of the leading Russian web content providers. At Mail.Ru, the sowtware serves the <quote>hottest</quote> data, such as online users and their sessions, online application - properties, the map between users and their serving shards. + properties, mapping between users and their serving shards, + and so on. </para> <para> @@ -96,13 +97,11 @@ xlink:href="http://www.docbook.org/tdg5/en/html/docbook.html">DocBook 5</citetitle> XML markup language and is using the standard <citetitle xlink:href="http://docbook.sourceforge.net/release/xsl/current/doc/">DocbBook - XSL</citetitle> formatting conventions: - </para> + XSL</citetitle> formatting conventions:</para> <para> UNIX shell command input is prefixed with '$ ' and is formatted using a fixed-width font: - <programlisting> - <prompt>$ </prompt>tarantool_box <option>--daemonize</option> + <programlisting><prompt>$ </prompt>tarantool_box <option>--daemonize</option> </programlisting> </para> <para> @@ -138,11 +137,11 @@ </para> <para> <emphasis role="strong">Caution:</emphasis> To prevent spam, Launchpad - mailing list software silently drops all mail sent by - unregistered users. Registration also - allows you to report bug and create feature requests. + mailing list software silently drops all mail sent from + non-registered email addresses. Launchpad registration also + allows you to report bugs and create feature requests. You can always check whether or not your mail has been - delivered in the public mailing list archive, <link + delivered to the mailing list in the public list archive, <link xlink:href="https://lists.launchpad.net/tarantool-developers"/>. </para> </section> diff --git a/doc/user/proctitle.xml b/doc/user/proctitle.xml new file mode 100644 index 0000000000..23be03ca57 --- /dev/null +++ b/doc/user/proctitle.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE book [ +<!ENTITY % tnt SYSTEM "../tnt.ent"> +%tnt; +]> +<appendix xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml:id="proctitle"> + +<title>Server process titles</title> + +<para> + Linux and FreeBSD operating systems allow a running process to + modify its title, which otherwise contains the program name. + Tarantool uses this feature to aid to needs of system + administration, such as figuring out what services are running + on a host, TCP/IP ports in use, et cetera. +</para> +<para> + Tarantool process title follows the following naming scheme: + <command><replaceable>program_name</replaceable>: <replaceable>role</replaceable>[@<olink targetptr="custom_proc_title"/>] [ports in use]</command> +</para> +<para> + <emphasis role="strong">program_name</emphasis> is typically + <command>tarantool_box</command>. The role can be one of the + following: + <itemizedlist> + <listitem><para> + <emphasis role="strong">primary</emphasis> -- the master node, + </para></listitem> + <listitem><para> + <emphasis role="strong">replica/<constant>IP</constant>:<constant>port</constant></emphasis> -- a replication node, + </para></listitem> + <listitem><para> + <emphasis role="strong">wal_writer</emphasis> -- a write + ahead log management process (always pairs up with the main + process, be it primary or replica). + </para></listitem> + <listitem><para> + <emphasis role="strong">replication_server </emphasis>-- + runs only if <olink targetptr="replication_port"/> is set, + accepts connections on this port and creates a + </para></listitem> + <listitem><para> + <emphasis role="strong">replication_relay </emphasis>-- a + process that servers a single replication connection. + </para></listitem> + </itemizedlist> + Possible port names are: <quote>pri</quote> for + <olink targetptr="primary_port"/>, <quote>sec</quote> for <olink + targetptr="secondary_port"/>, <quote>adm</quote> for <olink + targetptr="admin_port"/> and <quote>memcached</quote> for <olink + targetptr="memcached_port"/>. +</para> +<para> + For example: + <itemizedlist> + <listitem><para> + <command>tarantool_box: primary pri:50000 sec:50001 adm:50002</command> + </para></listitem> + <listitem><para> + <command>tarantool_box: primary@infobox pri:15013 sec:15523 adm:10012</command> + </para></listitem> + <listitem><para> + <command>tarantool_box: wal_writer</command> + </para></listitem> + </itemizedlist> +</para> +</appendix> + +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/user/replication.xml b/doc/user/replication.xml new file mode 100644 index 0000000000..ffa5a607da --- /dev/null +++ b/doc/user/replication.xml @@ -0,0 +1,164 @@ +<!DOCTYPE book [ +<!ENTITY % tnt SYSTEM "../tnt.ent"> +%tnt; +]> +<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml:id="replication"> + +<title>Replication</title> +<blockquote><para> + To set up replication, it's necessary to prepare the master, + configure a replica, and establish procedures for recovery from + a degraded state. +</para></blockquote> + +<section> + <title>Setting up the master</title> + <para> + To prepare the master for connections from replica, it's only + necessary to enable <olink targetptr="replication_port"/> in + the configuration file. An example configuration file can be + found in <link + xlink:href="https://github.com/mailru/tarantool/blob/master/test/box_replication/tarantool.cfg"><filename>test/box_replication/tarantool.cfg</filename></link>. A master with enabled replication_port can accept connections + from as many replicas as necessary on that port. Each replica + has its own replication state. + </para> +</section> +<section> + <title>Setting up a replica</title> + <para> + Replica gets all updates from the master by simply shipping + the write ahead log (WAL) and applying it. + Each record in the WAL has a log sequence number + (LSN), operation type (INSERT, UPDATE, DELETE) and a + timestamp. + </para> + <para> + For replication to work correctly, the latest LSN + on the replica must match or fall behind the latest LSN + on the master. If the replica has its own updates, + this leads to it getting out of sync, since + updates from the master having identical LSNs are + not applied. Indeed, if replication is on, Tarantool + does not accept updates, even on its <olink + targetptr="primary_port"/>. + </para> + <para> + Tarantool always requires a valid snapshot file to boot from: + it should be prepared with <olink targetptr="init-storage-option"/> option or copied from the master. + </para> + <para> + To start replication, configure <olink + targetptr="replication_source_port"/> and <olink + targetptr="replication_source_ipaddr"/>. + Other parameters can also be changed, but existing namespaces and + their primary keys on the replica must be identical to ones on the + master. + </para> + <para> + Once connected to the master, the replica requests all changes + that happened after the latest local LSN. It is therefore + necessary to keep WAL files on the master host as long as + there are replicas that haven't applied them yet. An example + configuration can be found in <link + xlink:href="https://github.com/mailru/tarantool/blob/master/test/box_replication/tarantool_slave.cfg"><filename>test/box_replication/tarantool_slave.cfg</filename></link>. + </para> + <para> + In absence of WALs, a replica can be "seeded" at any time + with a snapshot file, manually copied from the master. + </para> + <note><simpara> + Replication parameters are "dynamic", which allows the + replica to become a master and vice versa with help of + <olink targetptr="reload-configuration"/> statement. + </simpara></note> + +</section> +<section> + <title>Recovering from a degraded state</title> + <para> + "Degraded state" is a situation when the master becomes + unavailable -- either due to hardware or network failure, or a + programming bug. There is no reliable way for a replica to detect + that the master is gone for all, since sources of failure and + replication environments vary significantly. + </para> + <para> + A separate monitoring script (or scripts, if decision making + quorum is desirable) is necessary to detect a master failure. + Such script would typically try to update a tuple in an + auxiliary namespace on the master, and raise alarm if a + network or disk error persists longer than is acceptable. + </para> + <para> + When a master failure is detected, the following needs + to be done: + <itemizedlist> + <listitem> + <para> + First and foremost, make sure that the master does not + accepts updates. This is necessary to prevent the + situation when, should the master failure end up being + transient, some updates still go to the master, while + others already end up on the replica. + </para> + <para> + If the master is available, the easiest way to turn + on read-only mode is to turn Tarantool into a replica of + itself. This can be done by setting master's <olink + targetptr="replication_source_ipaddr"/> and <olink + targetptr="replication_source_port"/> to point to self. + </para> + <para> + If the master is not available, best bet is to log into + the machine and kill the server, or change the + machine's network configuration (DNS, IP address). + </para> + <para> + If the machine is not available, it's perhaps prudent + to power it off. + </para> + </listitem> + <listitem> + <para> + Record the replica's LSN, by issuing <olink + targetptr="show-info"/>. This LSN may prove useful if + there are updates on the master that never reached + the replica. + </para> + </listitem> + <listitem> + <para> + Propagate the replica to become a master. This is done + by setting <olink targetptr="replication_source_port"/> + on replica to <constant>0</constant>. + </para> + </listitem> + <listitem> + <para> + Change the application configuration to point to the new + master. This can be done either by changing the + application's internal routing table, or by setting up + old master's IP address on the new master's machine, or + using some other approach. + </para> + </listitem> + <listitem> + <para> + Recover the old master. If there are updates that didn't + make it to the new master, they have to be applied + manually. You can use <olink targetptr="cat-option"/> + option to read server logs. + </para> + </listitem> + </itemizedlist> + </para> +</section> + +</chapter> + +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/user/target.db b/doc/user/target.db index 7080cd3db8..928dca484a 100644 --- a/doc/user/target.db +++ b/doc/user/target.db @@ -1 +1 @@ -<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool/Box User Guide, version 1.4.0-69-g21aaa81</ttl><xreftext>Tarantool/Box User Guide, version 1.4.0-69-g21aaa81</xreftext><div element="chapter" href="#id77162" number="1"><ttl>Preface</ttl><xreftext>Chapter 1, <i>Preface</i></xreftext><div element="section" href="#preface" number="" targetptr="preface"><ttl>Tarantool/Box: an overview</ttl><xreftext>the section called “Tarantool/Box: an overviewâ€</xreftext></div><div element="section" href="#id284163" number=""><ttl>Conventions</ttl><xreftext>the section called “Conventionsâ€</xreftext></div><div element="section" href="#id283612" number=""><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugsâ€</xreftext></div></div><div element="chapter" href="#id283358" number="2"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext></div><div element="chapter" href="#id285778" number="3"><ttl>Dynamic data model</ttl><xreftext>Chapter 3, <i>Dynamic data model</i></xreftext></div><div element="chapter" href="#language-reference" number="4" targetptr="language-reference"><ttl>Language reference</ttl><xreftext>Chapter 4, <i>Language reference</i></xreftext><div element="section" href="#id286284" number=""><ttl>Administrative console</ttl><xreftext>the section called “Administrative consoleâ€</xreftext><obj element="emphasis" href="#reload-configuration" number="" targetptr="reload-configuration"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div></div><div element="chapter" href="#configuration-reference" number="5" targetptr="configuration-reference"><ttl>Configuration reference</ttl><xreftext>Chapter 5, <i>Configuration reference</i></xreftext><div element="section" href="#id286637" number=""><ttl>Command line options</ttl><xreftext>the section called “Command line optionsâ€</xreftext><obj element="listitem" href="#help-option" number="" targetptr="help-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#version-option" number="" targetptr="version-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#config-option" number="" targetptr="config-option"><ttl>???TITLE???</ttl><xreftext/></obj></div><div element="section" href="#id286190" number=""><ttl>The option file</ttl><xreftext>the section called “The option fileâ€</xreftext></div></div></div> +<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool/Box User Guide, version 1.4.1-39-g93bf87f</ttl><xreftext>Tarantool/Box User Guide, version 1.4.1-39-g93bf87f</xreftext><div element="chapter" href="#id276861" number="1"><ttl>Preface</ttl><xreftext>Chapter 1, <i>Preface</i></xreftext><div element="section" href="#preface" number="" targetptr="preface"><ttl>Tarantool/Box: an overview</ttl><xreftext>the section called “Tarantool/Box: an overviewâ€</xreftext></div><div element="section" href="#id275832" number=""><ttl>Conventions</ttl><xreftext>the section called “Conventionsâ€</xreftext></div><div element="section" href="#id275906" number=""><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugsâ€</xreftext></div></div><div element="chapter" href="#id278073" number="2"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext></div><div element="chapter" href="#id278088" number="3"><ttl>Dynamic data model</ttl><xreftext>Chapter 3, <i>Dynamic data model</i></xreftext></div><div element="chapter" href="#language-reference" number="4" targetptr="language-reference"><ttl>Language reference</ttl><xreftext>Chapter 4, <i>Language reference</i></xreftext><div element="section" href="#id276237" number=""><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulationâ€</xreftext><div element="section" href="#id276287" number=""><ttl>Memcached protocol</ttl><xreftext>the section called “Memcached protocolâ€</xreftext></div></div><div element="section" href="#id276318" number=""><ttl>Writing stored procedures in Lua</ttl><xreftext>the section called “Writing stored procedures in Luaâ€</xreftext></div><div element="section" href="#id276329" number=""><ttl>Administrative console</ttl><xreftext>the section called “Administrative consoleâ€</xreftext><obj element="term" href="#save-snapshot" number="" targetptr="save-snapshot"><ttl>???TITLE???</ttl><xreftext>SAVE SNAPSHOT</xreftext></obj><obj element="term" href="#reload-configuration" number="" targetptr="reload-configuration"><ttl>???TITLE???</ttl><xreftext>RELOAD CONFIGURATION</xreftext></obj><obj element="term" href="#show-configuration" number="" targetptr="show-configuration"><ttl>???TITLE???</ttl><xreftext>SHOW CONFIGURATION</xreftext></obj><obj element="term" href="#show-info" number="" targetptr="show-info"><ttl>???TITLE???</ttl><xreftext>SHOW INFO</xreftext></obj><obj element="term" href="#show-stat" number="" targetptr="show-stat"><ttl>???TITLE???</ttl><xreftext>SHOW STAT</xreftext></obj><obj element="term" href="#show-slab" number="" targetptr="show-slab"><ttl>???TITLE???</ttl><xreftext>SHOW SLAB</xreftext></obj><obj element="term" href="#show-palloc" number="" targetptr="show-palloc"><ttl>???TITLE???</ttl><xreftext>SHOW PALLOC</xreftext></obj><obj element="term" href="#save-coredump" number="" targetptr="save-coredump"><ttl>???TITLE???</ttl><xreftext>SAVE COREDUMP</xreftext></obj><obj element="term" href="#show-fiber" number="" targetptr="show-fiber"><ttl>???TITLE???</ttl><xreftext>SHOW FIBER</xreftext></obj></div></div><div element="chapter" href="#replication" number="5" targetptr="replication"><ttl>Replication</ttl><xreftext>Chapter 5, <i>Replication</i></xreftext><div element="section" href="#id278677" number=""><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the masterâ€</xreftext></div><div element="section" href="#id278701" number=""><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replicaâ€</xreftext></div><div element="section" href="#id278788" number=""><ttl>Recovering from a degraded state</ttl><xreftext>the section called “Recovering from a degraded stateâ€</xreftext></div></div><div element="chapter" href="#configuration-reference" number="6" targetptr="configuration-reference"><ttl>Configuration reference</ttl><xreftext>Chapter 6, <i>Configuration reference</i></xreftext><div element="section" href="#id281471" number=""><ttl>Command line options</ttl><xreftext>the section called “Command line optionsâ€</xreftext><obj element="listitem" href="#help-option" number="" targetptr="help-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#version-option" number="" targetptr="version-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#config-option" number="" targetptr="config-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="option" href="#init-storage-option" number="" targetptr="init-storage-option"><ttl>???TITLE???</ttl><xreftext>--init-storage</xreftext></obj><obj element="option" href="#cat-option" number="" targetptr="cat-option"><ttl>???TITLE???</ttl><xreftext>--cat</xreftext></obj></div><div element="section" href="#option-file" number="" targetptr="option-file"><ttl>The option file</ttl><xreftext>option file</xreftext><obj element="table" href="#id281556" number="6.1"><ttl>Basic parameters</ttl><xreftext>Table 6.1, “Basic parametersâ€</xreftext></obj><obj element="entry" href="#wal_dir" number="" targetptr="wal_dir"><ttl>???TITLE???</ttl><xreftext>wal_dir</xreftext></obj><obj element="entry" href="#snap_dir" number="" targetptr="snap_dir"><ttl>???TITLE???</ttl><xreftext>snap_dir</xreftext></obj><obj element="entry" href="#primary_port" number="" targetptr="primary_port"><ttl>???TITLE???</ttl><xreftext>primary_port</xreftext></obj><obj element="entry" href="#secondary_port" number="" targetptr="secondary_port"><ttl>???TITLE???</ttl><xreftext>secondary_port</xreftext></obj><obj element="entry" href="#admin_port" number="" targetptr="admin_port"><ttl>???TITLE???</ttl><xreftext>admin_port</xreftext></obj><obj element="entry" href="#custom_proc_title" number="" targetptr="custom_proc_title"><ttl>???TITLE???</ttl><xreftext>custom_proc_title</xreftext></obj><obj element="table" href="#id281961" number="6.2"><ttl>Configuring the storage</ttl><xreftext>Table 6.2, “Configuring the storageâ€</xreftext></obj><obj element="anchor" href="#slab_alloc_arena" number="" targetptr="slab_alloc_arena"><ttl>???TITLE???</ttl><xreftext>slab_alloc_arena</xreftext></obj><obj element="para" href="#namespace" number="" targetptr="namespace"><ttl>???TITLE???</ttl><xreftext>the section called “The option fileâ€</xreftext></obj><obj element="table" href="#id282262" number="6.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 6.3, “Binary logging and snapshotsâ€</xreftext></obj><obj element="table" href="#id282524" number="6.4"><ttl>Replication</ttl><xreftext>Table 6.4, “Replicationâ€</xreftext></obj><obj element="entry" href="#replication_port" number="" targetptr="replication_port"><ttl>???TITLE???</ttl><xreftext>replication_port</xreftext></obj><obj element="entry" href="#replication_source_port" number="" targetptr="replication_source_port"><ttl>???TITLE???</ttl><xreftext>replication_source_port</xreftext></obj><obj element="entry" href="#replication_source_ipaddr" number="" targetptr="replication_source_ipaddr"><ttl>???TITLE???</ttl><xreftext>replication_source_ipaddr</xreftext></obj><obj element="table" href="#id282717" number="6.5"><ttl>Networking</ttl><xreftext>Table 6.5, “Networkingâ€</xreftext></obj><obj element="table" href="#id282874" number="6.6"><ttl>Logging</ttl><xreftext>Table 6.6, “Loggingâ€</xreftext></obj><obj element="table" href="#id283081" number="6.7"><ttl>Memcached protocol support</ttl><xreftext>Table 6.7, “Memcached protocol supportâ€</xreftext></obj><obj element="anchor" href="#memcached_port" number="" targetptr="memcached_port"><ttl>???TITLE???</ttl><xreftext>memcached_port</xreftext></obj><obj element="anchor" href="#memcached_namespace" number="" targetptr="memcached_namespace"><ttl>???TITLE???</ttl><xreftext>memcached_namespace</xreftext></obj><obj element="anchor" href="#memcached_expire" number="" targetptr="memcached_expire"><ttl>???TITLE???</ttl><xreftext>memcached_expire</xreftext></obj></div></div><div element="chapter" href="#connectors" number="7" targetptr="connectors"><ttl>Connectors</ttl><xreftext>Chapter 7, <i>Connectors</i></xreftext><div element="section" href="#id280207" number=""><ttl>C</ttl><xreftext>the section called “Câ€</xreftext></div><div element="section" href="#id279967" number=""><ttl>Perl</ttl><xreftext>the section called “Perlâ€</xreftext></div><div element="section" href="#id278939" number=""><ttl>PHP</ttl><xreftext>the section called “PHPâ€</xreftext></div><div element="section" href="#id278950" number=""><ttl>Python</ttl><xreftext>the section called “Pythonâ€</xreftext></div><div element="section" href="#id278961" number=""><ttl>Ruby</ttl><xreftext>the section called “Rubyâ€</xreftext></div></div><div element="appendix" href="#proctitle" number="A" targetptr="proctitle"><ttl>Server process titles</ttl><xreftext>Appendix A, <i>Server process titles</i></xreftext></div><div element="appendix" href="#errcode" number="B" targetptr="errcode"><ttl>List of error codes</ttl><xreftext>Appendix B, <i>List of error codes</i></xreftext><obj element="term" href="#ERR_CODE_NONMASTER" number="" targetptr="ERR_CODE_NONMASTER"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_NONMASTER</xreftext></obj><obj element="term" href="#ERR_CODE_ILLEGAL_PARAMS" number="" targetptr="ERR_CODE_ILLEGAL_PARAMS"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_ILLEGAL_PARAMS</xreftext></obj><obj element="term" href="#ERR_CODE_NODE_IS_RO" number="" targetptr="ERR_CODE_NODE_IS_RO"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_NODE_IS_RO</xreftext></obj><obj element="term" href="#ERR_CODE_MEMORY_ISSUE" number="" targetptr="ERR_CODE_MEMORY_ISSUE"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_MEMORY_ISSUE</xreftext></obj><obj element="term" href="#ERR_CODE_WAL_IO" number="" targetptr="ERR_CODE_WAL_IO"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_WAL_IO</xreftext></obj><obj element="term" href="#ERR_CODE_INDEX_VIOLATION" number="" targetptr="ERR_CODE_INDEX_VIOLATION"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_INDEX_VIOLATION</xreftext></obj><obj element="term" href="#ERR_CODE_NO_SUCH_NAMESPACE" number="" targetptr="ERR_CODE_NO_SUCH_NAMESPACE"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_NO_SUCH_NAMESPACE</xreftext></obj><obj element="term" href="#ERR_CODE_NO_SUCH_INDEX" number="" targetptr="ERR_CODE_NO_SUCH_INDEX"><ttl>???TITLE???</ttl><xreftext>ERR_CODE_NO_SUCH_INDEX</xreftext></obj></div></div> diff --git a/doc/user/tnt-fo.xsl b/doc/user/tnt-fo.xsl new file mode 100644 index 0000000000..6952f3bfca --- /dev/null +++ b/doc/user/tnt-fo.xsl @@ -0,0 +1,14 @@ +<?xml version='1.0'?> +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" + xmlns:xslthl="http://xslthl.sf.net"> + +<xsl:import href="http://docbook.sourceforge.net/release/xsl-ns/current/fo/docbook.xsl"/> + +<xsl:param name="generate.toc" select="'book toc'"/> +<xsl:param name="fop1.extentions">1</xsl:param> +<xsl:param name="paper.type">A4</xsl:param> +<xsl:param name="highlight.source" select="1"/> +<xsl:param name="highlight.xslthl.config">file:////usr/share/xml/docbook/stylesheet/docbook-xsl-ns/highlighting/xslthl-config.xml</xsl:param> + +</xsl:stylesheet> diff --git a/doc/user/tnt-html.xsl b/doc/user/tnt-html.xsl index 107ef6681c..e1edda2131 100644 --- a/doc/user/tnt-html.xsl +++ b/doc/user/tnt-html.xsl @@ -1,9 +1,32 @@ <?xml version='1.0'?> <xsl:stylesheet - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" + xmlns:xslthl="http://xslthl.sf.net"> <xsl:import href="http://docbook.sourceforge.net/release/xsl-ns/current/html/docbook.xsl"/> +<xsl:import href="html-highlight.xsl"/> + +<xsl:param name="generate.toc" select="'book toc'"/> <xsl:param name="html.stylesheet" select="'tnt.css'"/> +<xsl:param name="highlight.source" select="1"/> +<xsl:param name="highlight.xslthl.config">file:////usr/share/xml/docbook/stylesheet/docbook-xsl-ns/highlighting/xslthl-config.xml</xsl:param> + +<!-- Add Google Analytics to the generated html--> + +<xsl:template name="user.head.content"> + <script type="text/javascript"> + + var _gaq = _gaq || []; + _gaq.push(['_setAccount', 'UA-22120502-1']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> +</xsl:template> </xsl:stylesheet> diff --git a/doc/user/tnt.css b/doc/user/tnt.css index fbf0df02eb..28bf7088da 100644 --- a/doc/user/tnt.css +++ b/doc/user/tnt.css @@ -4,3 +4,13 @@ text-transform: uppercase; color: green; } + +.hl-keyword { + color: green; + font-weight: bold; +} + +.hl-comment{ + color: blue; + font-weight: bold; +} diff --git a/doc/user/tutorial.xml b/doc/user/tutorial.xml index 2b9b147321..201be01f5a 100644 --- a/doc/user/tutorial.xml +++ b/doc/user/tutorial.xml @@ -34,13 +34,14 @@ To build Tarantool from source, additionally: <itemizedlist> <listitem><para>CMake 2.6 or newer,</para></listitem> - <listitem><para>GCC 4.4 or newer.</para></listitem> + <listitem><para>GCC 4.4 or newer, with gcc-objc (ObjectiveC) + language frontend.</para></listitem> </itemizedlist> </para> <para> After download, unpack the binary package, an own directory will be created: <programlisting> - <prompt>$ </prompt><command>tar</command> <option>zxvf</option> <filename>package-name.tar.gz</filename></programlisting> + <prompt>$ </prompt><command>tar</command> <option>zxvf</option> <filename><replaceable><replaceable>package-name</replaceable></replaceable>.tar.gz</filename></programlisting> The binary download contains just two subdirectories: <filename>bin</filename> and <filename>doc</filename>. The server, by default, looks for its configuration file in @@ -49,7 +50,7 @@ <filename>bin</filename>, thus the server can be started right out of it: <programlisting> - <prompt>$ </prompt><command>cd package-name/bin && ./tarantool_box</command> + <prompt>$ </prompt><command>cd <replaceable>package-name</replaceable>/bin && ./tarantool_box</command> ... 1301424353.416 3459 104/33013/acceptor _ I> I am primary 1301424353.416 3459 1/sched _ I> initialized</programlisting> @@ -60,7 +61,7 @@ Once the server is started, you can connect to it and issue queries using a command line client implemented in Python: <programlisting> - <prompt>$ </prompt><command>cd package-name/bin && ./tarantool</command> + <prompt>$ </prompt><command>cd <replaceable>package-name</replaceable>/bin && ./tarantool</command> <prompt>tarantool> </prompt> <userinput>show info</userinput> <computeroutput> --- @@ -81,7 +82,7 @@ necessary: configuration and build. The easiest way to configure a source directory with CMake is by requesting an in-source build: <programlisting> - <prompt>$ </prompt><command>cd</command> <filename>package-name</filename> && <command>cmake</command> .</programlisting> + <prompt>$ </prompt><command>cd</command> <filename><replaceable>package-name</replaceable></filename> && <command>cmake</command> .</programlisting> Upon successful configuration, CMake prints the status of optional features: <programlisting> @@ -114,7 +115,8 @@ <para> Congratulations, you have the server up and running. Check out the remaining chapters of this manual to learn - more about available commands, contents of tarantool.cfg, + more about available commands, contents of + <filename>tarantool.cfg</filename>, replication and high availability with Tarantool. </para> </sidebar> diff --git a/doc/user/user.xml b/doc/user/user.xml index 9f859bde2a..2ae51a5595 100644 --- a/doc/user/user.xml +++ b/doc/user/user.xml @@ -12,63 +12,13 @@ <xi:include href="tutorial.xml"/> <xi:include href="data-model.xml"/> <xi:include href="language-reference.xml"/> -<xi:include href="configuration-reference.xml"/> -<!-- <xi:include href="replication.xml"/> -<xi:include href="memcached.xml"/> -<xi:include href="configuration.xml"/> -<xi:include href="logging.xml"/> +<xi:include href="configuration-reference.xml"/> <xi:include href="connectors.xml"/> -<xi:include href="appendix.xml"/> ---> +<xi:include href="proctitle.xml"/> +<xi:include href="errcode.xml"/> <!-- - TOC: - - Introduction - What it can basically do; - - Installation and Running - Command line options reference - - Data console and administrative console - Data operations - Administrative console operations - Format of response - - Setting up replication - Master-slave replication - - Support of memcached protocol - - Configuration reference - - Log file messages - - Format of the binary log/snapshot - - Tarantool command line shell - - Connectors - C - Ruby - Example - Perl - - Product release cycle - - Frequently Asked Questions - Q. What's on your roadmap? - Q. I found a bug. What to do? - What can possibly go wrong during compile: - as exception - old python - - confetti not found - explain what is going on - gcc compilation error: type 'VERBOSE=1 make' and - check out the exact error. - - Appendixes: - Configuration parameters index - Server error codes - Glossary of terms +<xi:include href="faq.xml"/> --> </book> <!-- diff --git a/include/errcode.h b/include/errcode.h index 71d239557a..ba7ad4e1e7 100644 --- a/include/errcode.h +++ b/include/errcode.h @@ -11,6 +11,17 @@ struct errcode_record { uint8_t errflags; }; +/* + * To add a new error code to Tarantool, extend this array. Please + * try to reuse empty slots (ERR_CODE_UNUSED*), if there are any + * left. + * + * !IMPORTANT! Currently you need to manually update the user + * guide (doc/user/errcode.xml) and the Python command line client + * (test/lib/sql_ast.py) with each added error code. Please don't + * forget to do it! + */ + #define ERROR_CODES(_) \ /* 0 */_(ERR_CODE_OK, 0, "OK") \ /* 1 */_(ERR_CODE_NONMASTER, 2, "Non master connection, but it should be") \ @@ -55,7 +66,7 @@ struct errcode_record { /* 37 */_(ERR_CODE_UPDATE_ID, 2, "Id's update") \ /* 38 */_(ERR_CODE_WRONG_VERSION, 2, "Unsupported version of protocol") \ /* end of silversearch error codes */ \ - /* 39 */_(ERR_CODE_UNKNOWN_ERROR, 2, "Unknown error") \ + /* 39 */_(ERR_CODE_WAL_IO, 2, "Failed to write to disk") \ /* 40 */_(ERR_CODE_UNUSED40, 0, "Unused40") \ /* 41 */_(ERR_CODE_UNUSED41, 0, "Unused41") \ /* 42 */_(ERR_CODE_UNUSED42, 0, "Unused42") \ @@ -72,10 +83,16 @@ struct errcode_record { /* 53 */_(ERR_CODE_UNUSED53, 0, "Unused53") \ /* 54 */_(ERR_CODE_UNUSED54, 0, "Unused54") \ /* 55 */_(ERR_CODE_NODE_FOUND, 2, "Node is found") \ - /* 56 */_(ERR_CODE_INDEX_VIOLATION, 2, "Some index violation occur") \ + /* 56 */_(ERR_CODE_INDEX_VIOLATION, 2, "Constraint violation") \ /* 57 */_(ERR_CODE_NO_SUCH_NAMESPACE, 2, "There is no such namespace") \ _(ERR_CODE_NO_SUCH_INDEX, 2, "No index with the given id is defined") + +/* + * !IMPORTANT! Please see an instruction how to add !IMPORTANT! + * !IMPORTANT! new errors at start of the file !IMPORTANT! + */ + ENUM0(tnt_error_codes_enum, ERROR_CODES); extern struct errcode_record tnt_error_codes[]; diff --git a/include/tbuf.h b/include/tbuf.h index ee07a38f10..63a45e344c 100644 --- a/include/tbuf.h +++ b/include/tbuf.h @@ -63,6 +63,16 @@ size_t tbuf_reserve(struct tbuf *b, size_t count); void tbuf_reset(struct tbuf *b); void *tbuf_peek(struct tbuf *b, size_t count); +/** + * Remove count bytes from the beginning, and adjust all sizes + * accordingly. + * + * @param count the number of bytes to forget about. + * + * @pre 0 <= count <= tbuf->len + */ +void tbuf_ltrim(struct tbuf *b, size_t count); + void tbuf_append_field(struct tbuf *b, void *f); void tbuf_vprintf(struct tbuf *b, const char *format, va_list ap) __attribute__ ((format(FORMAT_PRINTF, 2, 0))); diff --git a/mod/box/box.m b/mod/box/box.m index 20a4cf15ba..0f49c4cefe 100644 --- a/mod/box/box.m +++ b/mod/box/box.m @@ -823,7 +823,7 @@ txn_commit(struct box_txn *txn) i64 lsn = next_lsn(recovery_state, 0); if (!wal_write(recovery_state, wal_tag, fiber->cookie, lsn, t)) - tnt_raise(tnt_BoxException, errcode:ERR_CODE_UNKNOWN_ERROR); + tnt_raise(tnt_BoxException, errcode:ERR_CODE_WAL_IO); confirm_lsn(recovery_state, lsn); } @@ -1070,7 +1070,7 @@ custom_init(void) before_commit_update_hook = calloc(1, sizeof(box_hook_t)); if (cfg.namespace == NULL) - panic("at least one namespace should be configured"); + panic("at least one namespace must be configured"); for (int i = 0; i < namespace_count; i++) { if (cfg.namespace[i] == NULL) @@ -1166,7 +1166,7 @@ custom_init(void) if (strcmp(cfg.namespace[i]->index[j]->type, "HASH") == 0) { if (index->key_cardinality != 1) panic("(namespace = %" PRIu32 " index = %" PRIu32 ") " - "hash index must have single-filed key", i, j); + "hash index must have a single-field key", i, j); if (index->unique == false) panic("(namespace = %" PRIu32 " index = %" PRIu32 ") " @@ -1221,7 +1221,7 @@ box_process(struct box_txn *txn, u32 op, struct tbuf *request_data) say_error("tnt_PickleException: `%s' at %s:%i", e->reason, e->file, e->line); - return ERR_CODE_UNKNOWN_ERROR; + return ERR_CODE_ILLEGAL_PARAMS; } @catch (tnt_BoxException *e) { txn_abort(txn); @@ -1324,10 +1324,10 @@ title(const char *fmt, ...) va_end(ap); if (cfg.memcached) - set_proc_title("memcached:%s%s pri:%i adm:%i", + set_proc_title("%s%s memcached:%i adm:%i", buf, custom_proc_title, cfg.primary_port, cfg.admin_port); else - set_proc_title("box:%s%s pri:%i sec:%i adm:%i", + set_proc_title("%s%s pri:%i sec:%i adm:%i", buf, custom_proc_title, cfg.primary_port, cfg.secondary_port, cfg.admin_port); } @@ -1336,19 +1336,19 @@ static void remote_recovery_restart(struct tarantool_cfg *conf) { if (remote_recover) { - say_info("shuting downing remote hot standby"); + say_info("shutting downing the replica"); fiber_call(remote_recover); } - say_info("starting remote hot standby"); + say_info("starting the replica"); remote_recover = recover_follow_remote(recovery_state, conf->wal_feeder_ipaddr, conf->wal_feeder_port, default_remote_row_handler); status = palloc(eter_pool, 64); - snprintf(status, 64, "hot_standby/%s:%i%s", conf->wal_feeder_ipaddr, + snprintf(status, 64, "replica/%s:%i%s", conf->wal_feeder_ipaddr, conf->wal_feeder_port, custom_proc_title); - title("hot_standby/%s:%i%s", conf->wal_feeder_ipaddr, conf->wal_feeder_port, + title("replica/%s:%i%s", conf->wal_feeder_ipaddr, conf->wal_feeder_port, custom_proc_title); } @@ -1361,7 +1361,7 @@ box_master_or_slave(struct tarantool_cfg *conf) remote_recovery_restart(conf); } else { if (remote_recover) { - say_info("shuting downing remote hot standby"); + say_info("shuting downing the replica"); fiber_cancel(remote_recover); remote_recover = NULL; @@ -1517,7 +1517,7 @@ mod_init(void) recover(recovery_state, 0); stat_cleanup(stat_base, messages_MAX); - title("build_indexes"); + title("building indexes"); build_indexes(); @@ -1526,8 +1526,8 @@ mod_init(void) if (cfg.local_hot_standby) { say_info("starting local hot standby"); recover_follow(recovery_state, cfg.wal_dir_rescan_delay); - status = "hot_standby/local"; - title("hot_standby/local"); + status = "hot_standby"; + title("hot_standby"); } if (cfg.memcached != 0) { diff --git a/mod/box/box_cfg.cfg_tmpl b/mod/box/box_cfg.cfg_tmpl index 8f755a8b7f..d65ad2ed46 100644 --- a/mod/box/box_cfg.cfg_tmpl +++ b/mod/box/box_cfg.cfg_tmpl @@ -4,7 +4,7 @@ # Snapshot directory (where snapshots get saved/read) snap_dir=".", ro -# WAL directory (where WAL get saved/read) +# WAL directory (where WALs get saved/read) wal_dir=".", ro # Primary port (where updates are accepted) @@ -13,10 +13,11 @@ primary_port=0, ro, required # Secondary port (where only selects are accepted) secondary_port=0, ro -# warn about requests which take longer to process +# Warn about requests which take longer to process, in seconds. too_long_threshold=0.5 -# custom proc title is appended after normal +# A custom process list (ps) title string, appended after the standard +# program title. custom_proc_title=NULL, ro # Memcached emulation is enabled if memcached == 1 @@ -25,36 +26,38 @@ memcached=0, ro memcached_namespace=23, ro # maximum rows to consider per expire loop iteration memcached_expire_per_loop=1024 -# tarantool will try iterate all rows within this time +# tarantool will try to iterate over all rows within this time memcached_expire_full_sweep=3600 - -# do not write snapshot faster then snap_io_rate_limit MBytes/sec +# Do not write into snapshot faster than snap_io_rate_limit MB/sec snap_io_rate_limit=0.0, ro # Write no more rows in WAL rows_per_wal=500000, ro -# fsync WAL delay, only issue fsync if last fsync was wal_fsync_delay seconds ago -# WARNING: actually, several last requsts may stall for much longer +# fsync WAL delay, only issue fsync if last fsync was wal_fsync_delay +# seconds ago. +# WARNING: actually, several last requests may stall fsync for much longer wal_fsync_delay=0, ro -# size of WAL writer requests buffer +# size of WAL writer request buffer wal_writer_inbox_size=128, ro -# Local hot standby (if enabled server will run in locale hot standby mode -# continuously fetching WAL records from shared local directory +# Local hot standby (if enabled, the server will run in local hot standby +# mode, continuously fetching WAL records from shared local directory). local_hot_standby=0, ro -# delay in fractional seconds between successive re-readings of wal_dir +# Delay, in seconds, between successive re-readings of wal_dir. +# The re-scan is necessary to discover new WAL files or snapshots. wal_dir_rescan_delay=0.1, ro -# panic if where is error reading snap or wal -# be default panic any snapshot reading error and ignore errors then reading wals +# Panic if there is an error reading a snapshot or WAL. +# By default, panic on any snapshot reading error and ignore errors +# when reading WALs. panic_on_snap_error=1, ro panic_on_wal_error=0, ro -# Remote hot standby (if enabled server will run in hot standby mode +# Remote hot standby (if enabled, the server will run in hot standby mode # continuously fetching WAL records from wal_feeder_ipaddr:wal_feeder_port remote_hot_standby=0 wal_feeder_ipaddr=NULL diff --git a/mod/box/index.m b/mod/box/index.m index 3267729430..df74b4d2b2 100644 --- a/mod/box/index.m +++ b/mod/box/index.m @@ -490,7 +490,7 @@ validate_indexes(struct box_txn *txn) if (tuple != NULL && tuple != txn->old_tuple) tnt_raise(tnt_BoxException, - reason:"unique index violation" + reason:"duplicate key in a unique index" errcode:ERR_CODE_INDEX_VIOLATION); } } diff --git a/mod/feeder/feeder.m b/mod/feeder/feeder.m index 2176767be4..be2f8b8f1f 100644 --- a/mod/feeder/feeder.m +++ b/mod/feeder/feeder.m @@ -71,7 +71,7 @@ recover_feed_slave(int sock) fiber->has_peer = true; fiber->fd = sock; fiber_set_name(fiber, "feeder"); - set_proc_title("feeder:client_handler%s %s", custom_proc_title, fiber_peer_name(fiber)); + set_proc_title("replication_relay%s %s", custom_proc_title, fiber_peer_name(fiber)); ev_default_loop(0); @@ -128,7 +128,7 @@ mod_init(void) strcat(custom_proc_title, cfg.custom_proc_title); } - set_proc_title("feeder:acceptor%s %s:%i", + set_proc_title("replication_server%s %s:%i", custom_proc_title, cfg.wal_feeder_bind_ipaddr == NULL ? "ANY" : cfg.wal_feeder_bind_ipaddr, cfg.wal_feeder_bind_port); diff --git a/test/box/sql.result b/test/box/sql.result index 3816ec7499..233a1eafed 100644 --- a/test/box/sql.result +++ b/test/box/sql.result @@ -106,3 +106,11 @@ An error occurred: ERR_CODE_ILLEGAL_PARAMS, 'Illegal parameters' select * from t0 where k0='Spears' Found 1 tuple: ['Spears', 'Britney'] +# +# A test case for: http://bugs.launchpad.net/bugs/716683 +# Admin console should not stall on unknown command. + +show status +--- +unknown command. try typing help. +... diff --git a/test/box/sql.test b/test/box/sql.test index 6eac208fe8..5189ca9d28 100644 --- a/test/box/sql.test +++ b/test/box/sql.test @@ -76,4 +76,10 @@ server.stop() server.deploy(self.suite_ini["config"]) server.start() +print """# +# A test case for: http://bugs.launchpad.net/bugs/716683 +# Admin console should not stall on unknown command. +""" +exec admin 'show status' + # vim: syntax=python diff --git a/test/lib/tarantool_server.py b/test/lib/tarantool_server.py index 7f68075c62..280d80d7ef 100644 --- a/test/lib/tarantool_server.py +++ b/test/lib/tarantool_server.py @@ -70,7 +70,7 @@ class TarantoolServer(Server): Server._start_and_exit(self, args) else: if not self.gdb: - args.append("--daemonize") + args.append("--background") else: raise RuntimeError("'--gdb' and '--start-and-exit' can't be defined together") self.server = pexpect.spawn(args[0], args[1:], cwd = self.vardir) diff --git a/third_party/proctitle.c b/third_party/proctitle.c index f2872b66ec..1a580765ad 100644 --- a/third_party/proctitle.c +++ b/third_party/proctitle.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <limits.h> #ifdef HAVE_SYS_PSTAT_H #include <sys/pstat.h> /* for HP-UX */ @@ -216,7 +217,18 @@ init_set_proc_title(int argc, char **argv) */ ps_buffer_fixed_size = 0; #else - snprintf(ps_buffer, ps_buffer_size, "tarantool: "); + { + char basename_buf[PATH_MAX]; + + /* + * At least partially mimic FreeBSD, which for + * ./a.out outputs: + * + * a.out: custom title here (a.out) + */ + snprintf(basename_buf, sizeof basename_buf, "%s", argv[0]); + snprintf(ps_buffer, ps_buffer_size, "%s: ", basename(basename_buf)); + } ps_buffer_fixed_size = strlen(ps_buffer); -- GitLab