diff --git a/doc/user/configuration-reference.xml b/doc/user/configuration-reference.xml index 0e341bb56353b686299f5bbbdf7d9320acf156b5..e3a76577f0b2f92995c8dd0e3a7013d9a7c133be 100644 --- a/doc/user/configuration-reference.xml +++ b/doc/user/configuration-reference.xml @@ -16,8 +16,8 @@ <para> Tarantool splits its configuration parameters between command -line options and a configuration file. Command line flags -are provided for the most basic properties only: the rest +line options and a configuration file. Command line options +are provided only for the most basic properties; 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 @@ -139,7 +139,7 @@ Tarantool 1.4.0-69-g45551dd </listitem> </itemizedlist> <para> - The only two options which have effect on a running server are: + The only two options which could affect a running server are: </para> <itemizedlist> <listitem> @@ -150,7 +150,7 @@ Tarantool 1.4.0-69-g45551dd <listitem> <para><option>--background</option>, <option>-b</option></para> - <para>Detach from the controlling terminal and run in + <para>Detach from the controlling terminal and run in the background. <caution><para>Tarantool uses <filename>stdout</filename> and @@ -160,7 +160,7 @@ Tarantool 1.4.0-69-g45551dd either redirect its standard out and standard error streams, or provide <emphasis>logger</emphasis> option in the configuration file, since otherwise all logging - information will be lost</para></caution> + information will be lost.</para></caution> </para> </listitem> </itemizedlist> @@ -245,11 +245,10 @@ Tarantool 1.4.0-69-g45551dd <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> + <entry>A directory where database working files will be stored. + The server switches to work_dir with chdir(2) after + start. Can be relative to the current directory. + If not specified, defaults to the current directory.</entry> </row> <row> @@ -272,11 +271,11 @@ Tarantool 1.4.0-69-g45551dd <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> + <entry>A directory where write ahead log (.xlog) files are stored. + Can be relative to work_dir. Most commonly used so + that snapshot files and write ahead log files + can be stored on separate disks. + If not specified, defaults to work_dir.</entry> </row> <row> @@ -285,7 +284,7 @@ Tarantool 1.4.0-69-g45551dd <entry>""</entry> <entry>no</entry> <entry>no</entry> - <entry>A directory to store snapshots in. Can be + <entry>A directory where snapshot (.snap) files will be stored. Can be relative to work_dir. If not specified, defaults to work_dir. See also <olink targetptr="wal_dir"/>.</entry> </row> @@ -317,7 +316,7 @@ Tarantool 1.4.0-69-g45551dd 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 + Note: a replica also binds to this port, and accepts connections, but these connections can only serve reads until the replica becomes a master.</entry> </row> @@ -366,16 +365,16 @@ Tarantool 1.4.0-69-g45551dd <entry> <para>Inject the given string into <olink targetptr="proctitle">server process title</olink> - (what's shown in COMMAND column of <command>ps</command> + (what's shown in the COMMAND column for <command>ps</command> and <command>top</command> commands). For example, - an unmodified Tarantool process group looks like: + ordinarily <command>ps</command> shows the Tarantool server process thus: </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> +tarantool_box: primary pri: 33013 sec: 33014 adm: 33015</programlisting> + <para>But if the configuration file contains custom_proc_title=sessions then + the output looks like:</para> <programlisting>kostja@shmita:~$ ps -a -o command | grep box -tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> +tarantool_box: primary@sessions pri: 33013 sec: 33014 adm: 33015</programlisting> </entry> </row> @@ -454,10 +453,10 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <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 + the data structure that users get access to via the 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, + entries, and each entry describes a tuple set + and its indexes. Every entry is a composite object, best seen as a C programming language "struct" <footnote><xi:include href="space.xml"/></footnote>. </entry> @@ -492,7 +491,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>true</entry> <entry>no</entry> <entry>no</entry> - <entry>If there is an error reading the snapshot (at + <entry>If there is an error reading the snapshot file (at server start), abort.</entry> </row> @@ -502,8 +501,8 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>false</entry> <entry>no</entry> <entry>no</entry> - <entry>If there is an error reading from a write ahead - log (at server start), abort.</entry> + <entry>If there is an error reading a write ahead + log file (at server start), abort.</entry> </row> <row> @@ -515,7 +514,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <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> + <filename><first-lsn-in-wal>.xlog</filename> This can be useful for simple rsync-based backups. </entry> </row> @@ -527,7 +526,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>no</entry> <entry>yes</entry> <entry>Reduce the throttling effect of <olink - targetptr="box.snapshot"/> on the INSERT/UPDATE/DELETE + targetptr="box.snapshot"/> on 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 @@ -548,7 +547,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> 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 + does not lead to data corruption: all WAL records have a checksum, and only complete records are processed during recovery.</entry> </row> @@ -598,8 +597,10 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <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 + <entry>If replication_port is greater than zero, the + server is considered to be a Tarantool master. + The master server listens on the specified port + for incoming connections from replicas. See also <olink targetptr="replication_source"/>, which complements this setting on the replica side.</entry> @@ -612,11 +613,16 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>NULL</entry> <entry>no</entry> <entry><emphasis role="strong">yes</emphasis></entry> - <entry>Pair ip:port describing the master. If not empty, - replication is on, and Tarantool does not accept updates + <entry>If replication_source is not an empty string, the + server is considered to be a Tarantool replica. + The replica server will try to connect to the master + which replication_source specifies with format ip:port. + For example, if replication_source = "1.2.3.4:55555" then + the replica server tries to connect to 1.2.3.4 port 55555. + A replica server does not accept updates on <olink targetptr="primary_port"/>. This parameter is - dynamic, that is, to enter master mode, simply set the - value to an empty string and issue <olink + dynamic, that is, to enter master mode, simply set + replication_source to an empty string and issue <olink targetptr="box.cfg.reload"/>.</entry> </row> @@ -649,11 +655,11 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>0.0</entry> <entry>no</entry> <entry>yes</entry> - <entry>If non-zero, a sleep given duration is - injected between iterations of the event loop. Can be + <entry>The server will sleep for io_collect_interval seconds + 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 + not so frequent (for example, each connection issues just a handful of requests per second). </entry> </row> @@ -663,14 +669,14 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>16384</entry> <entry>no</entry> <entry>no</entry> - <entry>The size of read-ahead buffer associated with a - client connection. The larger is the buffer, the more - memory an active connection consumes and more requests + <entry>The size of the read-ahead buffer associated with a + client connection. The larger the buffer, the more + memory an active connection consumes and the more requests can be read from the operating system buffer in a single - system call. The rule of tumb is to make sure the buffer + system call. The rule of thumb is to make sure the buffer can contain at least a few dozen requests. Therefore, if a typical tuple in a request is large, e.g. a few - kilobytes or even megabytes, the readahead buffer should + kilobytes or even megabytes, the read-ahead buffer size should be increased. If batched request processing is not used, it's prudent to leave this setting at its default.</entry> @@ -682,7 +688,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>1024</entry> <entry>no</entry> <entry>no</entry> - <entry>The size of listen backlog.</entry> + <entry>The size of the listen backlog.</entry> </row> </tbody> @@ -717,10 +723,10 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <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 + one 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. + changed with the "logger" configuration parameter. </entry> </row> @@ -747,7 +753,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <entry>0</entry> <entry>no</entry> <entry>no</entry> - <entry>If this option is given, Tarantool does not + <entry>If logger_nonblock equals 1, 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 @@ -764,7 +770,7 @@ tarantool_box: primary@sessions pri:33013 sec:33014 adm:33015</programlisting> <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 + Has effect only if log_level is less than or equal to 3 (WARNING).</entry> </row> diff --git a/doc/user/connectors.xml b/doc/user/connectors.xml index 5ed2d5c1352926803437504ca950dabf37fcde3f..32883b956f3d5bdc631eb631cca33df89c61fb37 100644 --- a/doc/user/connectors.xml +++ b/doc/user/connectors.xml @@ -11,10 +11,182 @@ This chapter documents APIs for various programming languages. </para></blockquote> +<section xml:id="connector-packet-example"> +<title>Packet example</title> +<para> +The Tarantool API exists so that a client program can send a request packet +to the server, and receive a response. Here is an example of a what the client + would send for <command>INSERT INTO t0 VALUES ('A','BB')</command>. The BNF description of the components +is in file <link xlink:href="https://github.com/tarantool/tarantool/blob/master/doc/box-protocol.txt" xlink:title="A complete BNF of Tarantool client/server protocol">doc/box-protocol.txt</link>. +</para> + <informaltable frame='topbot'> + <tgroup cols='5' align='left' colsep='1' rowsep='1'> + <colspec colname='c1'/> + <colspec colname='c2'/> + <colspec colname='c3'/> + <colspec colname='c4'/> + <colspec colname='c5'/> + <thead> + <row> + <entry>Component</entry> + <entry>Byte#0</entry> + <entry>Byte#1</entry> + <entry>Byte#2</entry> + <entry>Byte#3</entry> + </row> + </thead> + <tbody> + <row> + <entry>type</entry> + <entry>13</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + </row> + <row> + <entry>body_length</entry> + <entry>17</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + </row> + <row> + <entry>request_id</entry> + <entry>1</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + </row> + <row> + <entry>space_no</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + </row> + <row> + <entry>flags</entry> + <entry>2</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + </row> + <row> + <entry>cardinality</entry> + <entry>2</entry> + <entry>0</entry> + <entry>0</entry> + <entry>0</entry> + </row> + <row> + <entry>field[0] size</entry> + <entry>1</entry> + <entry namest="c1" nameend="c4"></entry> + </row> + <row> + <entry>field[0] data</entry> + <entry>65</entry> + <entry namest="c2" nameend="c4"></entry> + </row> + <row> + <entry>field[1] size</entry> + <entry>2</entry> + <entry namest="c2" nameend="c5"></entry> + </row> + <row> + <entry>field[1] data</entry> + <entry>66</entry> + <entry>66</entry> + <entry namest="c3" nameend="c4"></entry> + </row> + </tbody> + </tgroup> + </informaltable> +<para> +Now, one could send that packet to the tarantool_box server, +and interpret the response (box-protocol.txt has a description +of the packet format for responses as well as requests). +But it would be easier, and less error-prone, if one could +invoke a routine that formats the packet according to typed +parameters. Something like <code>response=tarantool_routine("insert",0,"A","B");</code>. +And that is why APIs exist for drivers for C, Perl, Python, PHP, Ruby, and so on. +</para> + </section> + <section xml:id="connector-c"> <title>C</title> <para> - Please see <link + Here is a complete C program that inserts ['A','BB'] into space[0] via the C API for the + binary protocol. To compile, paste the code into a file named example.c and say <code> + gcc -o example example.c -I/<replaceable>tarantool-directory</replaceable>/connector/c/include</code> + where tarantool-directory = the directory that contains + the necessary file <filename>tp.h</filename>, and the default library path contains + the directory where Tarantool library files were placed at installation time. + Before trying to run, check that the server + (tarantool_box) is running on localhost (127.0.0.1) and its primary port is the default (33013) and + space[0]'s primary key type is string (space[0].index[0].key_field[0].type = "STR" in configuration file). + To run, say <code>./example</code>. + The program will format a buffer for sending an INSERT request, then open a socket connection + with the tarantool_box server at localhost:33013, then send the request, then check if the + server returned an error, then — if all is well — print "Insert succeeded". If the + row already exists, the program will print <quote>Duplicate key exists in unique index 0</quote>. + </para> +<programlisting language="cpp"> +#include <arpa/inet.h> +#include <stdio.h> +#include <tp.h> /* the usual Tarantool include */ + +int main() +{ + struct tp request; /* area for sending to server */ + struct tp reply; /* area for getting server reply */ + int fd; /* file descriptor for socket */ + struct sockaddr_in tt; /* the usual socket address info */ + tp_init(&request, NULL, 0, tp_realloc, NULL) /* initialize request buffer */ + tp_insert(&request, 0, 2); /* append INSERT header */ + tp_tuple(&request); /* begin appending body */ + tp_sz(&request,""); /* append field[0] */ + tp_sz(&request,"BB"); /* append field[1] */ + if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 0) /* open the socket, abort if failure */ + exit(1); + memset(&tt, 0, sizeof(tt)); /* connect to localhost:33013 */ + tt.sin_family = AF_INET; + tt.sin_addr.s_addr = inet_addr("127.0.0.1"); + tt.sin_port = htons(33013); + if (connect(fd, (struct sockaddr *) &tt, sizeof(tt)) <= 0) /* connect, abort if failure */ + exit(1); + int rc = write(fd, tp_buf(&request), tp_used(&request)); /* send the INSERT request */ + if (rc != tp_used(&request)) /* abort if send failed */ + exit(1); + tp_init(&reply, NULL, 0, tp_realloc, NULL); /* initialize reply buffer */ + while (1) { + ssize_t to_read = tp_req(&reply); + if (to_read <= 0) + break; + ssize_t new_size = tp_ensure(&reply, to_read); + if (new_size == -1) /* abort if error e.g. no memory */ + exit(1); + ssize_t res = read(fd, reply.p, to_read); /* get reply */ + if (res <= 0) /* abort if error e.g. no reply */ + exit(1); + tp_use(&reply, res); + } + ssize_t server_code = tp_reply(&reply); /* display+abort if error e.g. duplicate key */ + if (server_code != 0) { + printf("error: %-.*s\n", tp_replyerrorlen(&reply), + tp_replyerror(&reply)); + tp_free(&reply); + exit(1); + } + tp_free(&request); /* clean up */ + tp_free(&reply); + close(fd); + printf("Insert succeeded\n"); /* congratulate self */ +} +</programlisting> + <para> + The example program only shows one command and does not show all that's necessary for + good practice. For that, please see <link xlink:href="https://github.com/tarantool/tarantool/blob/master/connector/c/include/tp.h"><filename>connector/c</filename></link> in the source tree. </para> </section> @@ -29,6 +201,7 @@ <section xml:id="connector-perl"> <title>Perl</title> <para> + The Perl driver requires a schema definition. Please refer to CPAN module <link xlink:href='http://search.cpan.org/~unera/DR-Tarantool/'>DR::Tarantool</link>. </para> </section> diff --git a/doc/user/data-model.xml b/doc/user/data-model.xml index 47a47ae652798e55227e33fc359868be879b0c0f..ff446cb5a38bcc5a9ef2c31e5469a5dc1c85df76 100644 --- a/doc/user/data-model.xml +++ b/doc/user/data-model.xml @@ -1,155 +1,279 @@ -<!DOCTYPE section [ -<!ENTITY % tnt SYSTEM "../tnt.ent"> -%tnt; -]> + <section xmlns="http://docbook.org/ns/docbook" version="5.0" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="dynamic-data-model"> + <title>Dynamic data model</title> + +<para> + +If you tried out the <link linkend="getting-started-start-stop"><quote>Starting Tarantool and making your first database</quote></link> +exercise from the last chapter, then your database looks like this: +<programlisting> ++--------------------------------------------+ +| | +| SPACE 'space[0]' | +| +----------------------------------------+ | +| | | | +| | TUPLE SET 't0' | | +| | +-----------------------------------+ | | +| | | Tuple: [ 1 ] | | | +| | | Tuple: [ 2, 'Music' ] | | | +| | | Tuple: [ 3, 'length', 93 ] | | | +| | +-----------------------------------+ | | +| | | | +| | INDEX 'index[0]' | | +| | +-----------------------------------+ | | +| | | Key: 1 | | | +| | | Key: 2 | | | +| | | Key: 3 | | | +| | +-----------------------------------+ | | +| | | | +| +----------------------------------------+ | ++--------------------------------------------+ +</programlisting> +</para> + +<bridgehead renderas="sect2">Space</bridgehead> + +<para> +A <emphasis>space<alt>the paradigm of tuples and spaces is +derived from distributed computing</alt></emphasis> -- 'space[0]' in the example -- is a container. +</para> +<para> +There is always at least one space; there can be many spaces, +numbered as space[0], space[1], and so on. Spaces always +contain one tuple set and one or more indexes. +</para> + +<bridgehead renderas="sect2">Tuple Set</bridgehead> + +<para> +A <emphasis>tuple set<alt>There's a Wikipedia article about tuples: https://en.wikipedia.org/wiki/Tuple</alt></emphasis> -- 't0' in the example -- is a group of tuples. +</para> +<para> +There is always one tuple set in a space. +For the tarantool client, the identifier of a tuple set is <quote>t</quote> followed by the +space's number, for example <quote>t0</quote> refers to the tuple +set of space[0]. (The letter <quote>t</quote> stands for <quote>tuple set.</quote>) +</para> +<para> +A tuple fills +the same role as a <quote>row</quote> or a <quote>record</quote>, and the +components of a tuple (which we call <quote>fields</quote>) +fill the same role as a +<quote>row column</quote> or <quote>record field</quote>, except that: the +fields of a tuple don't need to have names. +That's why there was no need to pre-define the +tuple set in the configuration file, and that's +why each tuple can have a different number of +elements, and that's why we say that Tarantool has +a <quote>dynamic</quote> data model. +</para> +<para> +Any given tuple may have any number of fields and the +fields may have any of these three types: +NUM (32-bit unsigned integer between 0 and 2,147,483,647), +NUM64 (64-bit unsigned integer between 0 and 18,446,744,073,709,551,615), +or STR (string, any sequence of octets). +The identifier of a field is +<quote>k</quote> followed by the field's number, for example +<quote>k0</quote> refers to the first field of a tuple. +</para> +<note><para>This manual is following the tarantool client convention by +using tuple identifier = <quote>t</quote> followed by the space's number, and +using field identifier = <quote>k</quote> followed by the field's number. +The server knows nothing about such identifiers, it only cares +about the number. Other clients follow different conventions, +and may even have sophisticated ways of mapping meaningful names +to numbers.</para></note> +<para> +When the tarantool client displays a tuple, it surrounds +strings with single quotes, separates fields with commas, +and encloses the tuple inside square brackets. For example: +<computeroutput>[ 3, 'length', 93 ]</computeroutput>. +</para> + +<bridgehead renderas="sect2">Index</bridgehead> + +<para> +An index -- 'index[0]' in the example -- is a group of key values and pointers. +</para> +<para> +There is always at least one index in a space; there can be many. +The identifier of an index is 'index' followed by the index's number +within the space, so in our example there is one index and its +identifier is <quote>index[0]</quote>. +</para> + +<para> +An index may be <emphasis>multi-field</emphasis>, that is, the user can declare +that an index key value is taken from two or more fields +in the tuple, in any order. An index may be <emphasis>unique</emphasis>, that is, the user can declare +that it would be illegal to have the same key value twice. +An index may have <emphasis>one of three types</emphasis>: +HASH which is fastest and uses the least memory but must be unique, +TREE which allows partial-key searching and ordered results, +and BITSET which can be good for searches that contain '=' and 'AND' in the WHERE clause. +The first index -- index[0] -- is called the <emphasis><quote>primary key</quote> index</emphasis> +and it must be unique; all other indexes -- index[1], index[2], and so on -- are +<quote>secondary</quote> indexes. +</para> + +<para> +An index definition always includes at least one identifier of a tuple field and its expected type. +Take our example configuration file, which has the lines:<programlisting>space[0].index[0].key_field[0].fieldno = 0 +space[0].index[0].key_field[0].type = "NUM"</programlisting>The effect is that, for all tuples in t0, field number 0 (k0) +must exist and must be a 32-bit unsigned integer. +</para> + +<para> +For the current version of the Tarantool server, space definitions and index definitions must +be in the configuration file. Administrators must take care that what's in the configuration +file matches what's in the database. If a server is started with the wrong configuration file, +it could behave in an unexpected way or crash. However, it is possible to stop the server +or disable database accesses, then add new spaces and indexes, +then restart the server or re-enable database accesses. +The syntax details for defining spaces and indexes are in chapter 7 + <olink targetdoc="tarantool-user-guide" targetptr="configuration-reference">Configuration reference</olink>. +</para> + + +<bridgehead renderas="sect2">Operations</bridgehead> + +<para> +The basic operations are: the four data-change operations +(INSERT, UPDATE, DELETE, REPLACE), and the data-retrieval +operation (SELECT). There are also minor operations like <quote>ping</quote> +which are not available via the tarantool client's SQL-like +interface but can only be used with the binary protocol. +Also, there are <olink +targetptr="box.index.iterator">index iterator</olink> operations, +which can only be used with Lua stored procedures. +(Index iterators are for traversing indexes one key at a time, +taking advantage of features that are specific +to an index type, for example evaluating Boolean expressions +when traversing BITSET indexes, or going in descending order +when traversing TREE indexes.) +</para> + +<para> +Five examples of basic operations: +<programlisting> +/* Add a new tuple to tuple set t0. + The first field, k0, will be 999 (type is NUM). + The second field, k1, will be 'Taranto' (type is STR). */ +INSERT INTO t0 VALUES (999,'Taranto') + +/* Update the tuple, changing field k1. + The clause "WHERE <replaceable>primary-key-field-identifier</replaceable> = <replaceable>value</replaceable> is mandatory + because UPDATE statements must always have a WHERE clause that + specifies the primary key, which in this case is k0. */ +UPDATE t0 SET k1 = 'Tarantino' WHERE k0 = 999 + +/* Replace the tuple, adding a new field. + This is not possible with the UPDATE statement because + the SET clause of an UPDATE statement can only refer to + fields that already exist. */ +REPLACE INTO t0 VALUES (999,'Tarantella',Tarantula') + +/* Retrieve the tuple. + The WHERE clause is still mandatory, although it does not have to + mention the primary key. */ +SELECT * FROM t0 WHERE k0 = 999 + +/* Delete the tuple. + Once again the clause "WHERE k0 = <replaceable>value</replaceable> is mandatory. */ +DELETE FROM t0 WHERE k0 = 999 +</programlisting> +</para> + +<para> +How does Tarantool do a basic operation? Let's take this example: +<programlisting> +UPDATE t0 SET k1 = 'size', k2=0 WHERE k0 = 3 +</programlisting> +</para> + +<para> +STEP #1: the client parses the statement and changes it to a +binary-protocol instruction which has already been checked, +and which the server can understand without needing to parse +everything again. The client ships a packet to the server. +</para> +<para> +STEP #2: the server's <quote>transaction processor</quote> thread uses the +primary-key index on field k0 to find the location of the +tuple in memory. It determines that the tuple can be updated +(not much can go wrong when you're merely changing an unindexed +field value to something shorter). +</para> +<para> +STEP #3: the transaction processor thread sends a message to +the <emphasis>write-ahead logging<alt>There's a Wikipedia article about write-ahead logging: https://en.wikipedia.org/wiki/Write-ahead_logging</alt></emphasis> (WAL) thread. +</para> +<para> +At this point a <quote>yield</quote> takes place. To know +the significance of that -- and it's quite significant -- you +have to know a few facts and a few new words. +</para> +<para> +FACT #1: there is only one transaction processor thread. +Some people are used to the idea that there can be multiple +threads operating on the database, with (say) thread #1 +reading row #x while thread#2 writes row#y. With Tarantool +no such thing ever happens. Only the transaction processor +thread can access the database, and there is only one +transaction processor thread for each instance of the server. +</para> +<para> +FACT #2: the transaction processor thread can handle many +<emphasis>fibers<alt>There's a Wikipedia article about fibers: https://en.wikipedia.org/wiki/Fiber_%28computer_science%29</alt></emphasis>. +A fiber is a set of computer instructions that may contain <quote>yield</quote> signals. +The transaction processor thread will execute all computer instructions +until a yield, then switch to execute the instructions of a different fiber. +Thus (say) the thread reads row#x for the sake of fiber#1, +then writes row#y for the sake of fiber#2. +</para> +<para> +FACT #3: yields must happen, otherwise the transaction processor thread +would stick permanently on the same fiber. There are implicit yields: +every data-change operation or network-access causes an implicit yield, +and every statement that goes through the tarantool client causes an +implicit yield. And there are explicit yields: in a Lua stored procedure +one can and should add <quote>yield</quote> statements to prevent hogging. +This is called <emphasis>cooperative multitasking<alt>There's a Wikipedia +article with a section about cooperative multitasking: +https://en.wikipedia.org/wiki/Cooperative_multitasking#Cooperative_multitasking.2Ftime-sharing</alt></emphasis>. +</para> +<para> +Since all data-change operations end with an implicit yield and +an implicit commit, and since no data-change operation can change +more than one tuple, there is no need for any locking. +Consider, for example, a stored procedure that does three operations:<programlisting> +SELECT /* this does not yield and does not commit */ +UPDATE /* this yields and commits */ +SELECT /* this does not yield and does not commit */</programlisting> +The combination <quote>SELECT plus UPDATE</quote> is an atomic transaction: +the stored procedure holds a consistent view of the database +until the UPDATE ends. For the combination <quote>UPDATE plus SELECT</quote> +the view is not consistent, because after the UPDATE the transaction processor +thread can switch to another fiber, and delete the tuple that +was just updated. +</para> +<para> +Since locks don't exist, and disk writes only involve the write-ahead log, +transactions are usually fast. Also the Tarantool server may not be +using up all the threads of a powerful multi-core processor, +so advanced users may be able to start a second Tarantool +server on the same processor without ill effects. +</para> <para> - Tarantool data is organized in <emphasis>tuples</emphasis>. Tuple - length is varying: a tuple can contain any number - of fields. A field can be either numeric — - 32- or 64- bit unsigned integer, or binary - string — a sequence of octets. - Tuples are stored and retrieved by means of indexing. An index - can cover one or multiple fields, in any order. Fields included - into the first index are always assumed to be the identifying - (unique) key. The remaining fields make up a value, associated - with the key. -</para> -<para> - Apart from the primary key, it is possible to define secondary - <emphasis>indexes</emphasis> on other tuple fields. - - A secondary index does not have to be unique and can cover - multiple fields. The total number of fields in a tuple must be - at least equal to the ordinal number of the last field - participating in any index. -</para> -<para> - Supported index types are HASH, TREE and BITSET. HASH - index is the fastest one, with smallest memory footprint. - TREE index, in addition to key/value look ups, support partial - key lookups, key-part lookups for multipart keys and ordered - retrieval. BITSET indexes, while can serve as a standard unique - key, are best suited for bit-pattern look-ups, i.e. search for - objects satisfying multiple properties. -</para> -<para> - Tuple sets together with defined indexes form - <emphasis>spaces<alt>the paradigm of tuples and spaces is - derived from distributed computing</alt></emphasis>. - - The basic server operations are insert, replace, delete, - update, which modify a tuple in a space, and select, - which retrieves tuples from a space. All operations that modify - data require the primary key for look up. Select, however, may - use any index. - </para> - <para> - A Lua stored procedure can combine multiple - trivial commands, as well as access data using <olink - targetptr="box.index.iterator">index iterators</olink>. Indeed, - the iterators provide full access to the power of indexes, - enabling index-type specific access, such as boolean expression - evaluation for BITMAP indexes, or reverse range retrieval for - TREEs. -</para> -<para> - All operations in Tarantool are atomic and durable: they are - either executed and written to the write ahead log or rolled back. - A stored procedure, containing a combination of basic operations, - holds a consistent view of the database as long as it doesn't - incur writes to the write ahead log or to network. In particular, - a select followed by an update or delete is atomic. -</para> -<para> - While the subject of each data changing command is a - single tuple, an update may modify one or more tuple fields, as - well as add or delete fields, all in one command. It thus - provides an alternative way to achieve multi-operation - atomicity. -</para> -<para> - Currently, entire server <emphasis>schema</emphasis> must be - specified in the configuration file. The schema contains all - spaces and indexes. A server started with a configuration - file that doesn't match contents of its data directory will most - likely crash, but may also behave in a non-defined way. - It is, however, possible to stop the server, - add new spaces and indexes to the schema or temporarily disable - existing spaces and indexes, and then restart the server. -</para> -<para> - Schema objects, such as spaces and indexes, are referred to - by a numeric id. For example, to insert a tuple, it is necessary - to provide id of the destination space; to select - a tuple, one must provide the identifying key, space id and - index id of the index used for lookup. Many Tarantool drivers - provide a local aliasing scheme, mapping numeric identifiers - to names. Use of numeric identifiers on the wire protocol - makes it lightweight and easy to parse. -</para> - -<para> - The configuration file shipped with the binary package defines - only one space with id <literal>0</literal>. It has no keys - other than the primary. The primary key numeric id is also - <literal>0</literal>. Tarantool command line client - supports a small subset of SQL, and it'll be used to - demonstrate supported data manipulation commands: - <programlisting> - localhost> insert into t0 values (1) - Insert OK, 1 row affected - localhost> select * from t0 where k0=1 - Found 1 tuple: - [1] - localhost> insert into t0 values ('hello') - An error occurred: ER_ILLEGAL_PARAMS, 'Illegal parameters' - localhost> replace into t0 values (1, 'hello') - Replace OK, 1 row affected - localhost> select * from t0 where k0=1 - Found 1 tuple: - [1, 'hello'] - localhost> update t0 set k1='world' where k0=1 - Update OK, 1 row affected - localhost> select * from t0 where k0=1 - Found 1 tuple: - [1, 'world'] - localhost> delete from t0 where k0=1 - Delete OK, 1 row affected - localhost> select * from t0 where k0=1 - No match</programlisting> - - <itemizedlist> - <title>Please observe:</title> - <listitem><para> - Since all object identifiers are numeric, Tarantool SQL subset - expects identifiers that end with a number (<literal>t0</literal>, - <literal>k0</literal>, <literal>k1</literal>, and so on): - this number is used to refer to the actual space or - index. - </para></listitem> - <listitem><para> - All commands actually tell the server which key/value pair - to change. In SQL terms, that means that all DML statements - must be qualified with the primary key. WHERE clause - is, therefore, mandatory. - </para></listitem> - <listitem><para> - REPLACE replaces data when a - tuple with given primary key already exists. Such replace - can insert a tuple with a different number of fields. - </para></listitem> - </itemizedlist> -</para> -<para> - Additional examples of SQL statements can be found in <citetitle + Additional examples of SQL statements can be found in the <citetitle xlink:href="https://github.com/tarantool/tarantool/tree/master/test/box" xlink:title="Tarantool regression test suite">Tarantool regression test suite</citetitle>. A complete grammar of - supported SQL is provided in <olink targetdoc="tarantool-user-guide" targetptr="language-reference">Language reference</olink> chapter. + supported SQL is provided in the <olink targetdoc="tarantool-user-guide" targetptr="language-reference">Language reference</olink> chapter. </para> <para> Since not all Tarantool operations can be expressed in SQL, to gain diff --git a/doc/user/errcode.xml b/doc/user/errcode.xml index 03a68e5292b9e83c43a2e11bf5cd00cad76b939d..d209e8e710dc1d9de276c9b956665c78dada43f8 100644 --- a/doc/user/errcode.xml +++ b/doc/user/errcode.xml @@ -44,13 +44,6 @@ file <filename xlink:href="https://github.com/tarantool/tarantool/blob/master/in </para></listitem> </varlistentry> - <varlistentry> - <term xml:id="ER_INDEX_VIOLATION" xreflabel="ER_INDEX_VIOLATION">ER_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="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 diff --git a/doc/user/limitations.xml b/doc/user/limitations.xml new file mode 100644 index 0000000000000000000000000000000000000000..e0404d76d652c741f6f2eebaf13c25d8cf89bdd4 --- /dev/null +++ b/doc/user/limitations.xml @@ -0,0 +1,64 @@ +<appendix xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xlink="http://www.w3.org/1999/xlink" + xml:id="limitations"> + +<title>Limitations</title> + + +<variablelist> + + <varlistentry> + <term xml:id="limitations-index-field-count" xreflabel="limitations-index-field-count">Number of fields in an index</term> + <listitem><para>For BITSET indexes, the maximum is 1. + For TREE indexes, the theoretical maximum is about 4 billion (BOX_FIELD_MAX) + but the practical maximum is the number of fields in a tuple. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="limitations-index-count" xreflabel="limitations-index-count">Number of indexes in a space</term> + <listitem><para>10 (BOX_INDEX_MAX). + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="limitations-tuple-field-count" xreflabel="limitations-tuple-field-count">Number of fields in a tuple</term> + <listitem><para>There is no theoretical maximum. + The practical maximum is whatever is specified by space.cardinality in the configuration file, + or the maximum tuple length. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="limitations-space-count" xreflabel="limitations-space-count">Number of spaces</term> + <listitem><para>255. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="limitations-connections-count" xreflabel="limitations-connections-count">Number of connections</term> + <listitem><para>The practical limit is the number of file descriptors that one can set with + the operating system. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="limitations-slab-alloc-arena-size" xreflabel="limitations-slab-alloc-arena-size">Space size</term> + <listitem><para>The total maximum size for all spaces is in effect set by the slab_alloc_arena_size + parameter in the configuration file, which in turn is limited by the total available memory. + </para></listitem> + </varlistentry> + + <varlistentry> + <term xml:id="limitations-update-count" xreflabel="limitations-updae-count">Update operations count</term> + <listitem><para>The maximum number of operations that can be in a single update is 4000 (BOX_UPDATE_OP_CNT_MAX). + </para></listitem> + </varlistentry> + +</variablelist> +</appendix> + +<!-- +vim: tw=66 syntax=docbk +vim: spell spelllang=en_us +--> diff --git a/doc/user/preface.xml b/doc/user/preface.xml index 6622718cf9622f343348b902c5b0f19673b3b326..576c7de44f7a30bbb2cdbd6a2ad2ad35e4e79172 100644 --- a/doc/user/preface.xml +++ b/doc/user/preface.xml @@ -110,7 +110,7 @@ Outside Mail.Ru the software is used by a growing number of projects in online gaming, digital marketing, and social media industries. While product development is sponsored by Mail.Ru, the - roadmap and the bugs database and the development process are fully + roadmap, the bugs database and the development process are fully open. The software incorporates patches from dozens of community contributors. The Tarantool community writes and maintains most of the drivers for programming languages. @@ -151,17 +151,7 @@ contact developers directly on <link xlink:href="irc://irc.freenode.net#tarantool">#tarantool</link> IRC channel or via a mailing list, - <link xlink:href="https://launchpad.net/~tarantool-developers">tarantool-developers@lists.launchpad.net</link>. - </para> - <para> - <emphasis role="strong">Caution:</emphasis> To prevent spam, the Launchpad - mailing-list software silently drops all mail coming from - non-registered email addresses -- so register with Launchpad - before sending emails. Launchpad registration also - allows you to report bugs and create feature requests. - You can check that your mail was delivered by looking at the - mailing list archive, <link - xlink:href="https://lists.launchpad.net/tarantool-developers"/>. + <link xlink:href="https://googlegroups.com/group/tarantool">Tarantool Google group</link>. </para> </section> diff --git a/doc/user/proctitle.xml b/doc/user/proctitle.xml index dc26fffba0b4708ad02bbac77eb67312fbc85448..4438caddcd44835f2f6f95d87efe35ff7a8c404d 100644 --- a/doc/user/proctitle.xml +++ b/doc/user/proctitle.xml @@ -12,9 +12,9 @@ <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 + Tarantool uses this feature to help meet the needs of system administration, such as figuring out what services are running - on a host, TCP/IP ports in use, et cetera. + on a host, what TCP/IP ports are in use, and so on. </para> <para> Tarantool process title follows the following naming scheme: @@ -31,11 +31,6 @@ <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, @@ -55,13 +50,10 @@ 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> + <command>tarantool_box: primary pri: 50000 sec: 50001 adm: 50002</command> </para></listitem> <listitem><para> - <command>tarantool_box: wal_writer</command> + <command>tarantool_box: primary@infobox pri: 15013 sec: 15523 adm: 10012</command> </para></listitem> </itemizedlist> </para> diff --git a/doc/user/server-administration.xml b/doc/user/server-administration.xml index b7583f5526d45acc8bf5b55ef342267ecd13e404..88e931a8b93380e543c6bffa008f5fe948bd625b 100644 --- a/doc/user/server-administration.xml +++ b/doc/user/server-administration.xml @@ -21,9 +21,67 @@ control flow never reaches the event loop (thanks to a runaway stored procedure), the server stops responding to any signal, and can be only killed with SIGKILL (this signal can not be ignored). +</para> +</section> + +<section xml:id="tarantar"> +<title>Utility <code>tarantar</code></title> +<para> +The tarantar utility program will create new snapshots by reading existing +snapshots and write-ahead-log (xlog) files. Thus it differs from <olink targetptr="save-snapshot"/>, +which creates new snapshots from the database. Since tarantar uses less +memory than SAVE SNAPSHOT, it is especially appropriate for taking periodic +snapshots as a background task. +</para> +<para> +To prepare: ensure that the configuration file contains +<olink targetptr="wal_dir"/> and <olink targetptr="snap_dir"/> +clauses. Tarantar does not assume that wal_dir and snap_dir have default values. +</para> +<para> +To run:<programlisting> <command>tarantar</command> [options] <replaceable>configuration-file</replaceable></programlisting> +where possible options are:<simplelist> <member><code>-i <replaceable>seconds-count</replaceable></code> or <code>--interval <replaceable>seconds-count</replaceable></code> — repeat every seconds-count seconds. example: <code>-i 3600</code></member> + <member><code>-n <replaceable>lsn-number</replaceable></code> or <code>--lsn <replaceable>lsn-number</replaceable></code> — start from lsn = lsn-number. if not specified, lsn = latest. example: <code>-n 5</code></member> + <member><code>-l <replaceable>bytes-count</replaceable></code> or <code>--limit <replaceable>bytes-count</replaceable></code> — do not use more than bytes-count bytes of memory. example: <code>-l 5000000</code></member> + <member><code>--help </code> — display a help message and exit. example: <code>--help</code></member> + <member><code>-v </code> or <code>--version</code> — display version and exit. example: <code>-v</code></member></simplelist></para> +<para> +Example: +<programlisting> +<prompt>$ </prompt>~/tarantool/client/tarantar/tarantar -c -i 30 ./tarantool.cfg +snap_dir: /home/user/tarantool_test/work_dir +wal_dir: /home/user/tarantool_test/work_dir +spaces: 1 +interval: 30 +memory_limit: 0M + +START SNAPSHOTTING Fri Oct 25 09:35:25 2013 + +last snapshot lsn: 7 +(snapshot) 00000000000000000007.snap 0.000M processed +( >> ) 00000000000000000006.snap 0.000M processed + +START SNAPSHOTTING Fri Oct 25 09:35:55 2013 + +last snapshot lsn: 7 +(snapshot) 00000000000000000007.snap 0.000M processed + +( >> ) 00000000000000000006.snap 0.000M processed + +snapshot exists, skip. + +... + +</programlisting> </para> + +<para> +For an explanation of tarantar's design see <link xlink:href="https://github.com/tarantool/tarantool/wiki/Tarantar">the Tarantool wiki</link>. +</para> + </section> + <section xml:id="os-install-notes"> <title>System-specific administration notes</title> <blockquote><para> diff --git a/doc/user/space.xml b/doc/user/space.xml index 4b37baabf0e1f000f40706ebd9b7b9c1de085bc1..bf21eb877a399beaccc79bcf545d4049245c9e9f 100644 --- a/doc/user/space.xml +++ b/doc/user/space.xml @@ -3,7 +3,7 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="space"> <bridgehead>Space settings explained</bridgehead> -Space is a composite parameter, i.e. it has properties. +Space is a composite parameter, that is, it has properties. <programlisting language="cpp"> /* * Each tuple consists of fields. Three field types are @@ -24,10 +24,10 @@ struct index_field_t { }; /* - * HASH and TREE index types are supported. + * HASH and TREE and BITSET index types are supported. */ -enum { HASH, TREE } index_type; +enum { HASH, TREE, BITSET } index_type; struct index_t { index_field_t key_field[]; @@ -41,18 +41,18 @@ struct space_t /* A space can be quickly disabled and re-enabled at run time. */ bool enabled; /* - * If given, each tuple in the space must have exactly + * If cardinality is given, each tuple in the space must have exactly * this many fields. */ unsigned int arity; - /* Only used for HASH indexes, to preallocate memory. */ + /* estimated_rows is only used for HASH indexes, to preallocate memory. */ unsigned int estimated_rows; struct index_t index[]; }; </programlisting> The way a space 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: +one would initialize a C structure in a program. For example, +a minimal storage configuration looks like the following: <programlisting language="c"> space[0].enabled = 1 space[0].index[0].type = HASH diff --git a/doc/user/stored-procedures.xml b/doc/user/stored-procedures.xml index d13e140dcbfd58a1f814886fafe2601307f1cc04..10e85b053967d6aacedc81ca677e598b0fc86799 100644 --- a/doc/user/stored-procedures.xml +++ b/doc/user/stored-procedures.xml @@ -22,13 +22,13 @@ </para> <para> - Tarantool uses <link + Tarantool uses the <link xlink:href="http://www.luajit.org">LuaJIT</link> just-in-time Lua compiler and virtual machine. Apart from increased performance, this provides such features as <link xlink:href="http://bitop.luajit.org/">bitwise - operations</link> and <link xlink:href="#tonumber64">64-bit integer arithmetics.</link> + operations</link> and <link xlink:href="#tonumber64">64-bit integer arithmetic.</link> </para> </blockquote> <para> @@ -44,7 +44,7 @@ Found 1 tuple: </programlisting> In the language of the administrative console <olink targetptr="lua-command" /> evaluates an arbitrary - Lua chunk. CALL is the SQL standard statement, so its syntax + Lua chunk. CALL is an SQL standard statement, so its syntax was adopted by Tarantool command line client to invoke the CALL command of the binary protocol. </para> @@ -55,7 +55,7 @@ Found 1 tuple: parser plus the binary protocol on the <olink targetptr="primary_port" />. Since it's possible to execute any Lua chunk in the administrative console, the newly created <code - language="Pascal">function f1()</code> + language="Lua">function f1()</code> can be called there too: <programlisting><computeroutput>localhost> f1() --- @@ -113,7 +113,7 @@ expirationd.run_task("exprd space 0", 0, is_expired, purge, <para> The initialization script can select and modify data. However, if the server is a running replica, data change requests from - the start script fail just the same way they would fail if + the start script fail just the same way they would fail if they were sent from a remote client. </para> <para> @@ -151,8 +151,8 @@ expirationd.run_task("exprd space 0", 0, is_expired, purge, In the binary protocol, it's only possible to <emphasis role="strong">invoke</emphasis> existing procedures, but not <emphasis role="strong">define</emphasis> - or <emphasis role="strong">alter</emphasis> them. - CALL request packet contains CALL command code (22), the name + or <emphasis role="strong">alter</emphasis> them. The + CALL request packet contains the command code for CALL (22), the name of a procedure to be called, and a tuple for procedure arguments. Currently, Tarantool tuples are type-agnostic, thus each field of the tuple is passed into the procedure @@ -210,7 +210,7 @@ error: 1:15 expected '(' certain operations to be used by a system administrator only. </para> <para> - Every value, returned from a stored function by means of + Every value, returned from a stored function by means of a <code>return</code> clause, is converted to a Tarantool tuple. Tuples are returned as such, in binary form; a Lua scalar, such as a string or an integer, is converted to a tuple with only @@ -223,7 +223,7 @@ error: 1:15 expected '(' is sent to the client as <olink targetptr="ER_PROC_LUA" /> return code, with the original error message preserved. Similarly, an error which has occurred inside Tarantool (observed on the - client as an error code), when happens during execution of a + client as an error code), when it happens during execution of a Lua procedure, produces a genuine Lua error: <programlisting><computeroutput>localhost> function f1() error("oops") end --- @@ -241,7 +241,7 @@ localhost> pcall(box.insert, 99, 1, 'test') </para> <para> It's possible not only to invoke trivial Lua code, but call - into Tarantool storage functionality, using + into Tarantool storage functionality, using the <code>box</code> Lua library. The contents of the library can be inspected at runtime: @@ -262,7 +262,7 @@ replace: function select_range: function pack: function ...</computeroutput></programlisting> - As is shown in the listing, <code>box</code> package ships: + As is shown in the listing, the <code>box</code> package contains: <itemizedlist> <listitem><para> high-level functions, such as @@ -274,7 +274,7 @@ pack: function libraries, such as <code>cfg, space, fiber, index, tuple</code>, to access server configuration, create, resume and interrupt fibers, inspect contents of spaces, indexes - and tuples, send and receive data over network. + and tuples, send and receive data over the network. </para></listitem> </itemizedlist> </para> @@ -287,8 +287,8 @@ pack: function <para>Convert a given string or a Lua number to a 64-bit integer. The returned value supports all arithmetic operations, but uses - 64-bit integer arithmetics, rather than floating-point, - arithmetics as in the built-in number type. + 64-bit integer arithmetic, rather than floating-point + arithmetic as in the built-in number type. <bridgehead renderas="sect4">Example</bridgehead> <programlisting> localhost> tonumber64('123456789'), tonumber64(123456789) @@ -362,7 +362,7 @@ localhost> type(i), type(i*2), type(i/2), i, i*2, i/2 command. </para> <para> - Please note, that since all requests from Lua + Please note that, since all requests from Lua enter the core through <emphasis role="lua">box.process()</emphasis>, all checks and triggers run by the core automatically apply. @@ -437,7 +437,7 @@ localhost> box.select(5, 1, 'firstname', 'lastname') <para> Search for tuples in the given space. This is a full version of the built-in SELECT command, in - which one can specify offset and limit in a + which one can specify offset and limit for a multi-tuple return. The server may return multiple tuples when the index is non-unique or a partial key is used for search. @@ -509,34 +509,65 @@ localhost> box.select(5, 1, 'firstname', 'lastname') Returns the updated tuple. <bridgehead renderas="sect4">Example</bridgehead> <programlisting> -localhost> box.insert(0, 0, 'hello world') ---- - - 0: {'hello world'} -... -localhost> box.update(0, 0, '+p', 1, 1) -- add value 1 to field #1 ---- -error: 'Field type does not match one required by operation: expected a 32-bit or 64-bit int' -... -localhost> box.update(0, 0, '+p', 0, 2) -- add value 2 to field 0 ---- - - 2: {'hello world'} -... -localhost> box.update(0, 2, '!p', 1, 'Bienvenue tout le monde!') ---- - - 2: {'Bienvenue tout le monde!', 'hello world'} -... -localhost> box.update(0, 2, '#p', 2, 1) ---- - - 2: {'Bienvenue tout le monde!'} -... -localhost> box.insert(0, 3, 'crocodile', 'giraffe', 'baobab', 'bamblebee', 'hippopotamus', 'rhino') ---- - - 3: {'crocodile', 'giraffe', 'baobab', 'bamblebee', 'hippopotamus', 'rhino'} -... -localhost> box.update(0, 3, '#p', 3, 2) ---- - - 3: {'crocodile', 'giraffe', 'hippopotamus', 'rhino'} -... +#Assume that the initial state of the database is ... +# space[0] has one tuple set and one primary key whose type is 32-bit integer. +# There is one row, with field[0] = 999 and field[1] = 'A'. + +#In the following update ... +# The first argument is 0, that is, the affected space is space[0] +# The second argument is 999, that is, the affected tuple is identified by primary key value = 999 +# The third argument is '=p', that is, there is one operation, assignment to a field +# The fourth argument is 1, that is, the affected field is field[1] +# The fifth argument is 'B', that is, field[1] contents change to 'B' +# Therefore, after the following update, field[0] = 999 and field[1] = 'B'. +lua box.update(0, 999, '=p', 1, 'B') + +#In the following update, the arguments are the same, except that ... +# the key is passed as a Lua table (inside braces). This is unnecessary +# when the primary key has only one field, but would be necessary if the +# primary key had more than one field. +# Therefore, after the following update, field[0] = 999 and field[1] = 'B' (no change). +lua box.update(0, {999}, '=p', 1, 'B') + +#In the following update, the arguments are the same, except that ... +# The fourth argument is 2, that is the affected field is field[2]. +# It is okay that, until now, field[2] has not existed. It gets added. +# Therefore, after the following update, field[0] = 999, field[1] = 'B', field[2] = 1. +lua box.update(0, 999, '=p', 2, 1) + +#In the following update, the arguments are the same, except that ... +# The third argument is '+p', that is, the operation is addition rather than assignment. +# Since field[2] previously contained 10, this means we're adding 1 to 1. +# Therefore, after the following update, field[0] = 999, field[1] = 'B', field[2] = 2. +lua box.update(0, 999, '+p', 2, 1) + +#In the following update ... +# The idea is to modify two fields at once. +# The third argument is '|p=p', that is, there are two operations, OR and assignment. +# The fourth and fifth arguments mean that field[2] gets ORed with 1. +# The fifth and sixth arguments mean that field[1] gets assigned 'C'. +# Therefore, after the following update, field[0] = 999, field[1] = 'C', field[2] = 3. +lua box.update(0, 999, '|p=p', 2, 1, 1, 'C') + +#In the following update ... +# The idea is to delete field[1], then subtract 3 from field[2], but ... +# after the delete, there is a renumbering -- so field[2] becomes field[1] +# before we subtract 3 from it, and that's why the sixth argument is 1 not 2. +# Therefore, after the following update, field[0] = 999, field[1] = 0. +lua box.update(0, 999, '#p-p', 1, 0, 1, 3) + +#In the following update ... +# We're making a long string so that the splice will work in the next example. +# Therefore, after the following update, field[0[ = 999, field[1] = 'XYZ'. +lua box.update(0, 999, '=p', 1, 'XYZ') + +#In the following update ... +# The third argument is ':p', that is, this is the example of splice. +# The fifth argument is actually four arguments packed together ... +# a filler, an offset, the number of bytes to cut (1), and the string to add ('!') +# Therefore, after the following update, field[0[ = 999, field[1] = 'X!Z'. +lua box.update(0, 999, ':p', 1, box.pack('ppp', 1, 1, '!')) + </programlisting> </para> </listitem> @@ -569,7 +600,7 @@ Call ERROR, Illegal parameters, key is not u32 (ER_ILLEGAL_PARAMS) </emphasis> </term> <listitem><para> - Select a range of tuples, starting from offset + Select a range of tuples, starting from the offset specified by <code>key</code>. The key can be multipart. Limit selection with at most <code>limit</code> tuples. If no key is specified, @@ -653,7 +684,7 @@ localhost> box.select_range(4, 1, 2, '1') </para> <para> For TREE indexes, this returns tuples in sorted order. - Other index types do not support this call. + For other index types this call is not supported. If <code>key</code> is <code>nil</code> or unspecified, the selection starts from the end of the index. <bridgehead renderas="sect4">Example</bridgehead> @@ -764,7 +795,7 @@ localhost> box.select_reverse_range(4, 1, 2, '1') </member> <member><code>p</code> — stores the length of the argument as a BER-encoded integer - followed by the argument itself (a 4-bytes for integers (LE order) + followed by the argument itself (a little-endian 4-byte integer for integers, and a binary blob for other types), </member> <member><code>=, +, &, |, ^, : </code>— @@ -947,7 +978,7 @@ box.dostring('local f = function(key) t=box.select(0, 0, key); if t ~= nil then </para> <para> Requires <emphasis>libuuid</emphasis> library to be - installed. The library is loaded in runtime, + installed. The library is loaded at runtime, and if the library is not available, this function returns an error. </para> @@ -960,7 +991,7 @@ box.dostring('local f = function(key) t=box.select(0, 0, key); if t ~= nil then <listitem> <para> Generate hex-string of 128-bit (16 bytes) unique id. - Return 32-bytes string. + Return 32-byte string. </para> <bridgehead renderas="sect4">Example</bridgehead> <programlisting> @@ -979,11 +1010,11 @@ box.dostring('local f = function(key) t=box.select(0, 0, key); if t ~= nil then <para> Raises a client error. The difference between this function and the built-in <code>error()</code> function in Lua - is that when the error reaches the client, it's error code + is that when the error reaches the client, its error code is preserved, whereas every Lua error is presented to the client as <constant>ER_PROC_LUA</constant>. This function makes it possible to emulate any kind of native exception, - such as a unique constraint violation, no such space/index, + such as unique constraint violation, no such space/index, etc. A complete list of errors is present in <link xlink:href="https://github.com/tarantool/tarantool/blob/master/include/errcode.h">errcode.h</link> file in the source tree. Lua constants which correspond to Tarantool errors @@ -1030,11 +1061,11 @@ localhost> box.auto_increment(0, "I am a duplicate") <listitem> <para> Increments a counter identified by the key. The key can be - multi-part, but there must be an index covering + multipart, but there must be an index covering all fields of the key. If there is no tuple identified by the given key, creates a new one with initial counter value set to 1. Returns the - new counter value back. + new counter value. </para> <bridgehead renderas="sect4">Example</bridgehead> <programlisting>localhost> box.counter.inc(0, 'top.mail.ru') @@ -1075,7 +1106,7 @@ localhost> box.counter.dec(0, 'top.mail.ru') <title>Package <code>box.tuple</code></title> <variablelist xml:id="box.tuple" xreflabel="box.tuple"> - <para>The package stands for <code>box.tuple</code> userdata + <para>This package handles the <code>box.tuple</code> userdata type. It is possible to access individual tuple fields using an index, select a range of fields, iterate over all fields in a tuple or convert a tuple to a Lua table. Tuples are @@ -1263,7 +1294,7 @@ box.cjson.decode('{"hello": "world"}').hello <para>This package is a container for all configured spaces. A space object provides access to space attributes, such as id, whether or not a space is - enabled, space arity, estimated number of rows. It also + enabled, space arity, and estimated number of rows. It also contains object-oriented versions of <code>box</code> functions. For example, instead of <code>box.insert(0, ...)</code> one can write <code>box.space[0]:insert(...)</code>. @@ -1318,7 +1349,7 @@ box.cjson.decode('{"hello": "world"}').hello </term> <listitem> <simpara> - Select a range of tuples, starting from offset specified by + Select a range of tuples, starting from the offset specified by <code>key</code>. The key can be multipart. Limit selection with at most <code>limit</code> tuples. If no key is specified, start from the first key in the index. @@ -1345,13 +1376,12 @@ box.cjson.decode('{"hello": "world"}').hello <simpara> Select a reverse range of tuples, limited by <code>limit</code>, starting from <code>key</code>. - The key can be multipart. TREE index returns - tuples in descending order. Other index types - do not support this call. + The key can be multipart. For TREE indexes, this returns + tuples in descending order. For other index types + this call is not supported. </simpara> </listitem> </varlistentry> - <varlistentry> <term> <emphasis role="lua">space:insert(...)</emphasis> @@ -1455,7 +1485,7 @@ localhost> for k,v in box.space[0]:pairs() do print(v) end <emphasis role="lua">index.type</emphasis> </term> <listitem><simpara> - A string for index type, either 'TREE', 'HASH', 'BITSET'. + A string for index type, either 'TREE', 'HASH', or 'BITSET'. </simpara></listitem> </varlistentry> @@ -1490,20 +1520,20 @@ localhost> for k,v in box.space[0]:pairs() do print(v) end index types support different iterators. The remaining arguments of the function are varying and depend on the iteration type. For example, - TREE index maintains a strict order of keys and + a TREE index maintains a strict order of keys and can return all tuples in ascending or descending order, starting from the specified key. Other index types, however, do not support ordering. </simpara> <para xml:id="iterator-consistency"> - To understand consistency of tuples, + To understand consistency of tuples returned by an iterator, it's essential to know the principles of the Tarantool transaction processing subsystem. An iterator in Tarantool does not own a consistent read view. Instead, each procedure is granted exclusive access to all tuples and spaces until it - encounters a "context switch": caused a write to + encounters a "context switch": by causing a write to disk, network, or by an explicit call to <emphasis role="lua" xlink:href="#box.fiber.yield">box.fiber.yield()</emphasis>. When the execution flow returns to the yielded @@ -1632,7 +1662,7 @@ error: 'Iterator type is not supported' <emphasis role="lua">index:count()</emphasis> </term> <listitem><simpara> - Iterate over an index, count the number of tuples which equal the + Iterate over an index, counting the number of tuples which equal the provided search criteria. The argument can either point to a tuple, a key, or one or more key parts. Returns the number of matched tuples. @@ -1689,10 +1719,10 @@ created. </para> <para> A runaway fiber can be stopped with <code>box.fiber.cancel()</code>. -<code>box.fiber.cancel()</code>, however, is advisory — it works -only if the runaway fiber is calling <code>box.fiber.testcancel()</code> +However, <code>box.fiber.cancel()</code> is advisory — it works +only if the runaway fiber calls <code>box.fiber.testcancel()</code> once in a while. Most <code>box.*</code> hooks, such as <code>box.delete()</code> -or <code>box.update()</code>, are calling <code>box.fiber.testcancel()</code>. +or <code>box.update()</code>, do call <code>box.fiber.testcancel()</code>. <code>box.select()</code> doesn't. </para> <para> @@ -1746,7 +1776,7 @@ and <code>box.fiber.testcancel()</code> is checked whenever such an event occurs <emphasis role="lua" xml:id="box.fiber.create">box.fiber.create(function) </emphasis> </term> <listitem><simpara> - Create a fiber for <code>function</code>. + Create a fiber for a <code>function</code>. </simpara> <bridgehead renderas="sect4">Errors</bridgehead> <simpara>Can hit a recursion limit.</simpara> @@ -1795,7 +1825,7 @@ and <code>box.fiber.testcancel()</code> is checked whenever such an event occurs This is a quick way to create and start a detached fiber. The fiber function is passed in the first argument, the function arguments follow. The fiber is - created detached and resumed immediately. + created, detached, and resumed immediately. </simpara></listitem> </varlistentry> @@ -1855,7 +1885,7 @@ and <code>box.fiber.testcancel()</code> is checked whenever such an event occurs <para> A session is an object associated with each client connection. Through this module, it's possible to query session state, -as well as set a Lua chunk executed on connect or disconnect +as well as set a Lua chunk executed on a connect or disconnect event. </para> <variablelist> @@ -1886,6 +1916,16 @@ event. <listitem><simpara>Return true if a session is alive, false otherwise.</simpara></listitem> </varlistentry> + + <varlistentry> + <term> + <emphasis role="lua">box.session.peer(id) </emphasis> + </term> + <listitem><simpara>Return the host address and port for the session + peer, for example "127.0.0.1:55457", or "0.0.0.0:0" if the session + is not connected.</simpara></listitem> + </varlistentry> + </variablelist> <para> This module also makes it possible to define triggers on connect @@ -2064,7 +2104,7 @@ end BSD sockets is a mechanism to exchange data with a local or remote host in connection-oriented (TCP) or datagram-oriented (UDP) mode. - Semantics of the calls in <code>box.socket</code> API closely follows + Semantics of the calls in the <code>box.socket</code> API closely follow semantics of the corresponding POSIX calls. Function names and signatures are mostly compatible with <link xlink:href="http://w3.impa.br/~diego/software/luasocket/">luasocket</link>. @@ -2108,7 +2148,7 @@ end a long time. </simpara> <simpara> - As all other <code>box</code> libraries, the API can be used + As with all other <code>box</code> libraries, the API can be used in procedural style (e.g. <code>box.socket.close(socket)</code>) as well as in object-oriented style (<code>socket:close()</code>). </simpara> @@ -2260,7 +2300,7 @@ end <para> Start listening for incoming connections. The listen backlog, on Linux, is taken from <filename>/proc/sys/net/core/somaxconn</filename>, - whereas on BSD is set to <constant>SOMAXCONN</constant>. + whereas on BSD it is set to <constant>SOMAXCONN</constant>. <bridgehead renderas="sect4">Returns</bridgehead> Socket on success, <code>nil, "error", errno, errstr</code> on error. </para> @@ -2332,7 +2372,7 @@ end <term><emphasis role="lua">socket:error()</emphasis></term> <listitem> <para> - Retrieve the last error occurred on a socket. + Retrieve the last error that occurred on a socket. <bridgehead renderas="sect4">Returns</bridgehead> <code>errno, errstr</code>. <code>0, "Success"</code> if there is no error. @@ -2370,7 +2410,7 @@ end The library also provides a pre-created connection object to the local server, <code>box.net.self</code>. This connection is always <quote>established</quote>. The - purpose of this object is to make polymorphic use of + purpose of this object is to make polymorphic use of the <code>box.net.box</code> API easier. There is an important difference, however, between the embedded connection and a remote one. With the embedded connection, @@ -2421,7 +2461,7 @@ end Create a new connection. The connection is established on demand, at the time of the first request. It is re-established automatically after - a disconnect. Argument + a disconnect. The argument <code>reconnect_interval</code> (in seconds) is responsible for the amount of time the server sleeps between failing attempts to reconnect. The @@ -2553,7 +2593,7 @@ end <listitem> <para> Returns a closure which is identical to the - invoked function, except the added timeout + invoked function, except for the added timeout functionality. <programlisting> -- wait for 'update' until it is finished @@ -2606,7 +2646,7 @@ logger = cat - >> tarantool.log <para> This package provides access to information about server variables: pid, uptime, version and such. - Its contents is identical to output of <olink + Its contents are identical to the output from <olink targetptr="show-info"/>. </para> <varlistentry> @@ -2615,8 +2655,8 @@ logger = cat - >> tarantool.log </term> <listitem> <simpara> - Since contents of box.info is dynamic, it's not - possible to iterate over keys with Lua + Since box.info contents are dynamic, it's not + possible to iterate over keys with the Lua <emphasis>pairs()</emphasis> function. For this purpose, <emphasis>box.info()</emphasis> builds and returns a Lua table with all keys and values provided @@ -2780,7 +2820,7 @@ localhost> </section> <section xml:id="sp-limitations"> -<title>Limitation of stored procedures</title> +<title>Limitations of stored procedures</title> <para> There are two limitations in stored procedures support one should @@ -2788,12 +2828,12 @@ localhost> </para> <bridgehead renderas="sect4">Cooperative multitasking environment</bridgehead> <para> - Tarantool core is built around cooperative multi-tasking + Tarantool core is built around a cooperative multi-tasking paradigm: unless a running fiber deliberately yields control to some other fiber, it is not preempted. <quote>Yield points</quote> are built into all calls from Tarantool core to the operating system. - Any system call which can block is performed in + Any system call which can block is performed in a asynchronous manner and the fiber waiting on the system call is preempted with a fiber ready to run. This model makes all programmatic locks unnecessary: @@ -2813,14 +2853,14 @@ localhost> long time. This can lead to unfair scheduling, when a single client throttles the rest of the system, or to apparent stalls in request processing. - Avoiding this situation is responsibility of the stored procedure - author. Most of <code>box</code> calls, such as + Avoiding this situation is the responsibility of the stored procedure + author. Most of the <code>box</code> calls, such as <code>box.insert()</code>, <code>box.update()</code>, <code>box.delete()</code> are yield points; <code>box.select()</code> and <code>box.select_range()</code>, however, are not. </para> <para> - It should also be noted, that in absence of transactions, + It should also be noted that, in absence of transactions, any yield in a stored procedure is a potential change in the database state. Effectively, it's only possible to have CAS (compare-and-swap) -like atomic stored diff --git a/doc/user/target.db b/doc/user/target.db index 46ec3d49e68281237b2cbdf971a87a7bd78d4231..cb1b971f7a82a9899ba62e06c308b6e4a5237d91 100644 --- a/doc/user/target.db +++ b/doc/user/target.db @@ -1,7 +1,7 @@ -<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool User Guide, version 1.6.0-345-g1d96f50</ttl><xreftext>Tarantool User Guide, version 1.6.0-345-g1d96f50</xreftext><div element="chapter" href="#preface" number="1" targetptr="preface"><ttl>Preface</ttl><xreftext>Chapter 1, <i>Preface</i></xreftext><div element="section" href="#tarantool-overview" number="" targetptr="tarantool-overview"><ttl>Tarantool: an overview</ttl><xreftext>the section called “Tarantool: an overviewâ€</xreftext></div><div element="section" href="#manual-conventions" number="" targetptr="manual-conventions"><ttl>Conventions</ttl><xreftext>the section called “Conventionsâ€</xreftext></div><div element="section" href="#reporting-bugs" number="" targetptr="reporting-bugs"><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugsâ€</xreftext></div></div><div element="chapter" href="#getting-started" number="2" targetptr="getting-started"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext><div element="section" href="#getting-started-binary" number="" targetptr="getting-started-binary"><ttl>Downloading and installing a binary package</ttl><xreftext>the section called “Downloading and installing a binary packageâ€</xreftext></div><div element="section" href="#getting-started-source" number="" targetptr="getting-started-source"><ttl>Downloading and building a source package</ttl><xreftext>the section called “Downloading and building a source packageâ€</xreftext></div><div element="section" href="#getting-started-start-stop" number="" targetptr="getting-started-start-stop"><ttl>Starting Tarantool and making your first database</ttl><xreftext>the section called “Starting Tarantool and making your first databaseâ€</xreftext></div></div><div element="chapter" href="#data-and-persistence" number="3" targetptr="data-and-persistence"><ttl>Data model and data persistence</ttl><xreftext>Chapter 3, <i>Data model and data persistence</i></xreftext><div element="section" href="#dynamic-data-model" number="" targetptr="dynamic-data-model"><ttl>Dynamic data model</ttl><xreftext>the section called “Dynamic data modelâ€</xreftext></div><div element="section" href="#data-persistence" number="" targetptr="data-persistence"><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="#data-manipulation" number="" targetptr="data-manipulation"><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulationâ€</xreftext></div><div element="section" href="#administrative-console" number="" targetptr="administrative-console"><ttl>Administrative console</ttl><xreftext>the section called “Administrative consoleâ€</xreftext><obj element="term" href="#box.snapshot" number="" targetptr="box.snapshot"><ttl>???TITLE???</ttl><xreftext>box.snapshot()</xreftext></obj><obj element="term" href="#box.cfg.reload" number="" targetptr="box.cfg.reload"><ttl>???TITLE???</ttl><xreftext>box.cfg.reload()</xreftext></obj><obj element="term" href="#box.cfg.show" number="" targetptr="box.cfg.show"><ttl>???TITLE???</ttl><xreftext>box.cfg()</xreftext></obj><obj element="term" href="#box.info" number="" targetptr="box.info"><ttl>???TITLE???</ttl><xreftext>box.info()</xreftext></obj><obj element="term" href="#box.stat.show" number="" targetptr="box.stat.show"><ttl>???TITLE???</ttl><xreftext>box.stat()</xreftext></obj><obj element="term" href="#box.slab.info" number="" targetptr="box.slab.info"><ttl>???TITLE???</ttl><xreftext>box.slab.info()</xreftext></obj><obj element="term" href="#box.coredump" number="" targetptr="box.coredump"><ttl>???TITLE???</ttl><xreftext>box.coredump()</xreftext></obj><obj element="term" href="#box.fiber.info" number="" targetptr="box.fiber.info"><ttl>???TITLE???</ttl><xreftext>box.fiber.info()</xreftext></obj><obj element="term" href="#lua-command" number="" targetptr="lua-command"><ttl>???TITLE???</ttl><xreftext> +<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool User Guide, version 1.6.0-353-gdeb3b39</ttl><xreftext>Tarantool User Guide, version 1.6.0-353-gdeb3b39</xreftext><div element="chapter" href="#preface" number="1" targetptr="preface"><ttl>Preface</ttl><xreftext>Chapter 1, <i>Preface</i></xreftext><div element="section" href="#tarantool-overview" number="" targetptr="tarantool-overview"><ttl>Tarantool: an overview</ttl><xreftext>the section called “Tarantool: an overviewâ€</xreftext></div><div element="section" href="#manual-conventions" number="" targetptr="manual-conventions"><ttl>Conventions</ttl><xreftext>the section called “Conventionsâ€</xreftext></div><div element="section" href="#reporting-bugs" number="" targetptr="reporting-bugs"><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugsâ€</xreftext></div></div><div element="chapter" href="#getting-started" number="2" targetptr="getting-started"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext><div element="section" href="#getting-started-binary" number="" targetptr="getting-started-binary"><ttl>Downloading and installing a binary package</ttl><xreftext>the section called “Downloading and installing a binary packageâ€</xreftext></div><div element="section" href="#getting-started-source" number="" targetptr="getting-started-source"><ttl>Downloading and building a source package</ttl><xreftext>the section called “Downloading and building a source packageâ€</xreftext></div><div element="section" href="#getting-started-start-stop" number="" targetptr="getting-started-start-stop"><ttl>Starting Tarantool and making your first database</ttl><xreftext>the section called “Starting Tarantool and making your first databaseâ€</xreftext></div></div><div element="chapter" href="#data-and-persistence" number="3" targetptr="data-and-persistence"><ttl>Data model and data persistence</ttl><xreftext>Chapter 3, <i>Data model and data persistence</i></xreftext><div element="section" href="#dynamic-data-model" number="" targetptr="dynamic-data-model"><ttl>Dynamic data model</ttl><xreftext>the section called “Dynamic data modelâ€</xreftext></div><div element="section" href="#data-persistence" number="" targetptr="data-persistence"><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="#data-manipulation" number="" targetptr="data-manipulation"><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulationâ€</xreftext></div><div element="section" href="#administrative-console" number="" targetptr="administrative-console"><ttl>Administrative console</ttl><xreftext>the section called “Administrative consoleâ€</xreftext><obj element="term" href="#box.snapshot" number="" targetptr="box.snapshot"><ttl>???TITLE???</ttl><xreftext>box.snapshot()</xreftext></obj><obj element="term" href="#box.cfg.reload" number="" targetptr="box.cfg.reload"><ttl>???TITLE???</ttl><xreftext>box.cfg.reload()</xreftext></obj><obj element="term" href="#box.cfg.show" number="" targetptr="box.cfg.show"><ttl>???TITLE???</ttl><xreftext>box.cfg()</xreftext></obj><obj element="term" href="#box.info" number="" targetptr="box.info"><ttl>???TITLE???</ttl><xreftext>box.info()</xreftext></obj><obj element="term" href="#box.stat.show" number="" targetptr="box.stat.show"><ttl>???TITLE???</ttl><xreftext>box.stat()</xreftext></obj><obj element="term" href="#box.slab.info" number="" targetptr="box.slab.info"><ttl>???TITLE???</ttl><xreftext>box.slab.info()</xreftext></obj><obj element="term" href="#box.coredump" number="" targetptr="box.coredump"><ttl>???TITLE???</ttl><xreftext>box.coredump()</xreftext></obj><obj element="term" href="#box.fiber.info" number="" targetptr="box.fiber.info"><ttl>???TITLE???</ttl><xreftext>box.fiber.info()</xreftext></obj><obj element="term" href="#lua-command" number="" targetptr="lua-command"><ttl>???TITLE???</ttl><xreftext> <span class="tntadmin">...</span> - </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="filename" href="#init.lua" number="" targetptr="init.lua"><ttl>???TITLE???</ttl><xreftext>init.lua</xreftext></obj><obj element="term" href="#tonumber64" number="" targetptr="tonumber64"><ttl>???TITLE???</ttl><xreftext>tonumber64</xreftext></obj><div element="section" href="#sp-box" number="" targetptr="sp-box"><ttl>Package <code class="code">box</code></ttl><xreftext>the section called “Package <code class="code">box</code>â€</xreftext><obj element="variablelist" href="#box" number="" targetptr="box"><ttl>???TITLE???</ttl><xreftext>box</xreftext></obj><obj element="emphasis" href="#box.process" number="" targetptr="box.process"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.select" number="" targetptr="box.select"><ttl>???TITLE???</ttl><xreftext>box.select</xreftext></obj><obj element="emphasis" href="#box.insert" number="" targetptr="box.insert"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.select_limit" number="" targetptr="box.select_limit"><ttl>???TITLE???</ttl><xreftext>box.select_limit</xreftext></obj><obj element="emphasis" href="#box.replace" number="" targetptr="box.replace"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.update" number="" targetptr="box.update"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.delete" number="" targetptr="box.delete"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.select_range" number="" targetptr="box.select_range"><ttl>???TITLE???</ttl><xreftext>box.select_range</xreftext></obj><obj element="emphasis" href="#box.select_reverse_range" number="" targetptr="box.select_reverse_range"><ttl>???TITLE???</ttl><xreftext>box.select_reverse_range</xreftext></obj></div><div element="section" href="#sp-box-tuple" number="" targetptr="sp-box-tuple"><ttl>Package <code class="code">box.tuple</code></ttl><xreftext>the section called “Package <code class="code">box.tuple</code>â€</xreftext><obj element="variablelist" href="#box.tuple" number="" targetptr="box.tuple"><ttl>???TITLE???</ttl><xreftext>box.tuple</xreftext></obj></div><div element="section" href="#sp-box-cjson" number="" targetptr="sp-box-cjson"><ttl>Package <code class="code">box.cjson</code></ttl><xreftext>the section called “Package <code class="code">box.cjson</code>â€</xreftext><obj element="variablelist" href="#box.cjson" number="" targetptr="box.cjson"><ttl>???TITLE???</ttl><xreftext>box.cjson</xreftext></obj></div><div element="section" href="#sp-box-space" number="" targetptr="sp-box-space"><ttl>Package <code class="code">box.space</code></ttl><xreftext>the section called “Package <code class="code">box.space</code>â€</xreftext><obj element="variablelist" href="#box.space" number="" targetptr="box.space"><ttl>???TITLE???</ttl><xreftext>box.space</xreftext></obj><obj element="emphasis" href="#box.space.select_range" number="" targetptr="box.space.select_range"><ttl>???TITLE???</ttl><xreftext>box.space[i].select_range()</xreftext></obj><obj element="emphasis" href="#box.space.select_reverse_range" number="" targetptr="box.space.select_reverse_range"><ttl>???TITLE???</ttl><xreftext>box.space.select_reverse_range</xreftext></obj></div><div element="section" href="#sp-box-index" number="" targetptr="sp-box-index"><ttl>Package <code class="code">box.index</code></ttl><xreftext>the section called “Package <code class="code">box.index</code>â€</xreftext><obj element="variablelist" href="#box.index" number="" targetptr="box.index"><ttl>???TITLE???</ttl><xreftext>box.index</xreftext></obj><obj element="emphasis" href="#box.index.iterator" number="" targetptr="box.index.iterator"><ttl>???TITLE???</ttl><xreftext>box.index.iterator(type, ...)</xreftext></obj><obj element="para" href="#iterator-consistency" number="" targetptr="iterator-consistency"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="para" href="#iterator-types" number="" targetptr="iterator-types"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="table" href="#idp874176" number="4.1"><ttl>Common iterator types</ttl><xreftext>Table 4.1, “Common iterator typesâ€</xreftext></obj><obj element="table" href="#idp895088" number="4.2"><ttl>TREE iterator types</ttl><xreftext>Table 4.2, “TREE iterator typesâ€</xreftext></obj><obj element="table" href="#idp312816" number="4.3"><ttl>BITSET iterator types</ttl><xreftext>Table 4.3, “BITSET iterator typesâ€</xreftext></obj></div><div element="section" href="#sp-box-fiber" number="" targetptr="sp-box-fiber"><ttl>Package <code class="code">box.fiber</code></ttl><xreftext>the section called “Package <code class="code">box.fiber</code>â€</xreftext><obj element="variablelist" href="#box.fiber" number="" targetptr="box.fiber"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj><obj element="emphasis" href="#box.fiber.id" number="" targetptr="box.fiber.id"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.self" number="" targetptr="box.fiber.self"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.find" number="" targetptr="box.fiber.find"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.create" number="" targetptr="box.fiber.create"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.resume" number="" targetptr="box.fiber.resume"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.yield" number="" targetptr="box.fiber.yield"><ttl>???TITLE???</ttl><xreftext>box.fiber.yield(...)</xreftext></obj><obj element="emphasis" href="#box.fiber.detach" number="" targetptr="box.fiber.detach"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.wrap" number="" targetptr="box.fiber.wrap"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.sleep" number="" targetptr="box.fiber.sleep"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.status" number="" targetptr="box.fiber.status"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.cancel" number="" targetptr="box.fiber.cancel"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.testcancel" number="" targetptr="box.fiber.testcancel"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div><div element="section" href="#sp-box-session" number="" targetptr="sp-box-session"><ttl>Package <code class="code">box.session</code></ttl><xreftext>the section called “Package <code class="code">box.session</code>â€</xreftext></div><div element="section" href="#sp-box-ipc" number="" targetptr="sp-box-ipc"><ttl>Package <code class="code">box.ipc</code> — inter procedure communication</ttl><xreftext>the section called “Package <code class="code">box.ipc</code> — inter procedure communicationâ€</xreftext><obj element="variablelist" href="#box.ipc" number="" targetptr="box.ipc"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj></div><div element="section" href="#sp-box-socket" number="" targetptr="sp-box-socket"><ttl>Package <code class="code">box.socket</code> — TCP and UDP sockets</ttl><xreftext>the section called “Package <code class="code">box.socket</code> — TCP and UDP socketsâ€</xreftext><obj element="variablelist" href="#box.socket" number="" targetptr="box.socket"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj><obj element="table" href="#idp832064" number="4.4"><ttl><code class="code">readline()</code> returns</ttl><xreftext>Table 4.4, “<code class="code">readline()</code> returnsâ€</xreftext></obj></div><div element="section" href="#sp-box-net-box" number="" targetptr="sp-box-net-box"><ttl>Package <code class="code">box.net.box</code> — working with networked Tarantool peers</ttl><xreftext>the section called “Package <code class="code">box.net.box</code> — working with networked Tarantool peersâ€</xreftext><obj element="variablelist" href="#box.net.box" number="" targetptr="box.net.box"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj><obj element="emphasis" href="#box.net.box.new" number="" targetptr="box.net.box.new"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.ping" number="" targetptr="box.net.box.ping"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.close" number="" targetptr="box.net.box.close"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.select" number="" targetptr="box.net.box.select"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.select_limit" number="" targetptr="box.net.box.select_limit"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.select_range" number="" targetptr="box.net.box.select_range"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.insert" number="" targetptr="box.net.box.insert"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.replace" number="" targetptr="box.net.box.replace"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.update" number="" targetptr="box.net.box.update"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.delete" number="" targetptr="box.net.box.delete"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.call" number="" targetptr="box.net.box.call"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.timeout" number="" targetptr="box.net.box.timeout"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div><div element="section" href="#sp-box-cfg" number="" targetptr="sp-box-cfg"><ttl>Packages <code class="code">box.cfg</code>, + </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="filename" href="#init.lua" number="" targetptr="init.lua"><ttl>???TITLE???</ttl><xreftext>init.lua</xreftext></obj><obj element="term" href="#tonumber64" number="" targetptr="tonumber64"><ttl>???TITLE???</ttl><xreftext>tonumber64</xreftext></obj><div element="section" href="#sp-box" number="" targetptr="sp-box"><ttl>Package <code class="code">box</code></ttl><xreftext>the section called “Package <code class="code">box</code>â€</xreftext><obj element="variablelist" href="#box" number="" targetptr="box"><ttl>???TITLE???</ttl><xreftext>box</xreftext></obj><obj element="emphasis" href="#box.process" number="" targetptr="box.process"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.select" number="" targetptr="box.select"><ttl>???TITLE???</ttl><xreftext>box.select</xreftext></obj><obj element="emphasis" href="#box.insert" number="" targetptr="box.insert"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.select_limit" number="" targetptr="box.select_limit"><ttl>???TITLE???</ttl><xreftext>box.select_limit</xreftext></obj><obj element="emphasis" href="#box.replace" number="" targetptr="box.replace"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.update" number="" targetptr="box.update"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.delete" number="" targetptr="box.delete"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.select_range" number="" targetptr="box.select_range"><ttl>???TITLE???</ttl><xreftext>box.select_range</xreftext></obj><obj element="emphasis" href="#box.select_reverse_range" number="" targetptr="box.select_reverse_range"><ttl>???TITLE???</ttl><xreftext>box.select_reverse_range</xreftext></obj></div><div element="section" href="#sp-box-tuple" number="" targetptr="sp-box-tuple"><ttl>Package <code class="code">box.tuple</code></ttl><xreftext>the section called “Package <code class="code">box.tuple</code>â€</xreftext><obj element="variablelist" href="#box.tuple" number="" targetptr="box.tuple"><ttl>???TITLE???</ttl><xreftext>box.tuple</xreftext></obj></div><div element="section" href="#sp-box-cjson" number="" targetptr="sp-box-cjson"><ttl>Package <code class="code">box.cjson</code></ttl><xreftext>the section called “Package <code class="code">box.cjson</code>â€</xreftext><obj element="variablelist" href="#box.cjson" number="" targetptr="box.cjson"><ttl>???TITLE???</ttl><xreftext>box.cjson</xreftext></obj></div><div element="section" href="#sp-box-space" number="" targetptr="sp-box-space"><ttl>Package <code class="code">box.space</code></ttl><xreftext>the section called “Package <code class="code">box.space</code>â€</xreftext><obj element="variablelist" href="#box.space" number="" targetptr="box.space"><ttl>???TITLE???</ttl><xreftext>box.space</xreftext></obj><obj element="emphasis" href="#box.space.select_range" number="" targetptr="box.space.select_range"><ttl>???TITLE???</ttl><xreftext>box.space[i].select_range()</xreftext></obj><obj element="emphasis" href="#box.space.select_reverse_range" number="" targetptr="box.space.select_reverse_range"><ttl>???TITLE???</ttl><xreftext>box.space.select_reverse_range</xreftext></obj></div><div element="section" href="#sp-box-index" number="" targetptr="sp-box-index"><ttl>Package <code class="code">box.index</code></ttl><xreftext>the section called “Package <code class="code">box.index</code>â€</xreftext><obj element="variablelist" href="#box.index" number="" targetptr="box.index"><ttl>???TITLE???</ttl><xreftext>box.index</xreftext></obj><obj element="emphasis" href="#box.index.iterator" number="" targetptr="box.index.iterator"><ttl>???TITLE???</ttl><xreftext>box.index.iterator(type, ...)</xreftext></obj><obj element="para" href="#iterator-consistency" number="" targetptr="iterator-consistency"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="para" href="#iterator-types" number="" targetptr="iterator-types"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="table" href="#idp25645584" number="4.1"><ttl>Common iterator types</ttl><xreftext>Table 4.1, “Common iterator typesâ€</xreftext></obj><obj element="table" href="#idp25341120" number="4.2"><ttl>TREE iterator types</ttl><xreftext>Table 4.2, “TREE iterator typesâ€</xreftext></obj><obj element="table" href="#idp25358624" number="4.3"><ttl>BITSET iterator types</ttl><xreftext>Table 4.3, “BITSET iterator typesâ€</xreftext></obj></div><div element="section" href="#sp-box-fiber" number="" targetptr="sp-box-fiber"><ttl>Package <code class="code">box.fiber</code></ttl><xreftext>the section called “Package <code class="code">box.fiber</code>â€</xreftext><obj element="variablelist" href="#box.fiber" number="" targetptr="box.fiber"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj><obj element="emphasis" href="#box.fiber.id" number="" targetptr="box.fiber.id"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.self" number="" targetptr="box.fiber.self"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.find" number="" targetptr="box.fiber.find"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.create" number="" targetptr="box.fiber.create"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.resume" number="" targetptr="box.fiber.resume"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.yield" number="" targetptr="box.fiber.yield"><ttl>???TITLE???</ttl><xreftext>box.fiber.yield(...)</xreftext></obj><obj element="emphasis" href="#box.fiber.detach" number="" targetptr="box.fiber.detach"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.wrap" number="" targetptr="box.fiber.wrap"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.sleep" number="" targetptr="box.fiber.sleep"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.status" number="" targetptr="box.fiber.status"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.cancel" number="" targetptr="box.fiber.cancel"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.fiber.testcancel" number="" targetptr="box.fiber.testcancel"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div><div element="section" href="#sp-box-session" number="" targetptr="sp-box-session"><ttl>Package <code class="code">box.session</code></ttl><xreftext>the section called “Package <code class="code">box.session</code>â€</xreftext></div><div element="section" href="#sp-box-ipc" number="" targetptr="sp-box-ipc"><ttl>Package <code class="code">box.ipc</code> — inter procedure communication</ttl><xreftext>the section called “Package <code class="code">box.ipc</code> — inter procedure communicationâ€</xreftext><obj element="variablelist" href="#box.ipc" number="" targetptr="box.ipc"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj></div><div element="section" href="#sp-box-socket" number="" targetptr="sp-box-socket"><ttl>Package <code class="code">box.socket</code> — TCP and UDP sockets</ttl><xreftext>the section called “Package <code class="code">box.socket</code> — TCP and UDP socketsâ€</xreftext><obj element="variablelist" href="#box.socket" number="" targetptr="box.socket"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj><obj element="table" href="#idp25542512" number="4.4"><ttl><code class="code">readline()</code> returns</ttl><xreftext>Table 4.4, “<code class="code">readline()</code> returnsâ€</xreftext></obj></div><div element="section" href="#sp-box-net-box" number="" targetptr="sp-box-net-box"><ttl>Package <code class="code">box.net.box</code> — working with networked Tarantool peers</ttl><xreftext>the section called “Package <code class="code">box.net.box</code> — working with networked Tarantool peersâ€</xreftext><obj element="variablelist" href="#box.net.box" number="" targetptr="box.net.box"><ttl>???TITLE???</ttl><xreftext>???TITLE???</xreftext></obj><obj element="emphasis" href="#box.net.box.new" number="" targetptr="box.net.box.new"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.ping" number="" targetptr="box.net.box.ping"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.close" number="" targetptr="box.net.box.close"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.select" number="" targetptr="box.net.box.select"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.select_limit" number="" targetptr="box.net.box.select_limit"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.select_range" number="" targetptr="box.net.box.select_range"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.insert" number="" targetptr="box.net.box.insert"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.replace" number="" targetptr="box.net.box.replace"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.update" number="" targetptr="box.net.box.update"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.delete" number="" targetptr="box.net.box.delete"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.call" number="" targetptr="box.net.box.call"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="emphasis" href="#box.net.box.timeout" number="" targetptr="box.net.box.timeout"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div><div element="section" href="#sp-box-cfg" number="" targetptr="sp-box-cfg"><ttl>Packages <code class="code">box.cfg</code>, <code class="code">box.info</code>, <code class="code">box.slab</code> and <code class="code">box.stat</code>: server introspection</ttl><xreftext>the section called “Packages <code class="code">box.cfg</code>, <code class="code">box.info</code>, <code class="code">box.slab</code> and - <code class="code">box.stat</code>: server introspectionâ€</xreftext><obj element="code" href="#box.cfg" number="" targetptr="box.cfg"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="code" href="#box.stat" number="" targetptr="box.stat"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div><div element="section" href="#sp-limitations" number="" targetptr="sp-limitations"><ttl>Limitation of stored procedures</ttl><xreftext>the section called “Limitation of stored proceduresâ€</xreftext></div></div><div element="section" href="#triggers" number="" targetptr="triggers"><ttl>Defining triggers in Lua</ttl><xreftext>the section called “Defining triggers in Luaâ€</xreftext><div element="section" href="#sp-box-session-triggers" number="" targetptr="sp-box-session-triggers"><ttl>Triggers on connect and disconnect</ttl><xreftext>session triggers</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="#replication-architecture" number="" targetptr="replication-architecture"><ttl>Replication architecture</ttl><xreftext>the section called “Replication architectureâ€</xreftext></div><div element="section" href="#setting-up-the-master" number="" targetptr="setting-up-the-master"><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the masterâ€</xreftext></div><div element="section" href="#settin-up-a-replica" number="" targetptr="settin-up-a-replica"><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replicaâ€</xreftext></div><div element="section" href="#recovering-from-a-degraded-state" number="" targetptr="recovering-from-a-degraded-state"><ttl>Recovering from a degraded state</ttl><xreftext>the section called “Recovering from a degraded stateâ€</xreftext></div></div><div element="chapter" href="#server-administration" number="6" targetptr="server-administration"><ttl>Server administration</ttl><xreftext>Chapter 6, <i>Server administration</i></xreftext><div element="section" href="#signal-handling" number="" targetptr="signal-handling"><ttl>Server signal handling</ttl><xreftext>the section called “Server signal handlingâ€</xreftext></div><div element="section" href="#os-install-notes" number="" targetptr="os-install-notes"><ttl>System-specific administration notes</ttl><xreftext>the section called “System-specific administration notesâ€</xreftext><div element="section" href="#Debian" number="" targetptr="Debian"><ttl>Debian GNU/Linux and Ubuntu</ttl><xreftext>the section called “Debian GNU/Linux and Ubuntuâ€</xreftext></div><div element="section" href="#rpm-based-distros" number="" targetptr="rpm-based-distros"><ttl>Fedora, RHEL, CentOS</ttl><xreftext>the section called “Fedora, RHEL, CentOSâ€</xreftext></div><div element="section" href="#FreeBSD" number="" targetptr="FreeBSD"><ttl>FreeBSD</ttl><xreftext>the section called “FreeBSDâ€</xreftext></div><div element="section" href="#mac-os-x" number="" targetptr="mac-os-x"><ttl>Mac OS X</ttl><xreftext>the section called “Mac OS Xâ€</xreftext></div></div></div><div element="chapter" href="#configuration-reference" number="7" targetptr="configuration-reference"><ttl>Configuration reference</ttl><xreftext>Chapter 7, <i>Configuration reference</i></xreftext><div element="section" href="#command-line-options" number="" targetptr="command-line-options"><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></div><div element="section" href="#option-file" number="" targetptr="option-file"><ttl>The option file</ttl><xreftext>option file</xreftext><obj element="table" href="#idp1404672" number="7.1"><ttl>Basic parameters</ttl><xreftext>Table 7.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="#script_dir" number="" targetptr="script_dir"><ttl>???TITLE???</ttl><xreftext>script_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="#bind_ipaddr" number="" targetptr="bind_ipaddr"><ttl>???TITLE???</ttl><xreftext>bind_ipaddr</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="#idp1462800" number="7.2"><ttl>Configuring the storage</ttl><xreftext>Table 7.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="#idp1498704" number="7.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 7.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="#idp1534096" number="7.4"><ttl>Replication</ttl><xreftext>Table 7.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="#idp1553136" number="7.5"><ttl>Networking</ttl><xreftext>Table 7.5, “Networkingâ€</xreftext></obj><obj element="table" href="#idp1572464" number="7.6"><ttl>Logging</ttl><xreftext>Table 7.6, “Loggingâ€</xreftext></obj></div></div><div element="chapter" href="#connectors" number="8" targetptr="connectors"><ttl>Connectors</ttl><xreftext>Chapter 8, <i>Connectors</i></xreftext><div element="section" href="#connector-c" number="" targetptr="connector-c"><ttl>C</ttl><xreftext>the section called “Câ€</xreftext></div><div element="section" href="#connector-node.js" number="" targetptr="connector-node.js"><ttl>node.js</ttl><xreftext>the section called “node.jsâ€</xreftext></div><div element="section" href="#connector-perl" number="" targetptr="connector-perl"><ttl>Perl</ttl><xreftext>the section called “Perlâ€</xreftext></div><div element="section" href="#connector-php" number="" targetptr="connector-php"><ttl>PHP</ttl><xreftext>the section called “PHPâ€</xreftext></div><div element="section" href="#connector-python" number="" targetptr="connector-python"><ttl>Python</ttl><xreftext>the section called “Pythonâ€</xreftext></div><div element="section" href="#connector-ruby" number="" targetptr="connector-ruby"><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_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_PART_COUNT" number="" targetptr="ER_KEY_PART_COUNT"><ttl>???TITLE???</ttl><xreftext>ER_KEY_PART_COUNT</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><obj element="term" href="#ER_FIBER_STACK" number="" targetptr="ER_FIBER_STACK"><ttl>???TITLE???</ttl><xreftext>ER_FIBER_STACK</xreftext></obj><obj element="term" href="#ER_UPDATE_FIELD" number="" targetptr="ER_UPDATE_FIELD"><ttl>???TITLE???</ttl><xreftext>ER_UPDATE_FIELD</xreftext></obj></div></div> + <code class="code">box.stat</code>: server introspectionâ€</xreftext><obj element="code" href="#box.cfg" number="" targetptr="box.cfg"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj><obj element="code" href="#box.stat" number="" targetptr="box.stat"><ttl>???TITLE???</ttl><xreftext>???</xreftext></obj></div><div element="section" href="#sp-limitations" number="" targetptr="sp-limitations"><ttl>Limitations of stored procedures</ttl><xreftext>the section called “Limitations of stored proceduresâ€</xreftext></div></div><div element="section" href="#triggers" number="" targetptr="triggers"><ttl>Defining triggers in Lua</ttl><xreftext>the section called “Defining triggers in Luaâ€</xreftext><div element="section" href="#sp-box-session-triggers" number="" targetptr="sp-box-session-triggers"><ttl>Triggers on connect and disconnect</ttl><xreftext>session triggers</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="#replication-architecture" number="" targetptr="replication-architecture"><ttl>Replication architecture</ttl><xreftext>the section called “Replication architectureâ€</xreftext></div><div element="section" href="#setting-up-the-master" number="" targetptr="setting-up-the-master"><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the masterâ€</xreftext></div><div element="section" href="#settin-up-a-replica" number="" targetptr="settin-up-a-replica"><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replicaâ€</xreftext></div><div element="section" href="#recovering-from-a-degraded-state" number="" targetptr="recovering-from-a-degraded-state"><ttl>Recovering from a degraded state</ttl><xreftext>the section called “Recovering from a degraded stateâ€</xreftext></div></div><div element="chapter" href="#server-administration" number="6" targetptr="server-administration"><ttl>Server administration</ttl><xreftext>Chapter 6, <i>Server administration</i></xreftext><div element="section" href="#signal-handling" number="" targetptr="signal-handling"><ttl>Server signal handling</ttl><xreftext>the section called “Server signal handlingâ€</xreftext></div><div element="section" href="#tarantar" number="" targetptr="tarantar"><ttl>Utility <code class="code">tarantar</code></ttl><xreftext>the section called “Utility <code class="code">tarantar</code>â€</xreftext></div><div element="section" href="#os-install-notes" number="" targetptr="os-install-notes"><ttl>System-specific administration notes</ttl><xreftext>the section called “System-specific administration notesâ€</xreftext><div element="section" href="#Debian" number="" targetptr="Debian"><ttl>Debian GNU/Linux and Ubuntu</ttl><xreftext>the section called “Debian GNU/Linux and Ubuntuâ€</xreftext></div><div element="section" href="#rpm-based-distros" number="" targetptr="rpm-based-distros"><ttl>Fedora, RHEL, CentOS</ttl><xreftext>the section called “Fedora, RHEL, CentOSâ€</xreftext></div><div element="section" href="#FreeBSD" number="" targetptr="FreeBSD"><ttl>FreeBSD</ttl><xreftext>the section called “FreeBSDâ€</xreftext></div><div element="section" href="#mac-os-x" number="" targetptr="mac-os-x"><ttl>Mac OS X</ttl><xreftext>the section called “Mac OS Xâ€</xreftext></div></div></div><div element="chapter" href="#configuration-reference" number="7" targetptr="configuration-reference"><ttl>Configuration reference</ttl><xreftext>Chapter 7, <i>Configuration reference</i></xreftext><div element="section" href="#command-line-options" number="" targetptr="command-line-options"><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></div><div element="section" href="#option-file" number="" targetptr="option-file"><ttl>The option file</ttl><xreftext>option file</xreftext><obj element="table" href="#idp26182784" number="7.1"><ttl>Basic parameters</ttl><xreftext>Table 7.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="#script_dir" number="" targetptr="script_dir"><ttl>???TITLE???</ttl><xreftext>script_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="#bind_ipaddr" number="" targetptr="bind_ipaddr"><ttl>???TITLE???</ttl><xreftext>bind_ipaddr</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="#idp26241360" number="7.2"><ttl>Configuring the storage</ttl><xreftext>Table 7.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="#idp26277088" number="7.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 7.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="#idp26312272" number="7.4"><ttl>Replication</ttl><xreftext>Table 7.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="#idp26331776" number="7.5"><ttl>Networking</ttl><xreftext>Table 7.5, “Networkingâ€</xreftext></obj><obj element="table" href="#idp26351072" number="7.6"><ttl>Logging</ttl><xreftext>Table 7.6, “Loggingâ€</xreftext></obj></div></div><div element="chapter" href="#connectors" number="8" targetptr="connectors"><ttl>Connectors</ttl><xreftext>Chapter 8, <i>Connectors</i></xreftext><div element="section" href="#connector-packet-example" number="" targetptr="connector-packet-example"><ttl>Packet example</ttl><xreftext>the section called “Packet exampleâ€</xreftext></div><div element="section" href="#connector-c" number="" targetptr="connector-c"><ttl>C</ttl><xreftext>the section called “Câ€</xreftext></div><div element="section" href="#connector-node.js" number="" targetptr="connector-node.js"><ttl>node.js</ttl><xreftext>the section called “node.jsâ€</xreftext></div><div element="section" href="#connector-perl" number="" targetptr="connector-perl"><ttl>Perl</ttl><xreftext>the section called “Perlâ€</xreftext></div><div element="section" href="#connector-php" number="" targetptr="connector-php"><ttl>PHP</ttl><xreftext>the section called “PHPâ€</xreftext></div><div element="section" href="#connector-python" number="" targetptr="connector-python"><ttl>Python</ttl><xreftext>the section called “Pythonâ€</xreftext></div><div element="section" href="#connector-ruby" number="" targetptr="connector-ruby"><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_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_KEY_PART_COUNT" number="" targetptr="ER_KEY_PART_COUNT"><ttl>???TITLE???</ttl><xreftext>ER_KEY_PART_COUNT</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><obj element="term" href="#ER_FIBER_STACK" number="" targetptr="ER_FIBER_STACK"><ttl>???TITLE???</ttl><xreftext>ER_FIBER_STACK</xreftext></obj><obj element="term" href="#ER_UPDATE_FIELD" number="" targetptr="ER_UPDATE_FIELD"><ttl>???TITLE???</ttl><xreftext>ER_UPDATE_FIELD</xreftext></obj></div><div element="appendix" href="#limitations" number="C" targetptr="limitations"><ttl>Limitations</ttl><xreftext>Appendix C, <i>Limitations</i></xreftext><obj element="term" href="#limitations-index-field-count" number="" targetptr="limitations-index-field-count"><ttl>???TITLE???</ttl><xreftext>limitations-index-field-count</xreftext></obj><obj element="term" href="#limitations-index-count" number="" targetptr="limitations-index-count"><ttl>???TITLE???</ttl><xreftext>limitations-index-count</xreftext></obj><obj element="term" href="#limitations-tuple-field-count" number="" targetptr="limitations-tuple-field-count"><ttl>???TITLE???</ttl><xreftext>limitations-tuple-field-count</xreftext></obj><obj element="term" href="#limitations-space-count" number="" targetptr="limitations-space-count"><ttl>???TITLE???</ttl><xreftext>limitations-space-count</xreftext></obj><obj element="term" href="#limitations-connections-count" number="" targetptr="limitations-connections-count"><ttl>???TITLE???</ttl><xreftext>limitations-connections-count</xreftext></obj><obj element="term" href="#limitations-slab-alloc-arena-size" number="" targetptr="limitations-slab-alloc-arena-size"><ttl>???TITLE???</ttl><xreftext>limitations-slab-alloc-arena-size</xreftext></obj><obj element="term" href="#limitations-update-count" number="" targetptr="limitations-update-count"><ttl>???TITLE???</ttl><xreftext>limitations-updae-count</xreftext></obj></div></div> diff --git a/doc/user/user.xml b/doc/user/user.xml index 98cdcde2dec19d24539a2959d914a4aea311a00c..e1052b869c1af826e4681512283826db3f749b09 100644 --- a/doc/user/user.xml +++ b/doc/user/user.xml @@ -18,6 +18,7 @@ <xi:include href="connectors.xml"/> <xi:include href="proctitle.xml"/> <xi:include href="errcode.xml"/> +<xi:include href="limitations.xml"/> <!-- <xi:include href="faq.xml"/> --> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 638c63ac6776320977e48b90bdcaadbf84d20cf6..3c2435f5c534e6a3ed75883596265e7f292063a5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -178,7 +178,7 @@ function(tarantool_module mod) add_library(lt${mod} STATIC ${recompiled_sources}) add_dependencies(lt${mod} generate_headers generate_admin_cc build_bundled_libs) - target_link_libraries(tarantool_${mod} lt${mod} ${common_libraries}) + target_link_libraries(tarantool_${mod} lt${mod} ${common_libraries} -rdynamic) if (ENABLE_STATIC) set_target_properties(tarantool_${mod} PROPERTIES diff --git a/src/log_io.cc b/src/log_io.cc index 79ef3e82dfc95f180e02bafc8b54096c91e31987..a49647705abd19fb7e19618fa85fb1dbfdd4deab 100644 --- a/src/log_io.cc +++ b/src/log_io.cc @@ -390,7 +390,7 @@ int inprogress_log_rename(struct log_io *l) { char *filename = l->filename; - char *new_filename; + char new_filename[PATH_MAX]; char *suffix = strrchr(filename, '.'); assert(l->is_inprogress); @@ -398,7 +398,6 @@ inprogress_log_rename(struct log_io *l) assert(strcmp(suffix, inprogress_suffix) == 0); /* Create a new filename without '.inprogress' suffix. */ - new_filename = (char *) alloca(suffix - filename + 1); memcpy(new_filename, filename, suffix - filename); new_filename[suffix - filename] = '\0'; diff --git a/src/plugin/mysql/CMakeLists.txt b/src/plugin/mysql/CMakeLists.txt index 0f7c445d33726257e2cfd280273e1d9ba07b8338..e7ea8df5751a432550238b7b2c5f9b40f3602cdd 100644 --- a/src/plugin/mysql/CMakeLists.txt +++ b/src/plugin/mysql/CMakeLists.txt @@ -6,7 +6,7 @@ if (MYSQL_FOUND) include_directories(${MYSQL_INCLUDE_DIRS}) add_library(mysql SHARED mysql.cc) - target_link_libraries(mysql ${MYSQL_LIBRARIES}) + target_link_libraries(mysql ${MYSQL_LIBRARIES} -rdynamic) install(TARGETS mysql LIBRARY DESTINATION ${PLUGIN_DIR}) else() message(STATUS "MySQL client not found, box.net.sql(mysql) disabled") diff --git a/src/plugin/pg/CMakeLists.txt b/src/plugin/pg/CMakeLists.txt index 98c348350656d891a303bc2c4a3fdd9daffe2112..dcaf15475d4c33dd6ad7b3008ed5bc11ee30a45c 100644 --- a/src/plugin/pg/CMakeLists.txt +++ b/src/plugin/pg/CMakeLists.txt @@ -7,7 +7,7 @@ if (PostgreSQL_FOUND) include_directories(${PostgreSQL_INCLUDE_DIRS}) add_library(pg SHARED pg.cc) - target_link_libraries(pg ${PostgreSQL_LIBRARIES}) + target_link_libraries(pg ${PostgreSQL_LIBRARIES} -rdynamic) install(TARGETS pg LIBRARY DESTINATION ${PLUGIN_DIR}) else() diff --git a/src/plugin/pg/pg.cc b/src/plugin/pg/pg.cc index eed46c7d748032bac7a18f6af8c89312498e4477..b8958faf7d632f4feb4d947d30ae7455168dcd17 100644 --- a/src/plugin/pg/pg.cc +++ b/src/plugin/pg/pg.cc @@ -81,7 +81,6 @@ lua_check_pgconn(struct lua_State *L, int index) return conn; } - /** do execute request (is run in the other thread) */ static ssize_t pg_exec(va_list ap) @@ -210,14 +209,19 @@ lua_pg_execute(struct lua_State *L) Oid *paramTypes = NULL; if (count > 0) { - paramValues = (typeof(paramValues)) - alloca( count * sizeof(*paramValues) ); - paramLengths = (typeof(paramLengths)) - alloca( count * sizeof(*paramLengths) ); - paramFormats = (typeof(paramFormats)) - alloca( count * sizeof(*paramFormats) ); - paramTypes = (typeof(paramTypes)) - alloca( count * sizeof(*paramTypes) ); + /* Allocate memory for params using lua_newuserdata */ + char *buf = (char *) lua_newuserdata(L, count * + (sizeof(*paramValues) + sizeof(*paramLengths) + + sizeof(*paramFormats) + sizeof(*paramTypes))); + + paramValues = (const char **) buf; + buf += count * sizeof(*paramValues); + paramLengths = (int *) buf; + buf += count * sizeof(*paramLengths); + paramFormats = (int *) buf; + buf += count * sizeof(*paramFormats); + paramTypes = (Oid *) buf; + buf += count * sizeof(*paramTypes); for(int i = 0, idx = 3; i < count; i++, idx++) { if (lua_isnil(L, idx)) { @@ -288,6 +292,7 @@ lua_pg_execute(struct lua_State *L) auto scope_guard = make_scoped_guard([&]{ PQclear(res); }); + lua_settop(L, 0); return lua_push_pgres(L, res); }