diff --git a/.gitignore b/.gitignore index 8db9e4cd903694db40a08a551fdc35266c5337b7..1f82f83581b598817abafda890c312928027bb98 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,9 @@ doc/www-data/*.ru.html doc/www-data.in/download doc/man/tarantool.1 doc/man/tarantool_box.1 +connector/c/tnt/libtarantool.so.1 +connector/c/tnt/libtarantool.so.1.1 +connector/c/tntnet/libtarantoolnet.so.1 +connector/c/tntnet/libtarantoolnet.so.1.1 +connector/c/tntsql/libtarantoolsql.so.1 +connector/c/tntsql/libtarantoolsql.so.1.1 diff --git a/doc/sql.txt b/doc/sql.txt index ccf121755c3c5f9a74fb2ef4de5e119dca0b6317..c277f1f8b78c420f8481912326485257400013a7 100644 --- a/doc/sql.txt +++ b/doc/sql.txt @@ -1,19 +1,19 @@ ; ; 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 +; 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 +; case-insensitive, so this convention is present only to improve ; legibility of the BNF. <sql> ::= <insert> | <replace> | <update> | <delete> | <select> <insert> ::= INSERT [INTO] <ident> VALUES <value_list> -<insert> ::= REPLACE [INTO] <ident> VALUES <value_list> +<replace> ::= REPLACE [INTO] <ident> VALUES <value_list> <update> ::= UPDATE <ident> SET <update_list> <simple_where> diff --git a/doc/user/CMakeLists.txt b/doc/user/CMakeLists.txt index ee097af2a65b08f850400db74b4ba327a2d10560..34d1a421ad6c8a36578529705a85f3a875351084 100644 --- a/doc/user/CMakeLists.txt +++ b/doc/user/CMakeLists.txt @@ -63,11 +63,10 @@ add_custom_target(pdf COMMAND fop tarantool_user_guide.fo tarantool_user_guide.pdf) add_custom_target(relink + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${XSLTPROC} --nonet --stringparam collect.xref.targets "only" - --xinclude -o ${PATH_USERGUIDE_HTML} - ${CMAKE_SOURCE_DIR}/doc/user/tnt-html.xsl - ${CMAKE_SOURCE_DIR}/doc/user/user.xml) + --xinclude tnt-html.xsl user.xml) # # Java saxon-based documentation generation (misc) diff --git a/doc/user/data-model.xml b/doc/user/data-model.xml index d8d193e5e95bde5677451fb343d0624a45903398..63560fd000b0387bcc8b19f3bee68feaacb36254 100644 --- a/doc/user/data-model.xml +++ b/doc/user/data-model.xml @@ -90,7 +90,7 @@ <listitem><para> REPLACE replaces data when a tuple with given primary key already exists. Such replace - can insert a tuple of different cardinality. + can insert a tuple with a different number of fields. </para></listitem> </itemizedlist> </para> diff --git a/doc/user/errcode.xml b/doc/user/errcode.xml index affe269ee40413b5213e88a0ecdf4741068b3986..ef2b92d5d9cc582aa0b26ca709b089fa6a18fa64 100644 --- a/doc/user/errcode.xml +++ b/doc/user/errcode.xml @@ -56,8 +56,8 @@ of existing codes.</para> </varlistentry> <varlistentry> - <term xml:id="ER_KEY_CARDINALITY" xreflabel="ER_KEY_CARDINALITY">ER_KEY_CARDINALITY</term> - <listitem><para>Key cardinality is greater than index cardinality + <term xml:id="ER_KEY_PART_COUNT" xreflabel="ER_KEY_PART_COUNT">ER_KEY_PART_COUNT</term> + <listitem><para>Key part count is greater than index part count </para></listitem> </varlistentry> diff --git a/doc/user/language-reference.xml b/doc/user/language-reference.xml index 15f719f0384ea9301ce5b807934161dc521675aa..a0c4e1502bba3f19694e68870bc8b82f286657b8 100644 --- a/doc/user/language-reference.xml +++ b/doc/user/language-reference.xml @@ -74,7 +74,7 @@ header, allows simplifying client or proxy I/O. The server response to a request always carries in its header the same request type and id. - The id makes it possible to always match request to a + The id makes it possible to always match a request to a response, even if the latter arrived out of order. </para> <para>Request type defines the format of the payload. @@ -85,11 +85,11 @@ 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 + concern oneself 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. + client supports a subset of 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 @@ -132,7 +132,7 @@ 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 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 @@ -151,8 +151,8 @@ <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 + <function>munmap(2)</function>s all memory except memory + where tuples are stored. 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 @@ -170,7 +170,7 @@ <programlisting>localhost> show info --- info: - version: "1.4.4" + version: "1.4.6" lsn: 843301 ... localhost> save snapshot @@ -258,6 +258,8 @@ info: <emphasis role="tntadmin">show stat</emphasis> </term> <listitem><para> + Show the average number of requests per second, and the total number of requests since startup, + broken down by request type: INSERT or SELECT or UPDATE or DELETE." <programlisting> localhost> show stat --- @@ -301,7 +303,7 @@ statistics: </term> <listitem><para> A pool allocator is used for temporary memory, when - serving client requests. Every fiber has an own + serving client requests. Every fiber has its own pool. Shows the current state of pools of all fibers. </para></listitem> </varlistentry> @@ -334,7 +336,7 @@ statistics: <listitem><para> Execute a chunk of Lua code. This can be used to define, invoke, debug and drop <olink - targetptr="stored-programs">stored programs</olink>, + targetptr="stored-procedures">stored procedures</olink>, inspect server environment, perform automated administrative tasks. </para></listitem> @@ -344,7 +346,7 @@ statistics: </section> -<xi:include href="stored-programs.xml" /> +<xi:include href="stored-procedures.xml" /> </chapter> diff --git a/doc/user/persistence-architecture.xml b/doc/user/persistence-architecture.xml index e1c3aa7377f6344f878e2442c301636ee8445e72..d1e7e46158a7d73bb7cb0fe9078a98f128f2aae4 100644 --- a/doc/user/persistence-architecture.xml +++ b/doc/user/persistence-architecture.xml @@ -7,7 +7,7 @@ <title>Data persistence</title> <para> To maintain data persistence, Tarantool writes each data change -request (INSERT, UPDATE, DELETE) into a write ahead log. WAL +request (INSERT, UPDATE, DELETE) into a write-ahead log. WAL files have extension <filename>.xlog</filename> and are stored in <olink targetptr="wal_dir"/>. A new WAL file is created for every <olink targetptr="rows_per_wal"/> records. Each INSERT, UPDATE or DELETE @@ -23,36 +23,35 @@ each WAL record contains a checksum and a UNIX time stamp. </para> <para> -Tarantool proceeds requests atomically: a change is either -accepted and recorded in the WAL, or is rejected wholesale. +Tarantool processes requests atomically: a change is either +accepted and recorded in the WAL, or discarded completely. Let's clarify how this happens, using REPLACE command as an example: <orderedlist> <listitem><para> - The server tries to locate an old tuple identified by - the same primary key. If found, the tuple is remembered for - later. + The server attempts to locate the original tuple by + primary key. If found, a reference to the tuple is retained + for later use. </para></listitem> <listitem><para> - The new tuple is <emphasis>validated</emphasis>. If it - violates any of the unique key constraints, misses - any of indexed fields, or an indexed field type does not - match index type, the change is aborted. + The new tuple is then <emphasis>validated</emphasis>. If it + violates a unique-key constraint, misses + an indexed field, or an index-field type does not + match the type of the index, the change is aborted. </para></listitem> <listitem><para> - The new tuple is marked 'invisible' and is added to + The new tuple is marked 'invisible' and is added to the primary and secondary indexes. </para></listitem> <listitem><para> - A message is sent to a separate <quote>wal_writer</quote> - thread requesting that the change is recorded in the WAL. - The fiber associate with the current connection is scheduled - off CPU until an acknowledgment is received from the WAL - writer. + A message is sent to <quote>wal_writer</quote>, running in a + separate thread, requesting that the change be recorded in the WAL. + The fiber associated with the current connection is suspended + until an acknowledgment from the WAL writer. </para></listitem> <listitem><para> - Upon success, 'invisible' flag is cleared - and the old tuple is deleted. A response is sent to the + Upon success, the 'invisible' flag is cleared + and the original tuple is deleted. A response is sent to the client. Upon failure, the new tuple is removed and <olink targetptr="ER_WAL_IO"/> error is sent to the client. </para></listitem> @@ -60,13 +59,12 @@ example: </para> <para> -Communication between master and WAL writer threads is asynchronous. -It is implemented using an asynchronous FIFO queue. -Asynchronous but reliable message passing between the master -and WAL writer threads allows Tarantool to continue handling -requests regardless of disk throughput. SELECT performance, -provided SELECTs are run in their own connections, is unaffected -by disk load. +The master and the WAL writer threads communicate using asynchronous (yet reliable) +messaging; the master theread, not being blocked on +WAL tasks, continues to handle requests quickly +even at hight volumes of disk I/O. For instance, SELECT performance, +provided SELECTs are run in their own connections, remains +unaffected by disk load. </para> <para> diff --git a/doc/user/space.xml b/doc/user/space.xml index 8f8816c97fa198181ed080aee999c804b889d75d..3bc9b92076877ba6b408d13e62a2efae547e61e5 100644 --- a/doc/user/space.xml +++ b/doc/user/space.xml @@ -41,8 +41,8 @@ struct space_t /* A space 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. + * If given, each tuple in the space must have exactly + * this many fields. */ unsigned int cardinality; /* Only used for HASH indexes, to preallocate memory. */ diff --git a/doc/user/stored-programs.xml b/doc/user/stored-procedures.xml similarity index 95% rename from doc/user/stored-programs.xml rename to doc/user/stored-procedures.xml index fd580c25c1c14255240cc97d3f679a1d33af410f..8d86e362d6f83f546385f0cb03b3df6c1ec6afd1 100644 --- a/doc/user/stored-programs.xml +++ b/doc/user/stored-procedures.xml @@ -5,7 +5,7 @@ <section 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="stored-programs"> + xml:id="stored-procedures"> <title>Writing stored procedures in Lua</title> <blockquote> <para> @@ -33,7 +33,7 @@ Found 1 tuple: In the language of the administrative console <olink targetptr="lua-command" /> evaluates an arbitrary Lua chunk. CALL is the SQL standard statement used - to represent CALL command of the binary + to invoke the CALL command of the binary protocol. In the example above, a Lua procedure is first defined using the text protocol of the administrative port, @@ -95,7 +95,7 @@ expirationd.run_task("exprd space 0", 0, is_expired, nil, </para> <para> - There is a single global instance of Lua interpreter, which is + There is a single global instance of the Lua interpreter, which is shared across all connections. Anything prefixed with <code>lua </code> on the administrative console is sent directly to this interpreter. Any change of the interpreter @@ -103,7 +103,7 @@ expirationd.run_task("exprd space 0", 0, is_expired, nil, </para> <para> Each connection, however, is using its own Lua - <emphasis>coroutine</emphasis> — a mechanism, akin to + <emphasis>coroutine</emphasis> — a mechanism akin to Tarantool <emphasis>fibers</emphasis>. A coroutine has an own execution stack and a Lua <emphasis>closure</emphasis> — set of local variables and definitions. @@ -180,7 +180,7 @@ error: 1:15 expected '(' When a function in Lua terminates with an error, the error is sent to the client as <olink targetptr="ER_PROC_LUA" /> return code, with the original error message preserved. - Similarly, an error occurred inside Tarantool (observed on the + Similarly, an error which has occurred inside Tarantool (observed on the client as an error code), when happens during execution of a Lua procedure, produces a genuine Lua error: <programlisting><computeroutput>localhost> lua function f1() error("oops") end @@ -247,7 +247,7 @@ pack: function <para> Process a request passed in as a binary string. This is an entry point into the server request - processor. It allows to insert, update, + processor. It can be used to insert, update, select and delete tuples from within a Lua procedure. </para> <para> @@ -373,8 +373,8 @@ localhost> lua box.select(5, 1, 'firstname', 'lastname') single character of format describes either an operation which needs to take place or operation argument. A format specifier also works as a - placeholder for the number of field, which needs - to be updated, or argument value. + placeholder for the number of a field, which needs + to be updated, or for an argument value. For example: <simplelist> <member><code>+p=p</code> — add a value @@ -419,7 +419,7 @@ localhost> lua box.update(0, 2, '!p', 1, 'Bienvenue tout le monde!') --- - 2: {'Bienvenue tout le monde!', 'Hello world!'} ... -localhost> lua box.update(0, 2, '#p', 2, 'Biennvenue tout le monde!') +localhost> lua box.update(0, 2, '#p', 2, 'Bienvenue tout le monde!') --- - 2: {'Bienvenue tout le monde!'} ... @@ -467,7 +467,7 @@ Call ERROR, Illegal parameters, key is not u32 (ER_ILLEGAL_PARAMS) can change significantly if data is inserted or deleted between two calls to <code>box.select_range()</code>. If <code>key</code> is <code>nil</code> or unspecified, - the selection starts from start of the index. + the selection starts from the start of the index. <bridgehead renderas="sect4">Example</bridgehead> <programlisting>localhost> show configuration --- @@ -535,8 +535,8 @@ localhost> lua box.select_range(4, 1, 2, '1') string, low byte first, </member> <member><code>p</code> — stores the length - of the argument as a 4-byte int, low byte first, - followed by the argument itself: a 4-byte int, low + of the argument as a 4-byte integer, low byte first, + followed by the argument itself: a 4-byte integer, low byte first, for integers, or a binary blob for anything else, </member> @@ -720,7 +720,7 @@ localhost> lua t:slice(1, -1) <emphasis role="lua">space.cardinality</emphasis> </term> <listitem><simpara> - A limit on tuple cardinality for tuples in this space. + A limit on tuple field count for tuples in this space. This limit can be set in the configuration file. Value 0 stands for <quote>unlimited</quote>. </simpara></listitem> @@ -732,8 +732,8 @@ localhost> lua t:slice(1, -1) </term> <listitem><simpara> A container for all defined indexes. An index is a Lua object - of type <code xlink:href="#box.index">box.index</code> which - allows to search tuples and iterate over them in predefined order. + of type <code xlink:href="#box.index">box.index</code> with + methods to search tuples and iterate over them in predefined order. </simpara></listitem> </varlistentry> <varlistentry> @@ -992,18 +992,21 @@ localhost> lua for k,v in i.next, i, nil do print(v) end <variablelist> <title>Package <code>box.fiber</code></title> - <para>Functions in this package allow to create, run and + <para>Functions in this package allow you to create, run and manage existing <emphasis>fibers</emphasis>. </para> <para> A fiber is an independent execution thread implemented using a mechanism of cooperative multitasking. -Each fiber can be running, suspended or dead. -A fiber is created (<code>box.fiber.create()</code>) suspended. -It can be started with <code>box.fiber.resume()</code>, yield -control back to the caller with <code>box.fiber.yield()</code> -end with <code>return</code> or just by reaching the end of -fiber function. + +A fiber has three possible states: running, suspended or dead. +When a fiber is created with <code>box.fiber.create()</code>, +it is suspended. +When a fiber is started with <code>box.fiber.resume()</code>, it is running. +When a fiber's control is yielded back to the caller with +<code>box.fiber.yield()</code>, it is suspended. +When a fiber ends (due to <code>return</code> or by reaching the +end of the fiber function), it is dead. </para> <para> A fiber can also be attached or detached. @@ -1048,15 +1051,17 @@ can be used to cancel runaway Lua procedures. </para> <para> The other potential problem comes from detached -fibers which never get scheduled, because are not subscribed -to any events, or no relevant events occur. Such morphing fibers +fibers which never get scheduled, because they are not subscribed +to any events, or because no relevant events occur. Such morphing fibers can be killed with <code>box.fiber.cancel()</code> at any time, since <code>box.fiber.cancel()</code> sends an asynchronous wakeup event to the fiber, and <code>box.fiber.testcancel()</code> is checked whenever such an event occurs. </para> <para>Like all Lua objects, dead fibers are - garbage collected.</para> + garbage collected: the garbage collector frees pool allocator + memory owned by the fiber, resets all fiber data, and returns + the fiber to the fiber pool.</para> <varlistentry> <term> <emphasis role="lua">box.fiber.id(fiber) </emphasis> @@ -1185,10 +1190,10 @@ logger = cat - >> tarantool.log </para> <section> -<title>Limitation of stored programs</title> +<title>Limitation of stored procedures</title> <para> - There are two limitations in stored program support one should + There are two limitations in stored procedures support one should be aware of: execution atomicity and lack of typing. </para> <bridgehead renderas="sect4">Cooperative multitasking environment</bridgehead> diff --git a/doc/user/target.db b/doc/user/target.db index 7991ed8da6bae718d50079a06ea2a2aec3155f62..dd34c3308be2ee10d639461b65e7fade20b0144e 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.5-186-ga1d666f</ttl><xreftext>Tarantool/Box User Guide, version 1.4.5-186-ga1d666f</xreftext><div element="chapter" href="#idp97824" 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="#idp200192" number=""><ttl>Conventions</ttl><xreftext>the section called “Conventionsâ€</xreftext></div><div element="section" href="#idp209088" number=""><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugsâ€</xreftext></div></div><div element="chapter" href="#idp230464" number="2"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext></div><div element="chapter" href="#data-and-persistence" number="3" targetptr="data-and-persistence"><ttl>Data model and data persitence</ttl><xreftext>Chapter 3, <i>Data model and data persitence</i></xreftext><div element="section" href="#idp296336" number=""><ttl>Dynamic data model</ttl><xreftext>the section called “Dynamic data modelâ€</xreftext></div><div element="section" href="#idp402880" number=""><ttl>Data persistence</ttl><xreftext>the section called “Data persistenceâ€</xreftext></div></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="#idp671408" number=""><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulationâ€</xreftext><div element="section" href="#idp666656" number=""><ttl>Memcached protocol</ttl><xreftext>the section called “Memcached protocolâ€</xreftext></div></div><div element="section" href="#idp663760" 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><obj element="term" href="#lua-command" number="" targetptr="lua-command"><ttl>???TITLE???</ttl><xreftext>LUA ...</xreftext></obj></div><div element="section" href="#stored-programs" number="" targetptr="stored-programs"><ttl>Writing stored procedures in Lua</ttl><xreftext>the section called “Writing stored procedures in Luaâ€</xreftext><obj element="code" href="#box" number="" targetptr="box"><ttl>???TITLE???</ttl><xreftext>box</xreftext></obj><obj element="code" href="#box.tuple" number="" targetptr="box.tuple"><ttl>???TITLE???</ttl><xreftext>box.tuple</xreftext></obj><obj element="code" href="#box.space" number="" targetptr="box.space"><ttl>???TITLE???</ttl><xreftext>box.space</xreftext></obj><obj element="code" href="#box.index" number="" targetptr="box.index"><ttl>???TITLE???</ttl><xreftext>box.index</xreftext></obj><div element="section" href="#idp880288" number=""><ttl>Limitation of stored programs</ttl><xreftext>the section called “Limitation of stored programsâ€</xreftext></div></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="#idp263808" number=""><ttl>Replication architecture</ttl><xreftext>the section called “Replication architectureâ€</xreftext></div><div element="section" href="#idm18496" number=""><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the masterâ€</xreftext></div><div element="section" href="#idp395232" number=""><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replicaâ€</xreftext></div><div element="section" href="#idp29680" 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="#idp912560" 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="#idp925232" number="6.1"><ttl>Basic parameters</ttl><xreftext>Table 6.1, “Basic parametersâ€</xreftext></obj><obj element="entry" href="#work_dir" number="" targetptr="work_dir"><ttl>???TITLE???</ttl><xreftext>work_dir</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="#idp974448" 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="#space" number="" targetptr="space"><ttl>???TITLE???</ttl><xreftext>the section called “The option fileâ€</xreftext></obj><obj element="table" href="#idp1010528" number="6.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 6.3, “Binary logging and snapshotsâ€</xreftext></obj><obj element="entry" href="#rows_per_wal" number="" targetptr="rows_per_wal"><ttl>???TITLE???</ttl><xreftext>rows_per_wal</xreftext></obj><obj element="entry" href="#wal_mode" number="" targetptr="wal_mode"><ttl>???TITLE???</ttl><xreftext>wal_mode</xreftext></obj><obj element="table" href="#idp1045376" 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" number="" targetptr="replication_source"><ttl>???TITLE???</ttl><xreftext>replication_source</xreftext></obj><obj element="table" href="#idp1064352" number="6.5"><ttl>Networking</ttl><xreftext>Table 6.5, “Networkingâ€</xreftext></obj><obj element="table" href="#idp1083120" number="6.6"><ttl>Logging</ttl><xreftext>Table 6.6, “Loggingâ€</xreftext></obj><obj element="table" href="#idp1108016" 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_space" number="" targetptr="memcached_space"><ttl>???TITLE???</ttl><xreftext>memcached_space</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="#idp104160" number=""><ttl>C</ttl><xreftext>the section called “Câ€</xreftext></div><div element="section" href="#idp91968" number=""><ttl>Perl</ttl><xreftext>the section called “Perlâ€</xreftext></div><div element="section" href="#idp192864" number=""><ttl>PHP</ttl><xreftext>the section called “PHPâ€</xreftext></div><div element="section" href="#idp891456" number=""><ttl>Python</ttl><xreftext>the section called “Pythonâ€</xreftext></div><div element="section" href="#idp188704" 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="#ER_NONMASTER" number="" targetptr="ER_NONMASTER"><ttl>???TITLE???</ttl><xreftext>ER_NONMASTER</xreftext></obj><obj element="term" href="#ER_ILLEGAL_PARAMS" number="" targetptr="ER_ILLEGAL_PARAMS"><ttl>???TITLE???</ttl><xreftext>ER_ILLEGAL_PARAMS</xreftext></obj><obj element="term" href="#ER_TUPLE_IS_RO" number="" targetptr="ER_TUPLE_IS_RO"><ttl>???TITLE???</ttl><xreftext>ER_TUPLE_IS_RO</xreftext></obj><obj element="term" href="#ER_MEMORY_ISSUE" number="" targetptr="ER_MEMORY_ISSUE"><ttl>???TITLE???</ttl><xreftext>ER_MEMORY_ISSUE</xreftext></obj><obj element="term" href="#ER_WAL_IO" number="" targetptr="ER_WAL_IO"><ttl>???TITLE???</ttl><xreftext>ER_WAL_IO</xreftext></obj><obj element="term" href="#ER_INDEX_VIOLATION" number="" targetptr="ER_INDEX_VIOLATION"><ttl>???TITLE???</ttl><xreftext>ER_INDEX_VIOLATION</xreftext></obj><obj element="term" href="#ER_KEY_CARDINALITY" number="" targetptr="ER_KEY_CARDINALITY"><ttl>???TITLE???</ttl><xreftext>ER_KEY_CARDINALITY</xreftext></obj><obj element="term" href="#ER_NO_SUCH_SPACE" number="" targetptr="ER_NO_SUCH_SPACE"><ttl>???TITLE???</ttl><xreftext>ER_NO_SUCH_SPACE</xreftext></obj><obj element="term" href="#ER_NO_SUCH_INDEX" number="" targetptr="ER_NO_SUCH_INDEX"><ttl>???TITLE???</ttl><xreftext>ER_NO_SUCH_INDEX</xreftext></obj><obj element="term" href="#ER_PROC_LUA" number="" targetptr="ER_PROC_LUA"><ttl>???TITLE???</ttl><xreftext>ER_PROC_LUA</xreftext></obj></div></div> +<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool/Box User Guide, version 1.4.5-219-g8cd1466</ttl><xreftext>Tarantool/Box User Guide, version 1.4.5-219-g8cd1466</xreftext><div element="chapter" href="#idp42304" 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="#idp199536" number=""><ttl>Conventions</ttl><xreftext>the section called “Conventionsâ€</xreftext></div><div element="section" href="#idp208432" number=""><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugsâ€</xreftext></div></div><div element="chapter" href="#idm37968" number="2"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext></div><div element="chapter" href="#data-and-persistence" number="3" targetptr="data-and-persistence"><ttl>Data model and data persitence</ttl><xreftext>Chapter 3, <i>Data model and data persitence</i></xreftext><div element="section" href="#idp26544" number=""><ttl>Dynamic data model</ttl><xreftext>the section called “Dynamic data modelâ€</xreftext></div><div element="section" href="#idp394448" number=""><ttl>Data persistence</ttl><xreftext>the section called “Data persistenceâ€</xreftext></div></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="#idp671792" number=""><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulationâ€</xreftext><div element="section" href="#idp667040" number=""><ttl>Memcached protocol</ttl><xreftext>the section called “Memcached protocolâ€</xreftext></div></div><div element="section" href="#idp664144" 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><obj element="term" href="#lua-command" number="" targetptr="lua-command"><ttl>???TITLE???</ttl><xreftext>LUA ...</xreftext></obj></div><div element="section" href="#stored-procedures" number="" targetptr="stored-procedures"><ttl>Writing stored procedures in Lua</ttl><xreftext>the section called “Writing stored procedures in Luaâ€</xreftext><obj element="code" href="#box" number="" targetptr="box"><ttl>???TITLE???</ttl><xreftext>box</xreftext></obj><obj element="code" href="#box.tuple" number="" targetptr="box.tuple"><ttl>???TITLE???</ttl><xreftext>box.tuple</xreftext></obj><obj element="code" href="#box.space" number="" targetptr="box.space"><ttl>???TITLE???</ttl><xreftext>box.space</xreftext></obj><obj element="code" href="#box.index" number="" targetptr="box.index"><ttl>???TITLE???</ttl><xreftext>box.index</xreftext></obj><div element="section" href="#idp880464" number=""><ttl>Limitation of stored procedures</ttl><xreftext>the section called “Limitation of stored proceduresâ€</xreftext></div></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="#idp275200" number=""><ttl>Replication architecture</ttl><xreftext>the section called “Replication architectureâ€</xreftext></div><div element="section" href="#idp41184" number=""><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the masterâ€</xreftext></div><div element="section" href="#idm31856" number=""><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replicaâ€</xreftext></div><div element="section" href="#idp288992" 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="#idp912960" 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="#idp925584" number="6.1"><ttl>Basic parameters</ttl><xreftext>Table 6.1, “Basic parametersâ€</xreftext></obj><obj element="entry" href="#work_dir" number="" targetptr="work_dir"><ttl>???TITLE???</ttl><xreftext>work_dir</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="#idp974864" 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="#space" number="" targetptr="space"><ttl>???TITLE???</ttl><xreftext>the section called “The option fileâ€</xreftext></obj><obj element="table" href="#idp1010880" number="6.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 6.3, “Binary logging and snapshotsâ€</xreftext></obj><obj element="entry" href="#rows_per_wal" number="" targetptr="rows_per_wal"><ttl>???TITLE???</ttl><xreftext>rows_per_wal</xreftext></obj><obj element="entry" href="#wal_mode" number="" targetptr="wal_mode"><ttl>???TITLE???</ttl><xreftext>wal_mode</xreftext></obj><obj element="table" href="#idp1045856" 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" number="" targetptr="replication_source"><ttl>???TITLE???</ttl><xreftext>replication_source</xreftext></obj><obj element="table" href="#idp1064832" number="6.5"><ttl>Networking</ttl><xreftext>Table 6.5, “Networkingâ€</xreftext></obj><obj element="table" href="#idp1083600" number="6.6"><ttl>Logging</ttl><xreftext>Table 6.6, “Loggingâ€</xreftext></obj><obj element="table" href="#idp1108496" 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_space" number="" targetptr="memcached_space"><ttl>???TITLE???</ttl><xreftext>memcached_space</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="#idm11744" number=""><ttl>C</ttl><xreftext>the section called “Câ€</xreftext></div><div element="section" href="#idp187680" number=""><ttl>Perl</ttl><xreftext>the section called “Perlâ€</xreftext></div><div element="section" href="#idp223696" number=""><ttl>PHP</ttl><xreftext>the section called “PHPâ€</xreftext></div><div element="section" href="#idp697056" number=""><ttl>Python</ttl><xreftext>the section called “Pythonâ€</xreftext></div><div element="section" href="#idp861616" 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="#ER_NONMASTER" number="" targetptr="ER_NONMASTER"><ttl>???TITLE???</ttl><xreftext>ER_NONMASTER</xreftext></obj><obj element="term" href="#ER_ILLEGAL_PARAMS" number="" targetptr="ER_ILLEGAL_PARAMS"><ttl>???TITLE???</ttl><xreftext>ER_ILLEGAL_PARAMS</xreftext></obj><obj element="term" href="#ER_TUPLE_IS_RO" number="" targetptr="ER_TUPLE_IS_RO"><ttl>???TITLE???</ttl><xreftext>ER_TUPLE_IS_RO</xreftext></obj><obj element="term" href="#ER_MEMORY_ISSUE" number="" targetptr="ER_MEMORY_ISSUE"><ttl>???TITLE???</ttl><xreftext>ER_MEMORY_ISSUE</xreftext></obj><obj element="term" href="#ER_WAL_IO" number="" targetptr="ER_WAL_IO"><ttl>???TITLE???</ttl><xreftext>ER_WAL_IO</xreftext></obj><obj element="term" href="#ER_INDEX_VIOLATION" number="" targetptr="ER_INDEX_VIOLATION"><ttl>???TITLE???</ttl><xreftext>ER_INDEX_VIOLATION</xreftext></obj><obj element="term" href="#ER_KEY_CARDINALITY" number="" targetptr="ER_KEY_CARDINALITY"><ttl>???TITLE???</ttl><xreftext>ER_KEY_CARDINALITY</xreftext></obj><obj element="term" href="#ER_NO_SUCH_SPACE" number="" targetptr="ER_NO_SUCH_SPACE"><ttl>???TITLE???</ttl><xreftext>ER_NO_SUCH_SPACE</xreftext></obj><obj element="term" href="#ER_NO_SUCH_INDEX" number="" targetptr="ER_NO_SUCH_INDEX"><ttl>???TITLE???</ttl><xreftext>ER_NO_SUCH_INDEX</xreftext></obj><obj element="term" href="#ER_PROC_LUA" number="" targetptr="ER_PROC_LUA"><ttl>???TITLE???</ttl><xreftext>ER_PROC_LUA</xreftext></obj></div></div> diff --git a/include/errcode.h b/include/errcode.h index 99e0531496484fa678c8be2a11642b263c1bcc5e..2875d6e625f7bdfff7426ae2295fd7c78759cd47 100644 --- a/include/errcode.h +++ b/include/errcode.h @@ -99,7 +99,7 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 44 */_(ER_UNKNOWN_UPDATE_OP, 2, "Unknown UPDATE operation") \ /* 45 */_(ER_EXACT_MATCH, 2, "Partial key in an exact match (key field count: %d, expected: %d)") \ /* 46 */_(ER_UNUSED46, 2, "Unused46") \ - /* 47 */_(ER_KEY_CARDINALITY, 2, "Key cardinality %d is greater than index cardinality %d") \ + /* 47 */_(ER_KEY_PART_COUNT, 2, "Key part count %d is greater than index part count %d") \ /* 48 */_(ER_PROC_RET, 2, "Return type '%s' is not supported in the binary protocol") \ /* 49 */_(ER_TUPLE_NOT_FOUND, 2, "Tuple doesn't exist") \ /* 50 */_(ER_NO_SUCH_PROC, 2, "Procedure '%.*s' is not defined") \ diff --git a/include/log_io.h b/include/log_io.h index e611b199b85b1e7574d86e3bd1249e176a51715a..b3f27b2b4329b4a9625b5d7d05348e272a27f7f7 100644 --- a/include/log_io.h +++ b/include/log_io.h @@ -133,9 +133,6 @@ struct recovery_state { struct wait_lsn wait_lsn; bool finalize; - - /* Points to module-specific state */ - void *data; }; struct recovery_state *recovery_state; @@ -175,19 +172,17 @@ static inline struct row_v11 *row_v11(const struct tbuf *t) return (struct row_v11 *)t->data; } -struct tbuf *convert_to_v11(struct tbuf *orig, u16 tag, u64 cookie, i64 lsn); - void recovery_init(const char *snap_dirname, const char *xlog_dirname, row_handler row_handler, int rows_per_wal, const char *wal_mode, double wal_fsync_delay, - int flags, void *data); + int flags); void recovery_update_mode(const char *wal_mode, double fsync_delay); void recovery_update_io_rate_limit(double new_limit); void recovery_free(); int recover(struct recovery_state *, i64 lsn); -void recover_follow(struct recovery_state *r, ev_tstamp wal_dir_rescan_delay); -void recover_finalize(struct recovery_state *r); +void recovery_follow_local(struct recovery_state *r, ev_tstamp wal_dir_rescan_delay); +void recovery_finalize(struct recovery_state *r); int wal_write(struct recovery_state *r, u16 tag, u16 op, u64 cookie, i64 lsn, struct tbuf *data); diff --git a/mod/box/box.m b/mod/box/box.m index b61f53117b5b8095e53dc605c149398a35a49de4..e7abf9b68eb00b5fd6f1809d3190798e7a856a53 100644 --- a/mod/box/box.m +++ b/mod/box/box.m @@ -1844,7 +1844,7 @@ box_enter_master_or_replica_mode(struct tarantool_cfg *conf) static void box_leave_local_standby_mode(void *data __attribute__((unused))) { - recover_finalize(recovery_state); + recovery_finalize(recovery_state); box_enter_master_or_replica_mode(&cfg); } @@ -2139,7 +2139,7 @@ mod_init(void) recovery_init(cfg.snap_dir, cfg.wal_dir, recover_row, cfg.rows_per_wal, cfg.wal_mode, cfg.wal_fsync_delay, - init_storage ? RECOVER_READONLY : 0, NULL); + init_storage ? RECOVER_READONLY : 0); recovery_update_io_rate_limit(cfg.snap_io_rate_limit); recovery_setup_panic(recovery_state, cfg.panic_on_snap_error, cfg.panic_on_wal_error); @@ -2168,7 +2168,7 @@ mod_init(void) if (cfg.local_hot_standby) { say_info("starting local hot standby"); - recover_follow(recovery_state, cfg.wal_dir_rescan_delay); + recovery_follow_local(recovery_state, cfg.wal_dir_rescan_delay); snprintf(status, sizeof(status), "hot_standby"); title("hot_standby"); } diff --git a/mod/box/index.m b/mod/box/index.m index 5d6bdb97a554245f1641b1d0f566c21f1ca10dd2..d9a896d6ca70c11d2030565a7408d21d878be1b1 100644 --- a/mod/box/index.m +++ b/mod/box/index.m @@ -199,7 +199,7 @@ iterator_first_equal(struct iterator *it) - (void) checkKeyParts: (int) part_count :(bool) partial_key_allowed { if (part_count > key_def->part_count) - tnt_raise(ClientError, :ER_KEY_CARDINALITY, + tnt_raise(ClientError, :ER_KEY_PART_COUNT, part_count, key_def->part_count); if (!partial_key_allowed && part_count < key_def->part_count) tnt_raise(ClientError, :ER_EXACT_MATCH, diff --git a/src/log_io.m b/src/log_io.m index 31d201472dad7ed26509fa37d92a287415280b38..e7bd3a8c9725778c8417097d7332b8e1b5710bfc 100644 --- a/src/log_io.m +++ b/src/log_io.m @@ -45,6 +45,67 @@ #include <crc32.h> #include <tarantool_pthread.h> #include "errinj.h" +/* + * Recovery subsystem + * ------------------ + * + * A facade of the recovery subsystem is struct recovery_state, + * which is a singleton. + * + * Depending on the configuration, start-up parameters, the + * actual task being performed, the recovery can be + * in a different state. + * + * The main factors influencing recovery state are: + * - temporal: whether or not the instance is just booting + * from a snapshot, is in 'local hot standby mode', or + * is already accepting requests + * - topological: whether or not it is a master instance + * or a replica + * - task based: whether it's a master process, + * snapshot saving process or a replication relay. + * + * Depending on the above factors, recovery can be in two main + * operation modes: "read mode", recovering in-memory state + * from existing data, and "write mode", i.e. recording on + * disk changes of the in-memory state. + * + * Let's enumerate all possible distinct states of recovery: + * + * Read mode + * --------- + * IR - initial recovery, initiated right after server start: + * reading data from the snapshot and existing WALs + * and restoring the in-memory state + * IRR - initial replication relay mode, reading data from + * existing WALs (xlogs) and sending it to the client. + * + * HS - standby mode, entered once all existing WALs are read: + * following the WAL directory for all changes done by the master + * and updating the in-memory state + * RR - replication relay, following the WAL directory for all + * changes done by the master and sending them to the + * replica + * + * Write mode + * ---------- + * M - master mode, recording in-memory state changes in the WAL + * R - replica mode, receiving changes from the master and + * recording them in the WAL + * S - snapshot mode, writing entire in-memory state to a compact + * snapshot file. + * + * The following state transitions are possible/supported: + * + * recovery_init() -> IR | IRR # recover() + * IR -> HS # recovery_follow_local() + * IRR -> RR # recovery_follow_local() + * HS -> M # recovery_finalize() + * M -> R # recovery_follow_remote() + * R -> M # recovery_stop_remote() + * M -> S # snapshot() + * R -> S # snapshot() + */ const u16 snap_tag = -1; const u16 wal_tag = -2; @@ -698,7 +759,9 @@ error: static struct log_io * -log_io_open_for_read(struct recovery_state *recover, struct log_io_class *class, i64 lsn, int suffix, +log_io_open_for_read(struct recovery_state *recover, + struct log_io_class *class, + i64 lsn, int suffix, const char *filename) { const char *errmsg; @@ -721,7 +784,7 @@ log_io_open_for_read(struct recovery_state *recover, struct log_io_class *class, strncpy(l->filename, filename, PATH_MAX); } - say_debug("%s: opening %s'", __func__, l->filename); + say_debug("%s: opening %s", __func__, l->filename); l->f = fopen(l->filename, "r"); if (l->f == NULL) { @@ -743,19 +806,22 @@ error: return NULL; } +/** + * In case of error, writes a message to the server log + * and sets errno. + */ struct log_io * -log_io_open_for_write(struct recovery_state *recover, struct log_io_class *class, i64 lsn, - int suffix, int *save_errno) +log_io_open_for_write(struct recovery_state *recover, + struct log_io_class *class, i64 lsn, int suffix) { struct log_io *l = NULL; int fd; char *dot; bool exists; - const char *errmsg; + int save_errno; l = calloc(1, sizeof(*l)); if (l == NULL) { - *save_errno = errno; say_syserror("calloc"); return NULL; } @@ -778,8 +844,7 @@ log_io_open_for_write(struct recovery_state *recover, struct log_io_class *class exists = access(l->filename, F_OK) == 0; *dot = '.'; if (exists) { - *save_errno = EEXIST; - errmsg = "exists"; + errno = EEXIST; goto error; } } @@ -790,29 +855,24 @@ log_io_open_for_write(struct recovery_state *recover, struct log_io_class *class */ fd = open(l->filename, O_WRONLY | O_CREAT | O_EXCL | l->class->open_wflags, 0664); - if (fd < 0) { - *save_errno = errno; - errmsg = strerror(errno); + if (fd < 0) goto error; - } l->f = fdopen(fd, "w"); - if (l->f == NULL) { - *save_errno = errno; - errmsg = strerror(errno); + if (l->f == NULL) goto error; - } say_info("creating `%s'", l->filename); write_header(l); return l; error: - say_error("%s: failed to open `%s': %s", __func__, l->filename, - errmsg); + save_errno = errno; /* Preserve over fclose()/free() */ + say_syserror("%s: failed to open `%s'", __func__, l->filename); if (l->f != NULL) fclose(l->f); free(l); + errno = save_errno; return NULL; } @@ -979,8 +1039,11 @@ recover_wal(struct recovery_state *r, struct log_io *l) } } -/* - * this function will not close r->current_wal if recovery was successful +/** Find out if there are new .xlog files since the current + * LSN, and read them all up. + * + * This function will not close r->current_wal if + * recovery was successful. */ static int recover_remaining_wals(struct recovery_state *r) @@ -998,7 +1061,10 @@ recover_remaining_wals(struct recovery_state *r) goto recover_current_wal; while (r->confirmed_lsn < wal_greatest_lsn) { - /* if newer WAL appeared in directory before current_wal was fully read try reread last */ + /* + * If a newer WAL appeared in the directory before + * current_wal was fully read, try re-reading + * one last time. */ if (r->current_wal != NULL) { if (r->current_wal->retry++ < 3) { say_warn("try reread `%s' despite newer WAL exists", @@ -1011,9 +1077,10 @@ recover_remaining_wals(struct recovery_state *r) } } - current_lsn = r->confirmed_lsn + 1; /* TODO: find better way looking for next xlog */ - next_wal = log_io_open_for_read(r, r->wal_class, current_lsn, 0, NULL); - + /* TODO: find a better way of finding the next xlog */ + current_lsn = r->confirmed_lsn + 1; + next_wal = log_io_open_for_read(r, r->wal_class, current_lsn, + 0, NULL); /* * When doing final recovery, and dealing with the * last file, try opening .<suffix>.inprogress. @@ -1035,30 +1102,33 @@ recover_remaining_wals(struct recovery_state *r) break; } - assert(r->current_wal == NULL); r->current_wal = next_wal; say_info("recover from `%s'", r->current_wal->filename); - recover_current_wal: +recover_current_wal: rows_before = r->current_wal->rows; result = recover_wal(r, r->current_wal); if (result < 0) { - say_error("failure reading from %s", r->current_wal->filename); + say_error("failure reading from %s", + r->current_wal->filename); break; } - if (r->current_wal->rows > 0 && r->current_wal->rows != rows_before) + if (r->current_wal->rows > 0 && + r->current_wal->rows != rows_before) { r->current_wal->retry = 0; - - /* rows == 0 could possible indicate to an empty WAL */ + } + /* rows == 0 could indicate an empty WAL */ if (r->current_wal->rows == 0) { - say_error("read zero records from %s", r->current_wal->filename); + say_error("read zero records from %s", + r->current_wal->filename); break; } if (result == LOG_EOF) { - say_info("done `%s' confirmed_lsn:%" PRIi64, r->current_wal->filename, + say_info("done `%s' confirmed_lsn:%" PRIi64, + r->current_wal->filename, r->confirmed_lsn); log_io_close(&r->current_wal); } @@ -1133,10 +1203,10 @@ recover(struct recovery_state *r, i64 lsn) return result; } -static void recover_follow_file(ev_stat *w, int revents __attribute__((unused))); +static void recovery_follow_file(ev_stat *w, int revents __attribute__((unused))); static void -recover_follow_dir(ev_timer *w, int revents __attribute__((unused))) +recovery_follow_dir(ev_timer *w, int revents __attribute__((unused))) { struct recovery_state *r = w->data; struct log_io *wal = r->current_wal; @@ -1147,13 +1217,13 @@ recover_follow_dir(ev_timer *w, int revents __attribute__((unused))) /* recover_remaining_wals found new wal */ if (r->current_wal != NULL && wal != r->current_wal) { ev_stat *stat = &r->current_wal->stat; - ev_stat_init(stat, recover_follow_file, r->current_wal->filename, 0.); + ev_stat_init(stat, recovery_follow_file, r->current_wal->filename, 0.); ev_stat_start(stat); } } static void -recover_follow_file(ev_stat *w, int revents __attribute__((unused))) +recovery_follow_file(ev_stat *w, int revents __attribute__((unused))) { struct recovery_state *r = w->data; int result; @@ -1161,28 +1231,29 @@ recover_follow_file(ev_stat *w, int revents __attribute__((unused))) if (result < 0) panic("recover failed"); if (result == LOG_EOF) { - say_info("done `%s' confirmed_lsn:%" PRIi64, r->current_wal->filename, + say_info("done `%s' confirmed_lsn:%" PRIi64, + r->current_wal->filename, r->confirmed_lsn); log_io_close(&r->current_wal); - recover_follow_dir((ev_timer *)w, 0); + recovery_follow_dir((ev_timer *)w, 0); } } void -recover_follow(struct recovery_state *r, ev_tstamp wal_dir_rescan_delay) +recovery_follow_local(struct recovery_state *r, ev_tstamp wal_dir_rescan_delay) { - ev_timer_init(&r->wal_timer, recover_follow_dir, + ev_timer_init(&r->wal_timer, recovery_follow_dir, wal_dir_rescan_delay, wal_dir_rescan_delay); ev_timer_start(&r->wal_timer); if (r->current_wal != NULL) { ev_stat *stat = &r->current_wal->stat; - ev_stat_init(stat, recover_follow_file, r->current_wal->filename, 0.); + ev_stat_init(stat, recovery_follow_file, r->current_wal->filename, 0.); ev_stat_start(stat); } } void -recover_finalize(struct recovery_state *r) +recovery_finalize(struct recovery_state *r) { int result; @@ -1430,11 +1501,9 @@ write_to_disk(struct recovery_state *r, struct wal_write_request *req) bool is_bulk_end = STAILQ_NEXT(req, wal_fifo_entry) == NULL; if (r->current_wal == NULL) { - int unused; /* Open WAL with '.inprogress' suffix. */ r->current_wal = - log_io_open_for_write(r, r->wal_class, req->lsn, -1, - &unused); + log_io_open_for_write(r, r->wal_class, req->lsn, -1); } else if (r->current_wal->rows == 1) { /* rename WAL after first successful write to name @@ -1599,8 +1668,7 @@ wal_write(struct recovery_state *r, u16 tag, u16 op, u64 cookie, void recovery_init(const char *snap_dirname, const char *wal_dirname, row_handler row_handler, int rows_per_wal, - const char *wal_mode, double wal_fsync_delay, - int flags, void *data) + const char *wal_mode, double wal_fsync_delay, int flags) { assert(recovery_state == NULL); recovery_state = p0alloc(eter_pool, sizeof(struct recovery_state)); @@ -1611,7 +1679,6 @@ recovery_init(const char *snap_dirname, const char *wal_dirname, r->wal_timer.data = r; r->row_handler = row_handler; - r->data = data; r->remote_recovery = NULL; r->snap_class = snapshot_class_create(snap_dirname); @@ -1760,13 +1827,12 @@ snapshot_save(struct recovery_state *r, void (*f) (struct log_io_iter *)) struct log_io *snap; char final_filename[PATH_MAX + 1]; char *dot; - int save_errno; memset(&i, 0, sizeof(i)); - snap = log_io_open_for_write(r, r->snap_class, r->confirmed_lsn, -1, &save_errno); + snap = log_io_open_for_write(r, r->snap_class, r->confirmed_lsn, -1); if (snap == NULL) - panic_status(save_errno, "can't open snap for writing"); + panic_status(errno, "Failed to save snapshot: failed to open file in write mode."); iter_open(snap, &i, write_rows); diff --git a/src/replication.m b/src/replication.m index efc782d9a40aa35893faf7e7a6526e98caa796e6..e6388b6c5c40122992b710e237ce9bfd6821ed21 100644 --- a/src/replication.m +++ b/src/replication.m @@ -560,7 +560,6 @@ replication_relay_loop(int client_sock) { char name[FIBER_NAME_MAXLEN]; struct sigaction sa; - struct recovery_state *log_io; struct tbuf *ver; i64 lsn; ssize_t r; @@ -617,12 +616,10 @@ replication_relay_loop(int client_sock) /* Initialize the recovery process */ recovery_init(NULL, cfg.wal_dir, replication_relay_send_row, INT32_MAX, "fsync_delay", 0, - RECOVER_READONLY, false); + RECOVER_READONLY); - log_io = recovery_state; - - recover(log_io, lsn); - recover_follow(log_io, 0.1); + recover(recovery_state, lsn); + recovery_follow_local(recovery_state, 0.1); ev_loop(0); diff --git a/src/salloc.m b/src/salloc.m index efe340ab113ba6c2b3104d206bc45fcd237f411f..9559146f1974757ac655d25d73105ea87bfc912b 100644 --- a/src/salloc.m +++ b/src/salloc.m @@ -351,8 +351,8 @@ slab_stat(struct tbuf *t) (int)slab_classes[i].item_size, slabs, items, used, free); } - tbuf_printf(t, " items_used: %.2f" CRLF, (double)total_used / arena.size * 100); - tbuf_printf(t, " arena_used: %.2f" CRLF, (double)arena.used / arena.size * 100); + tbuf_printf(t, " items_used: %.2f%%" CRLF, (double)total_used / arena.size * 100); + tbuf_printf(t, " arena_used: %.2f%%" CRLF, (double)arena.used / arena.size * 100); } void diff --git a/test/box_big/hash.result b/test/box_big/hash.result index 1726ff069a7a6444624f061bc6b19f88c70c2673..1083930a5ad75f84254e78906a589c066ea23fe4 100644 --- a/test/box_big/hash.result +++ b/test/box_big/hash.result @@ -100,7 +100,7 @@ error: 'Supplied key field type does not match index type: expected u32' ... lua box.space[10]:select(0, 1, 2) --- -error: 'Key cardinality 2 is greater than index cardinality 1' +error: 'Key part count 2 is greater than index part count 1' ... #-----------------------------------------------------------------------------# @@ -141,7 +141,7 @@ error: 'Supplied key field type does not match index type: expected u32' ... lua box.space[10]:delete(1, 2) --- -error: 'Key cardinality 2 is greater than index cardinality 1' +error: 'Key part count 2 is greater than index part count 1' ... #=============================================================================# @@ -245,7 +245,7 @@ error: 'Supplied key field type does not match index type: expected u64' ... lua box.space[11]:select(0, '00000001', '00000002') --- -error: 'Key cardinality 2 is greater than index cardinality 1' +error: 'Key part count 2 is greater than index part count 1' ... #-----------------------------------------------------------------------------# @@ -286,7 +286,7 @@ error: 'Supplied key field type does not match index type: expected u64' ... lua box.space[11]:delete('00000001', '00000002') --- -error: 'Key cardinality 2 is greater than index cardinality 1' +error: 'Key part count 2 is greater than index part count 1' ... #=============================================================================# @@ -372,7 +372,7 @@ lua box.space[12]:select(0, 'key 5') lua box.space[12]:select(0, 'key 1', 'key 2') --- -error: 'Key cardinality 2 is greater than index cardinality 1' +error: 'Key part count 2 is greater than index part count 1' ... #-----------------------------------------------------------------------------# @@ -409,7 +409,7 @@ lua box.space[12]:delete('key 5') lua box.space[12]:delete('key 1', 'key 2') --- -error: 'Key cardinality 2 is greater than index cardinality 1' +error: 'Key part count 2 is greater than index part count 1' ... lua box.space[10]:truncate() --- diff --git a/test/box_big/lua.result b/test/box_big/lua.result index 8024e87608230a18f495cbb1dd42742f4762e4d3..583ca0679d584dc0b00a833369a3f12429dfa36f 100644 --- a/test/box_big/lua.result +++ b/test/box_big/lua.result @@ -17,7 +17,7 @@ Found 1 tuple: # https://bugs.launchpad.net/tarantool/+bug/904208 # call box.select(1, 1, 'new', 'world', 'order') -An error occurred: ER_KEY_CARDINALITY, 'Key cardinality 3 is greater than index cardinality 2' +An error occurred: ER_KEY_PART_COUNT, 'Key part count 3 is greater than index part count 2' call box.delete(1, 'brave') Found 1 tuple: ['brave', 'new', 'world'] diff --git a/test/box_big/tree_pk_multipart.result b/test/box_big/tree_pk_multipart.result index bfcaaca1b8f6fb7b589c08f39c83b21ea40e02c8..c3c4667fa64dd764e12b973fa4ed779203874b6e 100644 --- a/test/box_big/tree_pk_multipart.result +++ b/test/box_big/tree_pk_multipart.result @@ -194,7 +194,7 @@ error: 'Partial key in an exact match (key field count: 2, expected: 3)' ... lua box.delete(9, 'The Wolf!', 'Vincent', 1, 'Come again?') --- -error: 'Key cardinality 4 is greater than index cardinality 3' +error: 'Key part count 4 is greater than index part count 3' ... lua box.update_ol(9, { box.upd.assign(3, '<ooops>') }, 'The Wolf!', 'Vincent', 1) --- @@ -223,7 +223,7 @@ error: 'Partial key in an exact match (key field count: 2, expected: 3)' ... lua box.update_ol(9, { box.upd.assign(3, '<ooops>') }, 'The Wolf!', 'Vincent', 1, 'Come again?') --- -error: 'Key cardinality 4 is greater than index cardinality 3' +error: 'Key part count 4 is greater than index part count 3' ... lua box.space[9]:len() --- diff --git a/test/lib/sql_ast.py b/test/lib/sql_ast.py index 0f353dfb17088f39f8a9a86a517f8ac917d75a1d..fed763dc886fc734f5472b00844dac33456a3eda 100644 --- a/test/lib/sql_ast.py +++ b/test/lib/sql_ast.py @@ -72,7 +72,7 @@ ER = { 44: "ER_UNKNOWN_UPDATE_OP" , 45: "ER_EXACT_MATCH" , 46: "ER_UNUSED46" , - 47: "ER_KEY_CARDINALITY" , + 47: "ER_KEY_PART_COUNT" , 48: "ER_PROC_RET" , 49: "ER_TUPLE_NOT_FOUND" , 50: "ER_NO_SUCH_PROC" ,