From bfd79ec5211004e9a43ebe82751b8898d788e3f2 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja.osipov@gmail.com>
Date: Tue, 15 Nov 2011 01:10:50 +0400
Subject: [PATCH] Lua: continue extending the user guide.

---
 README                       |  17 +++-
 doc/user/connectors.xml      |   2 +-
 doc/user/errcode.xml         |   6 ++
 doc/user/replication.xml     |   8 +-
 doc/user/stored-programs.xml | 152 ++++++++++++++++++++++++++++-------
 doc/user/target.db           |   2 +-
 doc/user/tnt.css             |   6 ++
 mod/box/box.lua              |  53 ++++++------
 mod/box/box_lua.m            |  13 ++-
 test/box/lua.result          |   4 -
 10 files changed, 192 insertions(+), 71 deletions(-)

diff --git a/README b/README
index bb01f41d7c..95a384cdab 100644
--- a/README
+++ b/README
@@ -18,8 +18,8 @@ Caveats:
 COMPILATION AND INSTALL
 
 Tarantool is written in C and Objective C.
-To build, you will need GCC Objective C frontend or
-Apple CLang compiler.
+To build, you will need GCC Objective C frontend
+(gcc-objc package on most systems) or Apple CLang compiler.
 
 CMake is used for configuration management.
 3 standard CMake build types are supported:
@@ -28,6 +28,9 @@ CMake is used for configuration management.
  also provides debugging capabilities
  * Release -- use only if the highest performance is required
 
+The only external library dependency is readline: libreadline-dev
+is required to build the command line client.
+
 Please follow these steps to compile Tarantool:
 
 tarantool $ cmake .
@@ -37,8 +40,14 @@ To use a different release type, say, RelWithDebugInfo, use:
 
 tarantool $ cmake . -DCMAKE_BUILD_TYPE=RelWithDebugInfo
 
-'make' will create tarantool_box executable in directory
-mod/box.
+Additional build options can be set similarly:
+
+tarantool $ cmake . -DCMAKE_BUILD_TYPE=RelWithDebugInfo -DENABLE_CLIENT=true
+
+-- builds the command line client.
+
+'make' creates tarantool_box executable in directory
+mod/box and tarantool executable in client/tarantool.
 
 There is no 'make install' goal, but no installation
 is required either.
diff --git a/doc/user/connectors.xml b/doc/user/connectors.xml
index 65153e39ed..b97c6eaec6 100644
--- a/doc/user/connectors.xml
+++ b/doc/user/connectors.xml
@@ -18,7 +18,7 @@
     <title>C</title>
     <para>
        Please see <link
-       xlink:href="https://github.com/mailru/tarantool/blob/master/connector/c/tnt.h"><filename>connector/c/tnt.h</filename></link> in the source tree.
+       xlink:href="https://github.com/mailru/tarantool/blob/master/connector/c"><filename>connector/c</filename></link> in the source tree.
     </para>
   </section>
 
diff --git a/doc/user/errcode.xml b/doc/user/errcode.xml
index 2246021fb3..c882838da5 100644
--- a/doc/user/errcode.xml
+++ b/doc/user/errcode.xml
@@ -68,6 +68,12 @@ of existing codes.</para>
     </para></listitem>
   </varlistentry>
 
+  <varlistentry>
+    <term xml:id="ER_PROC_LUA" xreflabel="ER_PROC_LUA">ER_PROC_LUA</term>
+    <listitem><para>An error inside Lua procedure.
+    </para></listitem>
+  </varlistentry>
+
 </variablelist>
 </appendix>
 
diff --git a/doc/user/replication.xml b/doc/user/replication.xml
index dff80ab994..bd6db13944 100644
--- a/doc/user/replication.xml
+++ b/doc/user/replication.xml
@@ -20,10 +20,10 @@
     fetching and applying its write ahead log (WAL).
     Each record in the WAL represents a single Tarantool/Box
     command, such as INSERT, UPDATE, DELETE and is assigned
-    a monotonically growing log sequence number (LSN) and a
-    timestamp. As long as all data change commands
-    are fully deterministic and operate on a single record,
-    Tarantool replication can be classified as row-based
+    a monotonically growing log sequence number (LSN).
+    In essence, Tarantool replication is row-based:
+    all data change commands are fully deterministic and operate
+    on a single record.
   </para>
   <para>
     A stored program invocation, unless requested explicitly,
diff --git a/doc/user/stored-programs.xml b/doc/user/stored-programs.xml
index 891b90dd59..70efccc7af 100644
--- a/doc/user/stored-programs.xml
+++ b/doc/user/stored-programs.xml
@@ -1,3 +1,7 @@
+<!DOCTYPE section [
+<!ENTITY % tnt SYSTEM "../tnt.ent">
+%tnt;
+]>
 <section xmlns="http://docbook.org/ns/docbook" version="5.0"
       xmlns:xi="http://www.w3.org/2001/XInclude"
       xmlns:xlink="http://www.w3.org/1999/xlink"
@@ -6,8 +10,8 @@
 <blockquote>
     <para>
         Lua is a light-weight, multi-paradigm embeddable language.
-        Stored procedures in Lua can be used to implement complex
-        data manipulation patterns and data structures. A
+        Stored procedures in Lua can be used to implement
+        data manipulation patterns or data structures. A
         server-side procedure written in Lua can select and modify
         data, access configuration and perform administrative
         tasks. It is possible to dynamically define, invoke,
@@ -30,15 +34,16 @@ 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 the command
-    line client uses to represent the CALL command of the binary
+    Lua chunk. "CALL" is the SQL standard statement used
+    to represent the CALL command of the binary
     protocol.
-    In the example above, we first define a Lua procedure
+    In the example above, a Lua procedure is first defined
     using the text protocol of the administrative port,
-    and then invoke it using the Tarantool client-side SQL
-    parser, and then the binary protocol on the <olink targetptr="primary_port" />.
+    and then invoked using the Tarantool client-side SQL
+    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>
+    administrative console, the newly created <code
+    language="Pascal">function f1()</code>
     can be called there too:
 <programlisting>
 <computeroutput>
@@ -60,9 +65,9 @@ localhost> lua "hello".." world"
   <para>
     There is a single global Lua interpreter state, which is
     shared across all connections. Each connection, however, is
-    running in its own Lua <quote>thread</quote> -- a mechanism, akin to
-    Tarantool <quote>fibers</quote>.
-    Anything, prefixed with "lua " on the administrative console
+    running in its own Lua <emphasis>thread</emphasis> -- a mechanism, akin to
+    Tarantool <emphasis>fibers</emphasis>.
+    Anything prefixed with <code>lua </code> on the administrative console
     is sent directly to the interpreter. In the binary protocol,
     however, it is only possible to invoke Lua functions, but not
     define or modify them.
@@ -71,39 +76,132 @@ localhost> lua "hello".." world"
     of the command, is passed into the stored procedure, each
     field of the tuple converted to a string parameter of the
     procedure. As long as currently Tarantool tuples are
-    type-agnostic, Lua strings are chosen as the transport means
+    type-agnostic, Lua strings are chosen as the transport media 
     between the server and the interpreter.
   </para>
   <para>
     Every value, returned from a stored function by means of
-    <quote>return</quote> clause, is converted to Tarantool/Box tuple
+    <code>return</code> clause, is converted to Tarantool/Box tuple
     and sent back to the client in binary form.
   </para>
+  <para>
+    When a function in Lua terminates with an error, it is 
+    returned to the client as <olink targetptr="ER_PROC_LUA" />
+    return code, with the original error message preserved.
+    Similarly, an error occurred inside Tarantool (observed on the
+    client as an error code), when happens during execution of a
+    Lua procedure, produces a genuine Lua exception.
+  </para>
   <para>
     It's possible not only to invoke trivial Lua code, but call
-    into Tarantool/Box storage functionality, using <quote>box</quote>
-    Lua library.
-    The main means of communication between Lua and Tarantool
-    is <quote>box.process()</quote> function, which allows
-    to send any kind of request to the server in the binary form.
-    Function <quote>box.process()</quote> is a server-side outlet
-    for Tarantool binary protocol. Any tuple returned by the
-    server is converted to a Lua object of type <quote>box.tuple</quote>
-    and appended to the return list of <quote>box.process()</quote>.
+    into Tarantool/Box storage functionality, using
+    <code>box</code>
+    Lua library. The actual contents of the library can be
+    inspected at runtime:
+<programlisting>
+<computeroutput>
+localhost> lua for k, v in pairs(box) do print(k, ": ", type(v)) end
+---
+fiber: table
+space: table
+cfg: table
+on_reload_configuration: function
+update: function
+process: function
+delete: function
+insert: function
+select: function
+index: table
+unpack: function
+replace: function
+select_range: function
+pack: function
+...
+</computeroutput>
+</programlisting>
+    As is shown in the listing, <code>box</code> package ships:
+    <itemizedlist>
+        <listitem><para>
+            high-level functions, such as
+            <code>process(), update(), select(), select_range(), insert(),
+                replace(), delete()</code>, to manipulate
+                tuples and access spaces from Lua.
+        </para></listitem>
+        <listitem><para>
+            libraries, such as <code>cfg, space, fiber, index, tuple</code>,
+            to access server configuration, create, resume and
+            interrupt fibers, inspect content of spaces, indexes
+            and tuples.
+        </para></listitem>
+    </itemizedlist>
+  </para>
+
+<para>
+<variablelist>
+    <title>Package <code>box</code> function index</title>
+
+    <varlistentry>
+        <term>
+            <emphasis role="lua">box.process(op, request)</emphasis>
+        </term>
+        <listitem>
+            <para>
+                The main extension provided to Lua by
+                Tarantool/Box -- ability to call
+                INSERT/UPDATE/SELECT/DELETE from within a Lua
+                procedure.
+            </para>
+            <para>
+                This is a low-level API, and it expects
+                all arguments to be packed in accordance
+                with the binary protocol format (iproto
+                header excluded).
+                <bridgehead renderas="sect4">Parameters</bridgehead>
+                <simplelist>
+                    <member><code>op</code> &mdash; number, Tarantool/Box command code, see
+                    <link xlink:href="https://github.com/mailru/tarantool/blob/master/doc/box-protocol.txt">
+                    <filename>doc/box-protocol.txt</filename></link>,
+                    </member>
+                    <member><code>request</code> &mdash; request packed in binary
+                    format</member>
+                </simplelist>
+                <bridgehead renderas="sect4">Returns</bridgehead>
+                This function returns zero or more tuples.
+                <bridgehead renderas="sect4">Errors</bridgehead>
+                Any server error produced by the executed command.
+            </para>
+        </listitem>
+    </varlistentry>
+</variablelist>
+</para>
+
+  <para>
+    Some of the functionality is implemented The Lua source code of these wrappers, as well as a more
+    extensive documentation can be found in
+    <filename>mod/box/box.lua</filename> file in the source tree.
+  </para>
+  <para>
+    The main communication portal between Lua and Tarantool
+    is <code>box.process()</code> function, which directly
+    invokes the Tarantool command handler and allows
+    to send any kind of request to the server.
+    Any tuple returned by the
+    server is converted to a Lua object of type
+    <code>box.tuple</code>
+    and is appended to the return list of
+    <code>box.process()</code>.
   </para>
   <para>
     A few wrappers are defined to simplify the most common
     tasks:
     <itemizedlist>
-        <listitem><para><quote>box.select(space, key, ...)</quote>
+        <listitem><para><code>box.select(space, key, ...)</code>
         to retrieve tuples. </para></listitem>
-        <listitem><para><quote>box.replace(space, ...)</quote>
+        <listitem><para><code>box.replace(space, ...)</code>
         to insert and replace tuples. The tuple is constructed
         from all the remaining arguments passed into the function.</para></listitem>
-        <listitem><para><quote>box.update(space, key, tuple)</quote> and <quote>box.delete(space, key)</quote>for updates and deletes respectively.</para></listitem>
+        <listitem><para><code>box.update(space, key, tuple)</code> and <code>box.delete(space, key)</code>for updates and deletes respectively.</para></listitem>
     </itemizedlist>
-    The Lua source code of these wrappers, as well as a more
-    extensive documentation can be found in <filename>mod/box/box.lua</filename> file in the source tree.
   </para>
 </section>
 <!--
diff --git a/doc/user/target.db b/doc/user/target.db
index ee0f957b3d..b7be49cea9 100644
--- a/doc/user/target.db
+++ b/doc/user/target.db
@@ -1 +1 @@
-<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool/Box User Guide, version 1.4.3-9-g472a615</ttl><xreftext>Tarantool/Box User Guide, version 1.4.3-9-g472a615</xreftext><div element="chapter" href="#idm34816" number="1"><ttl>Preface</ttl><xreftext>Chapter 1, <i>Preface</i></xreftext><div element="section" href="#preface" number="" targetptr="preface"><ttl>Tarantool/Box: an overview</ttl><xreftext>the section called “Tarantool/Box: an overview”</xreftext></div><div element="section" href="#idp17776" number=""><ttl>Conventions</ttl><xreftext>the section called “Conventions”</xreftext></div><div element="section" href="#idp26672" number=""><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugs”</xreftext></div></div><div element="chapter" href="#idp220784" number="2"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext></div><div element="chapter" href="#idp221040" number="3"><ttl>Dynamic data model</ttl><xreftext>Chapter 3, <i>Dynamic data model</i></xreftext></div><div element="chapter" href="#language-reference" number="4" targetptr="language-reference"><ttl>Language reference</ttl><xreftext>Chapter 4, <i>Language reference</i></xreftext><div element="section" href="#idm28384" number=""><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulation”</xreftext><div element="section" href="#idp360848" number=""><ttl>Memcached protocol</ttl><xreftext>the section called “Memcached protocol”</xreftext></div></div><div element="section" href="#idp364528" number=""><ttl>Administrative console</ttl><xreftext>the section called “Administrative console”</xreftext><obj element="term" href="#save-snapshot" number="" targetptr="save-snapshot"><ttl>???TITLE???</ttl><xreftext>SAVE SNAPSHOT</xreftext></obj><obj element="term" href="#reload-configuration" number="" targetptr="reload-configuration"><ttl>???TITLE???</ttl><xreftext>RELOAD CONFIGURATION</xreftext></obj><obj element="term" href="#show-configuration" number="" targetptr="show-configuration"><ttl>???TITLE???</ttl><xreftext>SHOW CONFIGURATION</xreftext></obj><obj element="term" href="#show-info" number="" targetptr="show-info"><ttl>???TITLE???</ttl><xreftext>SHOW INFO</xreftext></obj><obj element="term" href="#show-stat" number="" targetptr="show-stat"><ttl>???TITLE???</ttl><xreftext>SHOW STAT</xreftext></obj><obj element="term" href="#show-slab" number="" targetptr="show-slab"><ttl>???TITLE???</ttl><xreftext>SHOW SLAB</xreftext></obj><obj element="term" href="#show-palloc" number="" targetptr="show-palloc"><ttl>???TITLE???</ttl><xreftext>SHOW PALLOC</xreftext></obj><obj element="term" href="#save-coredump" number="" targetptr="save-coredump"><ttl>???TITLE???</ttl><xreftext>SAVE COREDUMP</xreftext></obj><obj element="term" href="#show-fiber" number="" targetptr="show-fiber"><ttl>???TITLE???</ttl><xreftext>SHOW FIBER</xreftext></obj><obj element="term" href="#lua-command" number="" targetptr="lua-command"><ttl>???TITLE???</ttl><xreftext>LUA ...</xreftext></obj></div><div element="section" href="#stored-programs" number="" targetptr="stored-programs"><ttl>Writing stored procedures in Lua</ttl><xreftext>the section called “Writing stored procedures in Lua”</xreftext></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="#idp348160" number=""><ttl>Replication architecture</ttl><xreftext>the section called “Replication architecture”</xreftext></div><div element="section" href="#idp352928" number=""><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the master”</xreftext></div><div element="section" href="#idp263504" number=""><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replica”</xreftext></div><div element="section" href="#idp269840" number=""><ttl>Recovering from a degraded state</ttl><xreftext>the section called “Recovering from a degraded state”</xreftext></div></div><div element="chapter" href="#configuration-reference" number="6" targetptr="configuration-reference"><ttl>Configuration reference</ttl><xreftext>Chapter 6, <i>Configuration reference</i></xreftext><div element="section" href="#idp661264" number=""><ttl>Command line options</ttl><xreftext>the section called “Command line options”</xreftext><obj element="listitem" href="#help-option" number="" targetptr="help-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#version-option" number="" targetptr="version-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#config-option" number="" targetptr="config-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="option" href="#init-storage-option" number="" targetptr="init-storage-option"><ttl>???TITLE???</ttl><xreftext>--init-storage</xreftext></obj><obj element="option" href="#cat-option" number="" targetptr="cat-option"><ttl>???TITLE???</ttl><xreftext>--cat</xreftext></obj></div><div element="section" href="#option-file" number="" targetptr="option-file"><ttl>The option file</ttl><xreftext>option file</xreftext><obj element="table" href="#idp673888" number="6.1"><ttl>Basic parameters</ttl><xreftext>Table 6.1, “Basic parameters”</xreftext></obj><obj element="entry" href="#wal_dir" number="" targetptr="wal_dir"><ttl>???TITLE???</ttl><xreftext>wal_dir</xreftext></obj><obj element="entry" href="#snap_dir" number="" targetptr="snap_dir"><ttl>???TITLE???</ttl><xreftext>snap_dir</xreftext></obj><obj element="entry" href="#primary_port" number="" targetptr="primary_port"><ttl>???TITLE???</ttl><xreftext>primary_port</xreftext></obj><obj element="entry" href="#secondary_port" number="" targetptr="secondary_port"><ttl>???TITLE???</ttl><xreftext>secondary_port</xreftext></obj><obj element="entry" href="#admin_port" number="" targetptr="admin_port"><ttl>???TITLE???</ttl><xreftext>admin_port</xreftext></obj><obj element="entry" href="#custom_proc_title" number="" targetptr="custom_proc_title"><ttl>???TITLE???</ttl><xreftext>custom_proc_title</xreftext></obj><obj element="table" href="#idp722528" number="6.2"><ttl>Configuring the storage</ttl><xreftext>Table 6.2, “Configuring the storage”</xreftext></obj><obj element="anchor" href="#slab_alloc_arena" number="" targetptr="slab_alloc_arena"><ttl>???TITLE???</ttl><xreftext>slab_alloc_arena</xreftext></obj><obj element="para" href="#space" number="" targetptr="space"><ttl>???TITLE???</ttl><xreftext>the section called “The option file”</xreftext></obj><obj element="table" href="#idp758544" number="6.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 6.3, “Binary logging and snapshots”</xreftext></obj><obj element="table" href="#idp789952" number="6.4"><ttl>Replication</ttl><xreftext>Table 6.4, “Replication”</xreftext></obj><obj element="entry" href="#replication_port" number="" targetptr="replication_port"><ttl>???TITLE???</ttl><xreftext>replication_port</xreftext></obj><obj element="entry" href="#replication_source" number="" targetptr="replication_source"><ttl>???TITLE???</ttl><xreftext>replication_source</xreftext></obj><obj element="table" href="#idp808928" number="6.5"><ttl>Networking</ttl><xreftext>Table 6.5, “Networking”</xreftext></obj><obj element="table" href="#idp827696" number="6.6"><ttl>Logging</ttl><xreftext>Table 6.6, “Logging”</xreftext></obj><obj element="table" href="#idp852592" number="6.7"><ttl>Memcached protocol support</ttl><xreftext>Table 6.7, “Memcached protocol support”</xreftext></obj><obj element="anchor" href="#memcached_port" number="" targetptr="memcached_port"><ttl>???TITLE???</ttl><xreftext>memcached_port</xreftext></obj><obj element="anchor" href="#memcached_space" number="" targetptr="memcached_space"><ttl>???TITLE???</ttl><xreftext>memcached_space</xreftext></obj><obj element="anchor" href="#memcached_expire" number="" targetptr="memcached_expire"><ttl>???TITLE???</ttl><xreftext>memcached_expire</xreftext></obj></div></div><div element="chapter" href="#connectors" number="7" targetptr="connectors"><ttl>Connectors</ttl><xreftext>Chapter 7, <i>Connectors</i></xreftext><div element="section" href="#idp491568" number=""><ttl>C</ttl><xreftext>the section called “C”</xreftext></div><div element="section" href="#idp493696" number=""><ttl>Perl</ttl><xreftext>the section called “Perl”</xreftext></div><div element="section" href="#idp537824" number=""><ttl>PHP</ttl><xreftext>the section called “PHP”</xreftext></div><div element="section" href="#idp539168" number=""><ttl>Python</ttl><xreftext>the section called “Python”</xreftext></div><div element="section" href="#idp632096" number=""><ttl>Ruby</ttl><xreftext>the section called “Ruby”</xreftext><obj element="example" href="#idp636896" number="7.1"><ttl>userbox.rb</ttl><xreftext>Example 7.1, “userbox.rb”</xreftext></obj></div></div><div element="appendix" href="#proctitle" number="A" targetptr="proctitle"><ttl>Server process titles</ttl><xreftext>Appendix A, <i>Server process titles</i></xreftext></div><div element="appendix" href="#errcode" number="B" targetptr="errcode"><ttl>List of error codes</ttl><xreftext>Appendix B, <i>List of error codes</i></xreftext><obj element="term" href="#ER_NONMASTER" number="" targetptr="ER_NONMASTER"><ttl>???TITLE???</ttl><xreftext>ER_NONMASTER</xreftext></obj><obj element="term" href="#ER_ILLEGAL_PARAMS" number="" targetptr="ER_ILLEGAL_PARAMS"><ttl>???TITLE???</ttl><xreftext>ER_ILLEGAL_PARAMS</xreftext></obj><obj element="term" href="#ER_TUPLE_IS_RO" number="" targetptr="ER_TUPLE_IS_RO"><ttl>???TITLE???</ttl><xreftext>ER_TUPLE_IS_RO</xreftext></obj><obj element="term" href="#ER_MEMORY_ISSUE" number="" targetptr="ER_MEMORY_ISSUE"><ttl>???TITLE???</ttl><xreftext>ER_MEMORY_ISSUE</xreftext></obj><obj element="term" href="#ER_WAL_IO" number="" targetptr="ER_WAL_IO"><ttl>???TITLE???</ttl><xreftext>ER_WAL_IO</xreftext></obj><obj element="term" href="#ER_INDEX_VIOLATION" number="" targetptr="ER_INDEX_VIOLATION"><ttl>???TITLE???</ttl><xreftext>ER_INDEX_VIOLATION</xreftext></obj><obj element="term" href="#ER_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></div></div>
+<div element="book" href="#tarantool-user-guide" number="" targetptr="tarantool-user-guide"><ttl>Tarantool/Box User Guide, version 1.4.3-9-g472a615</ttl><xreftext>Tarantool/Box User Guide, version 1.4.3-9-g472a615</xreftext><div element="chapter" href="#idm34816" number="1"><ttl>Preface</ttl><xreftext>Chapter 1, <i>Preface</i></xreftext><div element="section" href="#preface" number="" targetptr="preface"><ttl>Tarantool/Box: an overview</ttl><xreftext>the section called “Tarantool/Box: an overview”</xreftext></div><div element="section" href="#idp17776" number=""><ttl>Conventions</ttl><xreftext>the section called “Conventions”</xreftext></div><div element="section" href="#idp26672" number=""><ttl>Reporting bugs</ttl><xreftext>the section called “Reporting bugs”</xreftext></div></div><div element="chapter" href="#idp220784" number="2"><ttl>Getting started</ttl><xreftext>Chapter 2, <i>Getting started</i></xreftext></div><div element="chapter" href="#idp221040" number="3"><ttl>Dynamic data model</ttl><xreftext>Chapter 3, <i>Dynamic data model</i></xreftext></div><div element="chapter" href="#language-reference" number="4" targetptr="language-reference"><ttl>Language reference</ttl><xreftext>Chapter 4, <i>Language reference</i></xreftext><div element="section" href="#idp384848" number=""><ttl>Data manipulation</ttl><xreftext>the section called “Data manipulation”</xreftext><div element="section" href="#idp378896" number=""><ttl>Memcached protocol</ttl><xreftext>the section called “Memcached protocol”</xreftext></div></div><div element="section" href="#idp376016" number=""><ttl>Administrative console</ttl><xreftext>the section called “Administrative console”</xreftext><obj element="term" href="#save-snapshot" number="" targetptr="save-snapshot"><ttl>???TITLE???</ttl><xreftext>SAVE SNAPSHOT</xreftext></obj><obj element="term" href="#reload-configuration" number="" targetptr="reload-configuration"><ttl>???TITLE???</ttl><xreftext>RELOAD CONFIGURATION</xreftext></obj><obj element="term" href="#show-configuration" number="" targetptr="show-configuration"><ttl>???TITLE???</ttl><xreftext>SHOW CONFIGURATION</xreftext></obj><obj element="term" href="#show-info" number="" targetptr="show-info"><ttl>???TITLE???</ttl><xreftext>SHOW INFO</xreftext></obj><obj element="term" href="#show-stat" number="" targetptr="show-stat"><ttl>???TITLE???</ttl><xreftext>SHOW STAT</xreftext></obj><obj element="term" href="#show-slab" number="" targetptr="show-slab"><ttl>???TITLE???</ttl><xreftext>SHOW SLAB</xreftext></obj><obj element="term" href="#show-palloc" number="" targetptr="show-palloc"><ttl>???TITLE???</ttl><xreftext>SHOW PALLOC</xreftext></obj><obj element="term" href="#save-coredump" number="" targetptr="save-coredump"><ttl>???TITLE???</ttl><xreftext>SAVE COREDUMP</xreftext></obj><obj element="term" href="#show-fiber" number="" targetptr="show-fiber"><ttl>???TITLE???</ttl><xreftext>SHOW FIBER</xreftext></obj><obj element="term" href="#lua-command" number="" targetptr="lua-command"><ttl>???TITLE???</ttl><xreftext>LUA ...</xreftext></obj></div><div element="section" href="#stored-programs" number="" targetptr="stored-programs"><ttl>Writing stored procedures in Lua</ttl><xreftext>the section called “Writing stored procedures in Lua”</xreftext></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="#idp348448" number=""><ttl>Replication architecture</ttl><xreftext>the section called “Replication architecture”</xreftext></div><div element="section" href="#idp353184" number=""><ttl>Setting up the master</ttl><xreftext>the section called “Setting up the master”</xreftext></div><div element="section" href="#idp262720" number=""><ttl>Setting up a replica</ttl><xreftext>the section called “Setting up a replica”</xreftext></div><div element="section" href="#idp269168" number=""><ttl>Recovering from a degraded state</ttl><xreftext>the section called “Recovering from a degraded state”</xreftext></div></div><div element="chapter" href="#configuration-reference" number="6" targetptr="configuration-reference"><ttl>Configuration reference</ttl><xreftext>Chapter 6, <i>Configuration reference</i></xreftext><div element="section" href="#idp679424" number=""><ttl>Command line options</ttl><xreftext>the section called “Command line options”</xreftext><obj element="listitem" href="#help-option" number="" targetptr="help-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#version-option" number="" targetptr="version-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="listitem" href="#config-option" number="" targetptr="config-option"><ttl>???TITLE???</ttl><xreftext/></obj><obj element="option" href="#init-storage-option" number="" targetptr="init-storage-option"><ttl>???TITLE???</ttl><xreftext>--init-storage</xreftext></obj><obj element="option" href="#cat-option" number="" targetptr="cat-option"><ttl>???TITLE???</ttl><xreftext>--cat</xreftext></obj></div><div element="section" href="#option-file" number="" targetptr="option-file"><ttl>The option file</ttl><xreftext>option file</xreftext><obj element="table" href="#idp692032" number="6.1"><ttl>Basic parameters</ttl><xreftext>Table 6.1, “Basic parameters”</xreftext></obj><obj element="entry" href="#wal_dir" number="" targetptr="wal_dir"><ttl>???TITLE???</ttl><xreftext>wal_dir</xreftext></obj><obj element="entry" href="#snap_dir" number="" targetptr="snap_dir"><ttl>???TITLE???</ttl><xreftext>snap_dir</xreftext></obj><obj element="entry" href="#primary_port" number="" targetptr="primary_port"><ttl>???TITLE???</ttl><xreftext>primary_port</xreftext></obj><obj element="entry" href="#secondary_port" number="" targetptr="secondary_port"><ttl>???TITLE???</ttl><xreftext>secondary_port</xreftext></obj><obj element="entry" href="#admin_port" number="" targetptr="admin_port"><ttl>???TITLE???</ttl><xreftext>admin_port</xreftext></obj><obj element="entry" href="#custom_proc_title" number="" targetptr="custom_proc_title"><ttl>???TITLE???</ttl><xreftext>custom_proc_title</xreftext></obj><obj element="table" href="#idp740672" number="6.2"><ttl>Configuring the storage</ttl><xreftext>Table 6.2, “Configuring the storage”</xreftext></obj><obj element="anchor" href="#slab_alloc_arena" number="" targetptr="slab_alloc_arena"><ttl>???TITLE???</ttl><xreftext>slab_alloc_arena</xreftext></obj><obj element="para" href="#space" number="" targetptr="space"><ttl>???TITLE???</ttl><xreftext>the section called “The option file”</xreftext></obj><obj element="table" href="#idp776688" number="6.3"><ttl>Binary logging and snapshots</ttl><xreftext>Table 6.3, “Binary logging and snapshots”</xreftext></obj><obj element="table" href="#idp808096" number="6.4"><ttl>Replication</ttl><xreftext>Table 6.4, “Replication”</xreftext></obj><obj element="entry" href="#replication_port" number="" targetptr="replication_port"><ttl>???TITLE???</ttl><xreftext>replication_port</xreftext></obj><obj element="entry" href="#replication_source" number="" targetptr="replication_source"><ttl>???TITLE???</ttl><xreftext>replication_source</xreftext></obj><obj element="table" href="#idp827072" number="6.5"><ttl>Networking</ttl><xreftext>Table 6.5, “Networking”</xreftext></obj><obj element="table" href="#idp845840" number="6.6"><ttl>Logging</ttl><xreftext>Table 6.6, “Logging”</xreftext></obj><obj element="table" href="#idp870736" number="6.7"><ttl>Memcached protocol support</ttl><xreftext>Table 6.7, “Memcached protocol support”</xreftext></obj><obj element="anchor" href="#memcached_port" number="" targetptr="memcached_port"><ttl>???TITLE???</ttl><xreftext>memcached_port</xreftext></obj><obj element="anchor" href="#memcached_space" number="" targetptr="memcached_space"><ttl>???TITLE???</ttl><xreftext>memcached_space</xreftext></obj><obj element="anchor" href="#memcached_expire" number="" targetptr="memcached_expire"><ttl>???TITLE???</ttl><xreftext>memcached_expire</xreftext></obj></div></div><div element="chapter" href="#connectors" number="7" targetptr="connectors"><ttl>Connectors</ttl><xreftext>Chapter 7, <i>Connectors</i></xreftext><div element="section" href="#idp247104" number=""><ttl>C</ttl><xreftext>the section called “C”</xreftext></div><div element="section" href="#idp253312" number=""><ttl>Perl</ttl><xreftext>the section called “Perl”</xreftext></div><div element="section" href="#idp645056" number=""><ttl>PHP</ttl><xreftext>the section called “PHP”</xreftext></div><div element="section" href="#idp646400" number=""><ttl>Python</ttl><xreftext>the section called “Python”</xreftext></div><div element="section" href="#idp647744" number=""><ttl>Ruby</ttl><xreftext>the section called “Ruby”</xreftext><obj element="example" href="#idp652656" number="7.1"><ttl>userbox.rb</ttl><xreftext>Example 7.1, “userbox.rb”</xreftext></obj></div></div><div element="appendix" href="#proctitle" number="A" targetptr="proctitle"><ttl>Server process titles</ttl><xreftext>Appendix A, <i>Server process titles</i></xreftext></div><div element="appendix" href="#errcode" number="B" targetptr="errcode"><ttl>List of error codes</ttl><xreftext>Appendix B, <i>List of error codes</i></xreftext><obj element="term" href="#ER_NONMASTER" number="" targetptr="ER_NONMASTER"><ttl>???TITLE???</ttl><xreftext>ER_NONMASTER</xreftext></obj><obj element="term" href="#ER_ILLEGAL_PARAMS" number="" targetptr="ER_ILLEGAL_PARAMS"><ttl>???TITLE???</ttl><xreftext>ER_ILLEGAL_PARAMS</xreftext></obj><obj element="term" href="#ER_TUPLE_IS_RO" number="" targetptr="ER_TUPLE_IS_RO"><ttl>???TITLE???</ttl><xreftext>ER_TUPLE_IS_RO</xreftext></obj><obj element="term" href="#ER_MEMORY_ISSUE" number="" targetptr="ER_MEMORY_ISSUE"><ttl>???TITLE???</ttl><xreftext>ER_MEMORY_ISSUE</xreftext></obj><obj element="term" href="#ER_WAL_IO" number="" targetptr="ER_WAL_IO"><ttl>???TITLE???</ttl><xreftext>ER_WAL_IO</xreftext></obj><obj element="term" href="#ER_INDEX_VIOLATION" number="" targetptr="ER_INDEX_VIOLATION"><ttl>???TITLE???</ttl><xreftext>ER_INDEX_VIOLATION</xreftext></obj><obj element="term" href="#ER_NO_SUCH_SPACE" number="" targetptr="ER_NO_SUCH_SPACE"><ttl>???TITLE???</ttl><xreftext>ER_NO_SUCH_SPACE</xreftext></obj><obj element="term" href="#ER_NO_SUCH_INDEX" number="" targetptr="ER_NO_SUCH_INDEX"><ttl>???TITLE???</ttl><xreftext>ER_NO_SUCH_INDEX</xreftext></obj><obj element="term" href="#ER_PROC_LUA" number="" targetptr="ER_PROC_LUA"><ttl>???TITLE???</ttl><xreftext>ER_PROC_LUA</xreftext></obj></div></div>
diff --git a/doc/user/tnt.css b/doc/user/tnt.css
index 28bf7088da..8088f9f639 100644
--- a/doc/user/tnt.css
+++ b/doc/user/tnt.css
@@ -5,6 +5,12 @@
   color: green;
 }
 
+.lua {
+  font-family: monospace;
+  font-weight: bold;
+}
+
+
 .hl-keyword {
   color: green;
   font-weight: bold;
diff --git a/mod/box/box.lua b/mod/box/box.lua
index ecca4cd86f..9a1a0cd8f6 100644
--- a/mod/box/box.lua
+++ b/mod/box/box.lua
@@ -2,16 +2,16 @@
 --
 --
 function box.select(space, index, ...)
-    key = {...}
-    return select(2, -- skip the first return from select, number of tuples
-        box.process(17, box.pack('iiiiii'..string.rep('p', #key),
+    local key = {...}
+    return box.process(17,
+                       box.pack('iiiiii'..string.rep('p', #key),
                                  space,
                                  index,
                                  0, -- offset
                                  4294967295, -- limit
                                  1, -- key count
                                  #key, -- key cardinality
-                                 unpack(key))))
+                                 unpack(key)))
 end
 
 --
@@ -28,49 +28,50 @@ end
 -- index is always 0. It doesn't accept compound keys
 --
 function box.delete(space, key)
-    return select(2, -- skip the first return, tuple count
-        box.process(21, box.pack('iiip', space,
+    return box.process(21,
+                       box.pack('iiip', space,
                                  1, -- flags, BOX_RETURN_TUPLE
                                  1, -- cardinality
-                                 key)))
+                                 key))
 end
 
 -- insert or replace a tuple
 function box.replace(space, ...)
-    tuple = {...}
-    return select(2,
-        box.process(13, box.pack('iii'..string.rep('p', #tuple),
+    local tuple = {...}
+    return box.process(13,
+                       box.pack('iii'..string.rep('p', #tuple),
                                  space,
                                  1, -- flags, BOX_RETURN_TUPLE 
                                  #tuple, -- cardinality
-                                 unpack(tuple))))
+                                 unpack(tuple)))
 end
 
 -- insert a tuple (produces an error if the tuple already exists)
 function box.insert(space, ...)
-    tuple = {...}
-    return select(2,
-        box.process(13, box.pack('iii'..string.rep('p', #tuple),
-                                 space,
-                                 3, -- flags, BOX_RETURN_TUPLE | BOX_ADD
-                                 #tuple, -- cardinality
-                                 unpack(tuple))))
+    local tuple = {...}
+    return box.process(13,
+                       box.pack('iii'..string.rep('p', #tuple),
+                                space,
+                                3, -- flags, BOX_RETURN_TUPLE  | BOX_ADD
+                                #tuple, -- cardinality
+                                unpack(tuple)))
 end
 
+-- 
 function box.update(space, key, format, ...)
-    ops = {...}
-    return select(2,
-        box.process(19, box.pack('iiipi'..format,
+    local ops = {...}
+    return box.process(19,
+                       box.pack('iiipi'..format,
                                   space,
                                   1, -- flags, BOX_RETURN_TUPLE
                                   1, -- cardinality
                                   key, -- primary key
                                   #ops/2, -- op count
-                                  ...)))
+                                  unpack(ops)))
 end
 
 function box.on_reload_configuration()
-    index_mt = {}
+    local index_mt = {}
     -- __len and __index
     index_mt.len = function(index) return #index.idx end
     index_mt.__newindex = function(table, index)
@@ -84,7 +85,7 @@ function box.on_reload_configuration()
         return index.idx.next, index.idx, nil end
     --
     index_mt.range = function(index, limit, ...)
-        range = {}
+        local range = {}
         for k, v in index.idx.next, index.idx, ... do
             if #range >= limit then
                 break
@@ -94,7 +95,7 @@ function box.on_reload_configuration()
         return unpack(range)
     end
     --
-    space_mt = {}
+    local space_mt = {}
     space_mt.len = function(space) return space.index[0]:len() end
     space_mt.__newindex = index_mt.__newindex
     space_mt.select = function(space, ...) return box.select(space.n, ...) end
@@ -104,7 +105,7 @@ function box.on_reload_configuration()
     space_mt.delete = function(space, ...) return box.delete(space.n, ...) end
     space_mt.truncate = function(space)
         while true do
-            k, v = space.index[0].idx:next()
+            local k, v = space.index[0].idx:next()
             if v == nil then
                 break
             end
diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m
index 5988d13766..4d21f8c319 100644
--- a/mod/box/box_lua.m
+++ b/mod/box/box_lua.m
@@ -540,15 +540,20 @@ iov_add_multret(struct lua_State *L)
 }
 
 static void
-box_lua_dup_u32(u32 u32)
+box_lua_dup_u32(u32 u32 __attribute__((unused)))
 {
-	lua_pushinteger(in_txn()->L, u32);
+	/*
+	 * Do nothing -- the only u32 Box can give us is
+	 * tuple count, and we don't need it, since we intercept
+	 * everything into Lua stack first.
+	 * @sa iov_add_multret
+	 */
 }
 
 static void
-box_lua_add_u32(u32 *p_u32)
+box_lua_add_u32(u32 *p_u32 __attribute__((unused)))
 {
-	box_lua_dup_u32(*p_u32); /* xxx: this can't be done properly in Lua */
+	/* See the comment in box_lua_dup_u32. */
 }
 
 static void
diff --git a/test/box/lua.result b/test/box/lua.result
index eb600ed9a9..a9cb24b407 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -73,22 +73,18 @@ lua print(box.pack('p', 'this string is 45 characters long 1234567890 '))
 ...
 lua box.process(13, box.pack('iiippp', 0, 1, 3, 1, 'testing', 'lua rocks'))
 ---
- - 1
  - 1: {'testing', 'lua rocks'}
 ...
 lua box.process(17, box.pack('iiiiiip', 0, 0, 0, 2^31, 1, 1, 1))
 ---
- - 0
  - 1: {'testing', 'lua rocks'}
 ...
 lua box.process(21, box.pack('iiip', 0, 1, 1, 1))
 ---
- - 1
  - 1: {'testing', 'lua rocks'}
 ...
 lua box.process(17, box.pack('iiiiiip', 0, 0, 0, 2^31, 1, 1, 1))
 ---
- - 0
 ...
 lua box.process(22, box.pack('iii', 0, 0, 0))
 ---
-- 
GitLab