diff --git a/CMakeLists.txt b/CMakeLists.txt index 95b116a224216533503f5652b12a6453c9f5f59b..e72e8748e07822e3721becee39041186fc7b834f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,7 @@ add_custom_target(tags COMMAND ctags -R -f tags # set (CPACK_PACKAGE_VERSION_MAJOR "1") set (CPACK_PACKAGE_VERSION_MINOR "6") -set (CPACK_PACKAGE_VERSION_PATCH "1") +set (CPACK_PACKAGE_VERSION_PATCH "2") set (PACKAGE_VERSION "") @@ -300,6 +300,7 @@ add_dependencies(build_bundled_libs misc) include(BuildSophia) sophia_build() +set (sophia_lib "${PROJECT_BINARY_DIR}/third_party/sophia/db/libsophia.a") option(ENABLE_RPM "Enable install of a RPM specific files" OFF) diff --git a/README.md b/README.md index 777b60f3e749c6cab2ef3b312ad82c7edf8674b8..b2bb486e05ff159f3ba6f3999c9202692e3e2a39 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,7 @@ The build depends on the following external libraries: Please follow these steps to compile Tarantool: # If compiling from git - tarantool $ git submodule init - tarantool $ git submodule update + tarantool $ git submodule update --init tarantool $ cmake . tarantool $ make diff --git a/doc/box-protocol.txt b/doc/box-protocol.txt index 1ecc0be4a61ba34407d090b5e18e3065a0a19ce5..6ded42d535ef3b8f67851a53321627c3ebb3a0e9 100644 --- a/doc/box-protocol.txt +++ b/doc/box-protocol.txt @@ -4,8 +4,15 @@ ; The latest version of this document can be found in ; Tarantool source tree, doc/box-protocol.txt ; -; IPROTO is a binary request/response protocol that features a -; complete access to Tarantool functionality, including: +; IPROTO is a binary request/response protocol. +; The server begins the dialogue by sending a fixed-size (128 bytes) +; text greeting to the client. The first 64 bytes of the greeting +; contain server version. The second 64 bytes contain a base64- +; encoded random string, to use in authentification packet. + +; Once a greeting is read, the protocol becomes pure +; request/response and features a complete access to Tarantool +; functionality, including: ; - request multiplexing, e.g. ability to asynchronously issue ; multiple requests via the same connection ; - response format that supports zero-copy writes @@ -51,7 +58,7 @@ ; ; The value of the constant defines the type of value of the map. -; For example, for <error> key (0x31), the expected value is a +; For example, for <error> key (0x31), the expected value is a ; msgpack string with error message. ; All requests and responses utilize the same basic structure @@ -89,13 +96,15 @@ ; Request packet structure ; ----------------------------------- ; Value for <code> key in request can be: -; 0 -- <ping> ; 1 -- <select> ; 2 -- <insert> ; 3 -- <replace> ; 4 -- <update> ; 5 -- <delete> ; 6 -- <call> +; 7 -- <auth> +; 64 -- <ping> +; 66 -- <subscribe> ; <sync> is a unique request identifier, preserved in the response, ; The identifier is necessary to allow request multiplexing -- @@ -130,9 +139,24 @@ ; Call a stored function <call> ::= <function_name> | <tuple> +; Authenticate a session +; <key> holds the user name. <tuple> must be an array of 2 fields: +; authentication mechanism ("chap-sha1" is the only supported +; mechanism right now) and password, encrypted according to the +; specified mechanism +; https://github.com/tarantool/tarantool/blob/master/src/scramble.h +; for instructions how to prepare a hashed password for "chap-sha1" +; authentication mechanism. +; Authentication in Tarantool is optional, if no +; authentication is performed, session user is 'guest'. +; The server responds to authentication packet with a standard +; response with 0 tuples. + +<auth> ::= <key> | <tuple> + ; As can be seen from the grammar some requests have common keys, ; whereas other keys can be present only in a body of a single -; request type. +; request type. ; <space_id> space to use in the request ; To find the numeric space id by space name, one @@ -201,7 +225,7 @@ ; more tuples, otherwise it carries an error message that corresponds ; to the return code. -; On success, the server always returns a tuple or tuples, +; On success, the server always returns a tuple or tuples, ; when found. ; I.e. on success, response <body> contains <set> key. ; For select/update/delete, it's the tuple that matched @@ -250,5 +274,9 @@ ; Convenience macros which define hexadecimal constants for ; <int32> return codes (completion status + code) can be found here: ; https://github.com/tarantool/tarantool/blob/master/src/errcode.h +; +; +; Additional packets +; ------------------ ; vim: syntax=bnf diff --git a/doc/user/connectors.xml b/doc/user/connectors.xml index 8e7b9ce36ea239fe68ddaf50e082f99117dafc91..0b7069dfc917f41dd515953cc7c5673eca69103d 100644 --- a/doc/user/connectors.xml +++ b/doc/user/connectors.xml @@ -180,7 +180,7 @@ int main() <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. + xlink:href="https://github.com/tarantool/tarantool-c"><filename>connector/c</filename></link> source tree. </para> </section> diff --git a/doc/user/plugins.xml b/doc/user/plugins.xml index dee8c756402214d5bc275ccaeeacb0af6a571f5c..8c27b79452d77b31a4047be26ae22275bba4a305 100644 --- a/doc/user/plugins.xml +++ b/doc/user/plugins.xml @@ -57,7 +57,7 @@ This example assumes that MySQL 5.5 or MySQL 5.6 has been installed <para> The example was run on a Linux machine where the base directory -had a copy of the Tarantool source on ~/tarantool-stable, and +had a copy of the Tarantool source on ~/tarantool, and a copy of MySQL on ~/mysql-5.5. The mysqld server is already running on the local host 127.0.0.1. </para> @@ -95,7 +95,7 @@ Bye # Build the Tarantool server. Make certain that "cmake" gets the right # paths for the MySQL include directory and the MySQL libmysqlclient # library which were checked earlier. -<prompt>$ </prompt><userinput>cd ~/tarantool-stable</userinput> +<prompt>$ </prompt><userinput>cd ~/tarantool</userinput> <prompt>$ </prompt><userinput>make clean</userinput> <prompt>$ </prompt><userinput>rm CMakeCache.txt</userinput> <prompt>$ </prompt><userinput>cmake . -DWITH_MYSQL=on -DMYSQL_INCLUDE_DIR=~/mysql-5.5/include\</userinput> @@ -108,7 +108,7 @@ Bye ... -- Configuring done -- Generating done --- Build files have been written to: ~/tarantool-stable +-- Build files have been written to: ~/tarantool <prompt>$ </prompt><userinput>make</userinput> ... [ 49%] Built target core @@ -137,8 +137,8 @@ Linking CXX shared library libmysql.so # The script_dir is the directory where the init.lua file must be. # Now create a file named /home/pgulutzan/tarantool_test/init.lua # and put the following lines in it (again, change "/home/pgulutzan" -# to whatever the real directory is that contains tarantool-stable): -package.path = "/home/pgulutzan/tarantool-stable/src/module/sql/?.lua;"..package.path +# to whatever the real directory is that contains tarantool): +package.path = "/home/pgulutzan/tarantool/src/module/sql/?.lua;"..package.path require("sql") if type(box.net.sql) ~= "table" then error("net.sql load failed") @@ -149,19 +149,19 @@ require("box.net.mysql") <userinput>cd /home/pgulutzan/tarantool_test</userinput> <userinput>mkdir box</userinput> <userinput>mkdir box/net</userinput> -<userinput>cp ~/tarantool-stable/src/module/mysql/mysql.so ./box/net/mysql.so</userinput> +<userinput>cp ~/tarantool/src/module/mysql/mysql.so ./box/net/mysql.so</userinput> # Start the Tarantool server. # Run it in the background but let the initial display be in the foreground. # So it's possible to see the message that the plugin was loaded. -<prompt>$ </prompt><userinput>~/tarantool-stable/src/box/tarantool&</userinput> +<prompt>$ </prompt><userinput>~/tarantool/src/box/tarantool&</userinput> 2013-12-03 17:46:16.239 [12957] 1/sched C> version 1.5.1-271-g610930e ... loading /home/pgulutzan/tarantool_test/init.lua ... ... 2013-12-03 17:46:16.244 [12957] 1/sched C> entering event loop # Type 'Enter' and then start the Tarantool client. -<prompt>$ </prompt><userinput>~/tarantool-stable/client/tarantool/tarantool</userinput> +<prompt>$ </prompt><userinput>~/tarantool/client/tarantool/tarantool</userinput> <prompt>localhost> </prompt> # Create a Lua function that will connect to the MySQL server, @@ -207,7 +207,7 @@ must explicitly state where they are when building Tarantool from source. <para> The example was run on a Linux machine where the base directory -had a copy of the Tarantool source on ~/tarantool-stable, and +had a copy of the Tarantool source on ~/tarantool, and a copy of PostgreSQL on /usr. The postgres server is already running on the local host 127.0.0.1. </para> @@ -242,7 +242,7 @@ INSERT 0 1 # Build the Tarantool server. Make certain that "cmake" gets the right # paths for the PostgreSQL include directory and the PostgreSQL libpq # library which were checked earlier. -<prompt>$ </prompt><userinput>cd ~/tarantool-stable</userinput> +<prompt>$ </prompt><userinput>cd ~/tarantool</userinput> <prompt>$ </prompt><userinput>make clean</userinput> <prompt>$ </prompt><userinput>rm CMakeCache.txt</userinput> <prompt>$ </prompt><userinput>cmake . -DWITH_POSTGRESQL=on -DPostgreSQL_LIBRARY=/usr/lib/libpq.so\</userinput> @@ -254,7 +254,7 @@ INSERT 0 1 ... -- Configuring done -- Generating done --- Build files have been written to: ~/tarantool-stable +-- Build files have been written to: ~/tarantool <prompt>$ </prompt><userinput>make</userinput> ... [ 49%] Built target core @@ -267,21 +267,21 @@ Linking CXX shared library libpg.so <prompt>$ </prompt> # Before starting Tarantool server, tell it where the PostgreSQL plugin is. -<prompt>$ </prompt><userinput>export TARANTOOL_PLUGIN_DIR=~/tarantool-stable/src/plugin/pg</userinput> +<prompt>$ </prompt><userinput>export TARANTOOL_PLUGIN_DIR=~/tarantool/src/plugin/pg</userinput> <prompt>$ </prompt> # Start the Tarantool server. # Run it in the background but let the initial display be in the foreground. # So it's possible to see the message that the plugin was loaded. -<prompt>$ </prompt><userinput>~/tarantool-stable/src/box/tarantool&</userinput> +<prompt>$ </prompt><userinput>~/tarantool/src/box/tarantool&</userinput> 2013-12-06 13:01:51.518 [23978] 1/sched C> version 1.5.1-290-g45b93e7 -... Loading plugin: ~/tarantool-stable/src/plugin/pg/libpg.so ... +... Loading plugin: ~/tarantool/src/plugin/pg/libpg.so ... ... Plugin 'postgresql' was loaded, version: 1 ... 2013-12-06 13:01:51.531 [23978] 1/sched C> entering event loop # Type 'Enter' and then start the Tarantool client. -<prompt>$ </prompt><userinput>~/tarantool-stable/client/tarantool/tarantool</userinput> +<prompt>$ </prompt><userinput>~/tarantool/client/tarantool/tarantool</userinput> <prompt>localhost> </prompt> # Create a Lua function that will connect to the PostgreSQL server, diff --git a/doc/user/preface.xml b/doc/user/preface.xml index 96cd929902494088165fd5e4a5b0e255f4bc3cd9..c9e2285720c78b74bb872d9b617c22dfbdd38f29 100644 --- a/doc/user/preface.xml +++ b/doc/user/preface.xml @@ -8,8 +8,9 @@ <section xml:id="tarantool-overview"> <title>Tarantool: an overview</title> <para> - <productname>Tarantool</productname> is an in-memory NoSQL - database management system. The code is available for free under the terms of the + <productname>Tarantool</productname> is a NoSQL + database management system running in a Lua application + server. The code is available for free under the terms of the <citetitle xlink:href="http://www.gnu.org/licenses/license-list.html#ModifiedBSD">BSD license</citetitle>. Supported platforms are GNU/Linux, Mac OS diff --git a/doc/user/tutorial.xml b/doc/user/tutorial.xml index 8197556d797fa124e99d2b3d27c57a0b69f5ffc3..332b2a1d41bf80128bc985840fabbc34428fb22e 100644 --- a/doc/user/tutorial.xml +++ b/doc/user/tutorial.xml @@ -36,7 +36,7 @@ targetptr="getting-started-source"><quote>Downloading and building a source pack <para> If the installation has already been done, then you should try it out. So we've provided some instructions that you can use to make a temporary <quote>sandbox</quote>. -In a few minutes you can start the server, start the client, and type in some +In a few minutes you can start the server and type in some database-manipulation statements. The section about sandbox is <olink targetptr="getting-started-start-stop"><quote>Starting Tarantool and making your first database</quote></olink>. @@ -46,9 +46,9 @@ targetptr="getting-started-start-stop"><quote>Starting Tarantool and making your <title>Downloading and installing a binary package</title> <para> -The repositories for the <quote>stable</quote> release are at <link xlink:href="http://tarantool.org/dist" xlink:title="tarantool.org/dist">tarantool.org/dist</link>. +The repositories for the <quote>stable</quote> release are at <link xlink:href="http://tarantool.org/dist/stable" xlink:title="tarantool.org/dist/stble">tarantool.org/dist/stable</link>. The repositories for the <quote>master</quote> release are at <link xlink:href="http://tarantool.org/dist/master" xlink:title="tarantool.org/dist/master">tarantool.org/dist/master</link>. -Since this is the manual for the <quote>master</quote> release, all instructions use <link xlink:href="http://tarantool.org/dist" xlink:title="tarantool.org/dist/master">tarantool.org/dist/master</link>. +Since this is the manual for the <quote>master</quote> release, all instructions use <link xlink:href="http://tarantool.org/dist/master" xlink:title="tarantool.org/dist/master">tarantool.org/dist/master</link>. </para> <para> @@ -87,7 +87,7 @@ release=`lsb_release -c -s` <command>sudo tee</command> <option>-a</option> <filename>/etc/apt/sources.list.d/tarantool.list</filename> # install <command>sudo apt-get update</command> -<command>sudo apt-get install</command> tarantool tarantool-client +<command>sudo apt-get install</command> tarantool </programlisting> </para> @@ -114,7 +114,7 @@ release=`lsb_release -c -s` <command>sudo tee</command> <option>-a</option> <filename>/etc/apt/sources.list.d/tarantool.list</filename> # install <command>sudo apt-get update</command> -<command>sudo apt-get install</command> tarantool tarantool-client +<command>sudo apt-get install</command> tarantool </programlisting> </para> @@ -162,27 +162,6 @@ release=`lsb_release -c -s` </programlisting> </para> -<para> -<programlisting> -# ANY-LINUX commands for Tarantool master binary download: -# If you have a GNU/Linux distribution which is not one of the above, -# or if you want to install on your own subdirectory without affecting -# /usr /etc etc., start your browser and go to -# <link xlink:href="http://tarantool.org/dist/master">http://tarantool.org/dist/master</link> download page. -# Look for a recent file whose name ends with "tar.gz". You will want the -# right binary tarball (<filename>.tar.gz</filename>) file for your release architecture. -# Click on either the one whose name ends with "linux-i686.tar.gz" or -# the one whose name ends with "linux-x86_64.tar.gz" depending on your release architecture. -# This will cause a download of the latest master tarball. -# Suppose it is <filename>tarantool-1.6.1-9-g30fe8ae-linux-x86_64.tar.gz</filename>. Say: -<command>tar</command> <option>zxvf</option> <filename>tarantool-1.6.1-9-g30fe8ae-linux-x86_64.tar.gz</filename> -# You now have a directory named tarantool-1.6.1-9-g30fe8ae-linux-x86_64. -# Let's move it to ~/tarantool, which is an easier name to remember. -<command>mv</command> <filename>tarantool-1.6.1-9-g30fe8ae-linux-x86_64 ~/tarantool</filename> -# Within it there is a subdirectory <filename>/bin</filename> containing both server and client. -</programlisting> -</para> - <para> <programlisting> # FREEBSD commands for Tarantool master binary download: @@ -213,7 +192,6 @@ More advice for binary downloads is at <link xlink:href="http://tarantool.org/do </section> - <section xml:id="getting-started-source"> <title>Downloading and building a source package</title> <para> @@ -261,10 +239,10 @@ ones unless you intend to work on the documentation. <programlisting> binutils-dev or binutils-devel # contains GNU bfd for printing stack traces gcc or clang # see above git # see above - uuid-dev # optional, for box_uuid_* functions + uuid-dev # for box.uuid_* functions and replication cmake # see above - libreadline-dev # optional, for build with -DENABLE_CLIENT - libncurses5-dev or ncurses-devel # optional, for build with -DENABLE_CLIENT + libreadline-dev # for interactive mode + libncurses5-dev or ncurses-devel # see above xsltproc # optional, for build with -DENABLE_DOC lynx # optional, for build with -DENABLE_DOC jing # optional, for build with -DENABLE_DOC @@ -342,7 +320,7 @@ the tarantool download will go inside it, as <computeroutput><filename>~/taranto 4. Use <productname>git</productname> to download from github.com.<programlisting> <command>cd</command> ~ <command>git clone</command> <option>-b master</option> https://github.com/tarantool/tarantool.git <option>tarantool</option></programlisting> -The optional argument <quote>-b master</quote> causes download from the stable branch instead of the stable branch, +The optional argument <quote>-b master</quote> causes download from the master branch instead of the stable branch, and the optional last word on the line, <quote>tarantool</quote>, means download is to <computeroutput>~/tarantool</computeroutput>. </para> @@ -360,15 +338,13 @@ but we prefer this method because it works with older versions of <productname>g 6. Use CMake to initiate the build.<programlisting><command>cd</command> ~/tarantool <command>make clean</command> # unnecessary, added for good luck <command>rm CMakeCache.txt</command> # unnecessary, added for good luck -<command>cmake .</command> # Start build with build type=Debug, no client, no doc</programlisting> +<command>cmake .</command> # Start build with build type=Debug, no doc</programlisting> The option for specifying build type is <option>-DCMAKE_BUILD_TYPE=</option><replaceable>type</replaceable> where type = {None | Debug | Release | RelWithDebInfo | MinSizeRel} and a reasonable choice for production is <option>-DCMAKE_BUILD_TYPE=RelWithDebInfo</option> (<quote>Debug</quote> is used only by project maintainers and <quote>Release</quote> is used only when the highest performance is required). -The option for asking to build client is <computeroutput><option>-DENABLE_CLIENT=</option><replaceable>{true|false}</replaceable></computeroutput> -and a reasonable choice is <computeroutput><option>-DENABLE_CLIENT=true</option></computeroutput>. The option for asking to build documentation is <computeroutput><option>-DENABLE_DOC=</option><replaceable>{true|false}</replaceable></computeroutput> and the assumption is that only a minority will need to rebuild the documentation (such as what you're reading now), so details about @@ -433,7 +409,7 @@ For your added convenience, github.com has README files with example scripts: <productname xlink:href="https://github.com/tarantool/tarantool/blob/master/README.md">README.md</productname> for generic GNU/Linux. These example scripts assume that the intent is to download from the master branch, build -the server and the client (but not the documentation), and run tests after build. +the server (but not the documentation), and run tests after build. </para> <para> @@ -458,45 +434,21 @@ Here is how to create a simple test database after installing. </para> <para> -2. Create a configuration file. The Tarantool server can use a configuration -file with some definitions of ports and database objects. - The server, by default, looks for its configuration file in - the current working directory and in <computeroutput><filename>etc/</filename></computeroutput>. -Enter the following commands -which make a minimal configuration file that will be suitable for day one. -<programlisting> -<command>echo</command> "slab_alloc_arena = 0.1" | <command>tee</command> tarantool.cfg -<command>echo</command> "pid_file = \"box.pid\"" | <command>tee</command> <option>-a</option> tarantool.cfg -<command>echo</command> "primary_port = 3301" | <command>tee</command> <option>-a</option> tarantool.cfg -<command>echo</command> "admin_port = 33015" | <command>tee</command> <option>-a</option> tarantool.cfg -<command>echo</command> "rows_per_wal = 50000" | <command>tee</command> <option>-a</option> tarantool.cfg -<command>echo</command> "logger = \"tee -a tarantool.log\"" | <command>tee</command> <option>-a</option> tarantool.cfg -<command>echo</command> "work_dir = \"work_dir\"" | <command>tee</command> <option>-a</option> tarantool.cfg -# (With some downloads a tarantool.cfg file like this is already available -# in a test subdirectory.) -</programlisting> -</para> - -<para> -Initialize the storage area. -You only have to do this once.<programlisting> -#if you downloaded a binary with apt-get or yum, say this: - <command>/usr/bin/tarantool --init-storage</command> -#if you downloaded and untarred a binary tarball to ~/tarantool, say this: - <command>~/tarantool/bin/tarantool --init-storage</command> -#if you built from a source download, say this: - <command>~/tarantool/src/box/tarantool --init-storage</command></programlisting> -</para> - -<para> -Start the server. +2. Start the server. The server name is <computeroutput><filename>tarantool</filename></computeroutput>.<programlisting> #if you downloaded a binary with apt-get or yum, say this: <command>/usr/bin/tarantool</command> #if you downloaded and untarred a binary tarball to ~/tarantool, say this: <command>~/tarantool/bin/tarantool</command> #if you built from a source download, say this: - <command>~/tarantool/src/box/tarantool</command> </programlisting> + <command>~/tarantool/src/tarantool</command> </programlisting> +</para> + +<para> + The server starts in interactive mode and outputs a command prompt. + To turn on the database, configure it: +<programlisting>tarantool> box.cfg{admin_port=3313}</programlisting> + (this minimal example is sufficient). </para> <para> @@ -517,11 +469,13 @@ Now take the server down, with <programlisting><keycombo><keysym>Ctrl</keysym><k <para> Now start the server again. This time start it in the background.<programlisting> #if you downloaded a binary with apt-get or yum, say this: - <command>/usr/bin/tarantool --background</command> + <command>/usr/bin/tarantool</command> #if you downloaded and untarred a binary tarball to ~/tarantool, say this: - <command>~/tarantool/bin/tarantool --background</command> + <command>~/tarantool/bin/tarantool</command> #if you built from a source download, say this: - <command>~/tarantool/src/box/tarantool --background</command></programlisting> + <command>~/tarantool/src/box/tarantool</command> + <command>tarantool> box.cfg{admin_port=3313, background = true}</command> +</programlisting> </para> <para> @@ -536,28 +490,11 @@ Please follow instructions</olink> to find out how to manage Tarantool instances on your operating system. </para> -<note> -<para> - Alternatively, the server can be - started right out of the in-source build. Use the Tarantool - regression testing framework: - <programlisting><prompt>$ </prompt><command>./test/run</command> <option>--start-and-exit</option></programlisting> - It will create necessary files in directory - <filename>./test/var/</filename>, and start the server with - minimal configuration. -</para> -</note> <para> - Now that the server is up, you can start the client. The client name is tarantool.<programlisting> -#if you downloaded a binary with apt-get or yum, say this: - <command>/usr/bin/tarantool</command> -#if you downloaded and untarred a binary tarball to ~/tarantool, say this: - <command>~/tarantool/bin/tarantool</command> -#if you built from a source download on ~tarantool, say this: - <command>~/tarantool/client/tarantool/tarantool</command></programlisting> + Now that the server is up, you can connect to its administrative port.<programlisting> + <command>telnet 0 3313</command></programlisting> -If all goes well, a prompt will appear:<programlisting><prompt>localhost></prompt></programlisting> The client is waiting for the user to type instructions. </para> @@ -574,7 +511,6 @@ try this:<programlisting><prompt>localhost> </prompt><userinput>t = s:insert( <prompt>localhost> </prompt><userinput>t = s:insert({3, 'Length', 93})</userinput> </programlisting> - To select a tuple from the first space of the database, using the first defined key, try this:<programlisting><prompt>localhost> </prompt><userinput>s:select({3})</userinput></programlisting> @@ -617,7 +553,7 @@ To review ... If you followed all the instructions in this chapter, then so far you have: installed Tarantool from either a binary or a source repository, started up the Tarantool server, -inserted and selected tuples with the Tarantool client. +inserted and selected tuples. </para> </sidebar> diff --git a/doc/www-data.in/_layout/index b/doc/www-data.in/_layout/index index ad476f7a1f7da87a67f6721899f452f38802e0b0..c047f66c2474b5789e814abadddc429b9a7ddd57 100644 --- a/doc/www-data.in/_layout/index +++ b/doc/www-data.in/_layout/index @@ -1,5 +1,5 @@ {% extends "base" %} -{% set title = "Tarantool -- an in-memory NoSQL database" %} +{% set title = "Tarantool -- a NoSQL database in a Lua script" %} {% block content %} {{ index.main }} {% endblock content %} diff --git a/doc/www-data.in/_text/index.md b/doc/www-data.in/_text/index.md index d37ad199da8b1546afdb87cf15b0e2746fcd534f..cf11e157caa28f616ccf47e15fa513e711d9910d 100644 --- a/doc/www-data.in/_text/index.md +++ b/doc/www-data.in/_text/index.md @@ -2,38 +2,45 @@ index: main: | # Introduction - Tarantool is an in-memory database designed to store the most volatile - and highly accessible web content. Tarantool has been extensively used - in production since 2009. It's **open source**, BSD licensed. + Tarantool is a NoSQL database running inside a Lua program. It's + created to store and process the most volatile and highly accessible + Web data. Tarantool has been extensively used in production since 2009. + It's **open source**, BSD licensed. # Features + - a drop-in replacement for Lua 5.1, based on LuaJIT 2.0; + simply use *#!/usr/bin/tarantool* instead of *#!/usr/bin/lua* in your script, + - [MsgPack](http://msgpack.org) data format and MsgPack based client-server + protocol, + - two data engines: 100% in-memory with optional persistence and a + [2-level disk-based B-tree](http://sphia.org), to use with large data + sets, + - secondary key and index iterators support, + - asynchronous master-master replication, + - authentication and access control, - [lowest CPU overhead](benchmark.html) to store or serve a - piece of content, - - optional Write Ahead Logging for persistency and reliability, - - universal data access with [rich Lua stored - procedures](http://github.com/mailru/tntlua), which can exchange messages - between each other or networked peers, - - asynchronous master-slave replication and hot backup. + piece of content. # Get started ``` bash - # apt-get install tarantool tarantool-client - # cd /etc/tarantool - # cp instances.available/example.cfg instances.enabled/fqueue.cfg - # cd /usr/share/tarantool/lua - # wget http://github.com/mailru/tntlua/raw/master/fqueue.lua -O init.lua - # service tarantool start - tarantool: Staring instances - Starting 'fqueue' ... ok + # apt-get install tarantool + # tarantool + # tarantool> box.cfg{{admin_port=3313}} + # tarantool> myspace = box.schema.create_space('myspace') + # tarantool> myspace:create_index('primary') + # tarantool> tuple = {{ name = 'Tarantool', release = box.info.version, + # type = {{ 'NoSQL database', 'Lua interpreter'}}}} + # tarantool> myspace:auto_increment{{tuple}} + # - [1, {{'release': '1.6.1-445-ge8d3201', 'name': 'Tarantool' + # 'type': ['NoSQL database', 'Lua interpreter']}}] ``` - A fast and customizable message queue server is up and running. - # Learn more - [YCSB benchmark results](benchmark.html) - [FAQ](faq.html) - [Source repository](http://github.com/tarantool/tarantool) - - [Lua stored procedures repository]( http://github.com/mailru/tntlua) + - [Lua stored procedures repository](http://github.com/mailru/tntlua) + - [1.5 web site and downloads](http://stable.tarantool.org) diff --git a/doc/www-data.in/_text/intro.md b/doc/www-data.in/_text/intro.md index f58d167f76ed9ce23e102a107c4e14666596d220..3cd7ec3b3504c26d83f8ab3fa82f25294edb24b2 100644 --- a/doc/www-data.in/_text/intro.md +++ b/doc/www-data.in/_text/intro.md @@ -2,7 +2,8 @@ intro: main: | ## What is Tarantool? - Tarantool is an in-memory NoSQL database. The code is available + Tarantool is a NoSQL database running and a Lua application server. + The code is available for free under the terms of [BSD license]. Supported platforms are GNU/Linux, Mac OS and FreeBSD. diff --git a/doc/www-data.in/download.cmake b/doc/www-data.in/download.cmake index 46f990ba4708cd0240c3ed4bce0ff10dbf529bc0..0cf3c2adb527e9b70ab053f1056169b6ba701330 100644 --- a/doc/www-data.in/download.cmake +++ b/doc/www-data.in/download.cmake @@ -15,10 +15,10 @@ download: The version string may also contain a git revision id, to ease identification of the unqiue commit used to generate the build. - The current version of the stable branch is **@PACKAGE_VERSION@**. + The current version of the master branch is **@PACKAGE_VERSION@**. An automatic build system creates, tests and publishes packages - for every push into the stable branch. All binary packages contain + for every push into the master branch. All binary packages contain symbol information. Additionally, **-debug-** packages contain asserts and are compiled without optimization. @@ -47,7 +47,7 @@ download: It can be added to your apt sources list with: ```bash - wget http://tarantool.org/dist/master/public.key + wget http://tarantool.org/dist/public.key sudo apt-key add ./public.key release=`lsb_release -c -s` @@ -60,11 +60,11 @@ download: # For Ubuntu: cat > /etc/apt/sources.list.d/tarantool.list <<- EOF deb http://tarantool.org/dist/master/ubuntu/ $release main - deb-src http://tarantool.org/dist/mater/ubuntu/ $release main + deb-src http://tarantool.org/dist/master/ubuntu/ $release main EOF sudo apt-get update - sudo apt-get install tarantool tarantool-client + sudo apt-get install tarantool ``` ### CentOS 5-6 and RHEL 5-6 @@ -110,19 +110,6 @@ download: [layman]: http://wiki.gentoo.org/wiki/Layman - ### Other Linux distributions - <table border=1 title="Download the latest build, @PACKAGE_VERSION@" width=100%> - <th colspan=3>Static builds for Linux</th> - <tr> - <td> Binary tarball (**.tar.gz**) </td> - <td align=center> [32-bit] </td> - <td align=center> [64-bit] </td> - </tr> - </table> - - [32-bit]: http://tarantool.org/dist/master/tarantool-@PACKAGE_VERSION@-linux-i686.tar.gz - [64-bit]: http://tarantool.org/dist/master/tarantool-@PACKAGE_VERSION@-linux-x86_64.tar.gz - ### FreeBSD Tarantool is available from the FreeBSD Ports collection @@ -142,27 +129,27 @@ download: [Apple Developer]: https://developer.apple.com/downloads/ - # Development branch + # Old master branch - In the same manner as for [the stable branch][stable], every push into - [the master branch][master] is [available online][builds-m]. - The server roadmap is maintained on [Github][issues]. + In the same manner as for [the master branch][master], every push into + [the old master][stable] is [available online][builds-s]. + The server bugs database is maintained on [Github][issues]. [stable]: http://github.com/tarantool/tarantool/tree/stable [master]: http://github.com/tarantool/tarantool/tree/master - [builds-m]: http://tarantool.org/dist/master + [builds-s]: http://tarantool.org/dist/stable [issues]: http://github.com/tarantool/tarantool/issues ## Connectors - - Perl driver, [DR:Tarantool](http://search.cpan.org/~unera/DR-Tarantool-0.37/lib/DR/Tarantool.pm) + - Perl driver, [DR:Tarantool](http://search.cpan.org/~unera/DR-Tarantool-0.42/lib/DR/Tarantool.pm) - Java driver, [Maven repository](http://dgreenru.github.com/tarantool-java) - Ruby driver, [https://github.com/mailru/tarantool-ruby] - Python driver, [http://pypi.python.org/pypi/tarantool] - PHP driver, [https://github.com/tarantool/tarantool-php] - node.js driver, [https://github.com/devgru/node-tarantool] - Erlang driver, [https://github.com/rtsisyk/etarantool] - - C connector [is maintained in the server source tree](https://github.com/tarantool/tarantool/blob/master/connector/c) + - C connector [https://github.com/tarantool/tarantool-c] [http://tarantool.org/dist/master]: http://tarantool.org/dist/master [http://tarantool.org/dist/master/debian]: http://tarantool.org/dist/master/debian diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be7eb5ba1dcd1ededc9a9fc97614d68a407876d2..83c0aef69da56967490b50c19a29e58d00382f3e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,7 +152,11 @@ set(TARANTOOL_CXX_FLAGS ${CMAKE_CXX_FLAGS} PARENT_SCOPE) add_executable(tarantool tarantool.cc) add_dependencies(tarantool build_bundled_libs) -target_link_libraries(tarantool box ${common_libraries} -rdynamic) +target_link_libraries(tarantool + box + ${sophia_lib} + ${common_libraries} + -rdynamic) if (module_link_flags) set_target_properties(tarantool PROPERTIES diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index beea2c89dd5bd085e846421e1e26ccb9ef4f4fe1..600f848a2bc544640eee935a9a8ea2325f653719 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -4,6 +4,8 @@ endif() file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src/box/lua) +include_directories(${SOPHIA_INCLUDE_DIR}) + set(lua_sources) lua_source(lua_sources lua/schema.lua) lua_source(lua_sources lua/box.lua) @@ -27,6 +29,8 @@ add_library(box bitset_index.cc engine.cc engine_memtx.cc + engine_sophia.cc + sophia_index.cc space.cc alter.cc schema.cc @@ -42,4 +46,3 @@ add_library(box lua/slab.cc lua/index.cc lua/space.cc) - diff --git a/src/box/alter.cc b/src/box/alter.cc index f19e311d4c450c31e43845953da6d069074758b3..aec77035a1e5d7d81ecda2b3d535f7646ddc24fb 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -596,11 +596,7 @@ DropIndex::commit(struct alter_space *alter) Index *pk = index_find(alter->old_space, 0); if (pk == NULL) return; - struct iterator *it = pk->position(); - pk->initIterator(it, ITER_ALL, NULL, 0); - struct tuple *tuple; - while ((tuple = it->next(it))) - tuple_ref(tuple, -1); + alter->old_space->engine->factory->dropIndex(pk); } /** Change non-essential (no data change) properties of an index. */ diff --git a/src/box/box.cc b/src/box/box.cc index 4952ee201d197be84b27c543544d76352f8741a4..ae93421c29fe0eb0e76484e2101c0c6904fea6e8 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -46,6 +46,7 @@ #include "schema.h" #include "engine.h" #include "engine_memtx.h" +#include "engine_sophia.h" #include "space.h" #include "port.h" #include "request.h" @@ -315,6 +316,10 @@ engine_init() { MemtxFactory *memtx = new MemtxFactory(); engine_register(memtx); + + SophiaFactory *sophia = new SophiaFactory(); + sophia->init(); + engine_register(sophia); } void diff --git a/src/box/engine.cc b/src/box/engine.cc index 578e5ca00164c559171399dba09d1d136537629d..8efcc17516af982092311fe2c3456bc6b2b20d90 100644 --- a/src/box/engine.cc +++ b/src/box/engine.cc @@ -46,6 +46,12 @@ void EngineFactory::init() void EngineFactory::shutdown() {} +void EngineFactory::txnFinish(struct txn*) +{} + +void EngineFactory::recoveryEvent(enum engine_recovery_event) +{} + Engine::Engine(EngineFactory *f) :factory(f) { diff --git a/src/box/engine.h b/src/box/engine.h index fcb2462fd79e1181f1f9d06b60a5277e892fdb1e..21c586c41994540fc13e3123b4a1f28d9280b368 100644 --- a/src/box/engine.h +++ b/src/box/engine.h @@ -58,6 +58,15 @@ enum engine_recovery_state { READY_ALL_KEYS }; +/** + * Engine specific recovery events that represents + * global recovery stage change. + */ +enum engine_recovery_event { + END_RECOVERY_SNAPSHOT, + END_RECOVERY +}; + typedef void (*engine_recover_f)(struct space*); typedef struct tuple * @@ -83,7 +92,7 @@ class EngineFactory: public Object { virtual ~EngineFactory() {} /** Called once at startup. */ virtual void init(); - /** Called at server shutdown */ + /** Called at server shutdown. */ virtual void shutdown(); /** Create a new engine instance for a space. */ virtual Engine *open() = 0; @@ -92,6 +101,19 @@ class EngineFactory: public Object { * space. */ virtual Index *createIndex(struct key_def*) = 0; + /* + * Delete all tuples in the index on drop. + */ + virtual void dropIndex(Index*) = 0; + /** + * Check a key definition for violation of + * various limits. + */ + virtual void keydefCheck(struct key_def *key_def) = 0; + /* Clean transaction engine resources. */ + virtual void txnFinish(struct txn *txn); + /* Inform engine about a recovery stage change. */ + virtual void recoveryEvent(enum engine_recovery_event); public: /** Name of the engine. */ const char *name; @@ -100,7 +122,7 @@ class EngineFactory: public Object { struct rlist link; }; -/** Engine handle - an operator of a space */ +/** Engine handle - an operator of a space */ struct Engine: public Object { public: diff --git a/src/box/engine_memtx.cc b/src/box/engine_memtx.cc index f99d06b0a20ef0c86d202e1fa3af53e3cbee2a10..cb8fab1c7d87b54c46117546c8029133787ae275 100644 --- a/src/box/engine_memtx.cc +++ b/src/box/engine_memtx.cc @@ -46,7 +46,7 @@ struct Memtx: public Engine { virtual ~Memtx() { /* do nothing */ - /* engine->close(this); */ + /* factory->close(this); */ } }; @@ -62,6 +62,7 @@ struct Memtx: public Engine { * 2) when all XLOGs are loaded: * recover = space_build_all_keys */ + static inline void memtx_recovery_prepare(struct engine_recovery *r) { @@ -76,6 +77,19 @@ MemtxFactory::MemtxFactory() memtx_recovery_prepare(&recovery); } +void +MemtxFactory::recoveryEvent(enum engine_recovery_event event) +{ + switch (event) { + case END_RECOVERY_SNAPSHOT: + recovery.recover = space_build_primary_key; + break; + case END_RECOVERY: + recovery.recover = space_build_all_keys; + break; + } +} + Engine *MemtxFactory::open() { return new Memtx(this); @@ -96,3 +110,50 @@ MemtxFactory::createIndex(struct key_def *key_def) return NULL; } } + +void +MemtxFactory::dropIndex(Index *index) +{ + struct iterator *it = index->position(); + index->initIterator(it, ITER_ALL, NULL, 0); + struct tuple *tuple; + while ((tuple = it->next(it))) + tuple_ref(tuple, -1); +} + +void +MemtxFactory::keydefCheck(struct key_def *key_def) +{ + switch (key_def->type) { + case HASH: + if (! key_def->is_unique) { + tnt_raise(ClientError, ER_MODIFY_INDEX, + (unsigned) key_def->iid, + (unsigned) key_def->space_id, + "HASH index must be unique"); + } + break; + case TREE: + /* TREE index has no limitations. */ + break; + case BITSET: + if (key_def->part_count != 1) { + tnt_raise(ClientError, ER_MODIFY_INDEX, + (unsigned) key_def->iid, + (unsigned) key_def->space_id, + "BITSET index key can not be multipart"); + } + if (key_def->is_unique) { + tnt_raise(ClientError, ER_MODIFY_INDEX, + (unsigned) key_def->iid, + (unsigned) key_def->space_id, + "BITSET can not be unique"); + } + break; + default: + tnt_raise(ClientError, ER_INDEX_TYPE, + (unsigned) key_def->iid, + (unsigned) key_def->space_id); + break; + } +} diff --git a/src/box/engine_memtx.h b/src/box/engine_memtx.h index 14b8871fc2e361ce34882119af795e9cac80daad..e3ea0c0fa41094536414a4f445c453eeac4e2dfe 100644 --- a/src/box/engine_memtx.h +++ b/src/box/engine_memtx.h @@ -33,6 +33,9 @@ struct MemtxFactory: public EngineFactory { MemtxFactory(); virtual Engine *open(); virtual Index *createIndex(struct key_def *key_def); + virtual void dropIndex(Index *index); + virtual void keydefCheck(struct key_def *key_def); + virtual void recoveryEvent(enum engine_recovery_event event); }; #endif /* TARANTOOL_BOX_ENGINE_MEMTX_H_INCLUDED */ diff --git a/src/box/engine_sophia.cc b/src/box/engine_sophia.cc new file mode 100644 index 0000000000000000000000000000000000000000..3a06c76c0582600a10716d9c40cd508cd6cfa791 --- /dev/null +++ b/src/box/engine_sophia.cc @@ -0,0 +1,180 @@ +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "txn.h" +#include "tuple.h" +#include "engine.h" +#include "engine_sophia.h" +#include "index.h" +#include "sophia_index.h" +#include "space.h" +#include "exception.h" +#include "salad/rlist.h" +#include <sophia.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <errno.h> + +struct Sophia: public Engine { + Sophia(EngineFactory*); +}; + +Sophia::Sophia(EngineFactory *e) + :Engine(e) +{ } + +static struct tuple * +sophia_replace_noop(struct space*, + struct tuple*, struct tuple*, + enum dup_replace_mode) +{ + return NULL; +} + +static void +sophia_end_build_primary_key(struct space *space) +{ + engine_recovery *r = &space->engine->recovery; + /* enable replace */ + r->state = READY_ALL_KEYS; + r->replace = space_replace_primary_key; + r->recover = space_noop; +} + +static void +sophia_begin_build_primary_key(struct space *space) +{ + engine_recovery *r = &space->engine->recovery; + r->replace = sophia_replace_noop; + r->recover = sophia_end_build_primary_key; +} + +static inline void +sophia_recovery_prepare(struct engine_recovery *r) +{ + r->state = READY_NO_KEYS; + r->recover = sophia_begin_build_primary_key; + r->replace = space_replace_no_keys; +} + +SophiaFactory::SophiaFactory() + :EngineFactory("sophia") +{ + sophia_recovery_prepare(&recovery); +} + +void +SophiaFactory::init() +{ + int rc = mkdir("sophia", 0755); + + if (rc == -1 && errno != EEXIST) { + say_error("failed to create directory: 'sophia', %d, %s", + errno, strerror(errno)); + } +} + +Engine* +SophiaFactory::open() +{ + return new Sophia(this); +} + +void +SophiaFactory::recoveryEvent(enum engine_recovery_event event) +{ + switch (event) { + case END_RECOVERY_SNAPSHOT: + recovery.replace = sophia_replace_noop; + break; + case END_RECOVERY: + recovery.state = READY_NO_KEYS; + recovery.replace = space_replace_primary_key; + recovery.recover = space_noop; + break; + } +} + +Index* +SophiaFactory::createIndex(struct key_def *key_def) +{ + switch (key_def->type) { + case TREE: return new SophiaIndex(key_def); + default: + assert(false); + return NULL; + } +} + +void +SophiaFactory::dropIndex(Index *index) +{ + (void)index; +} + +void +SophiaFactory::keydefCheck(struct key_def *key_def) +{ + switch (key_def->type) { + case TREE: + if (! key_def->is_unique) { + tnt_raise(ClientError, ER_MODIFY_INDEX, + (unsigned) key_def->iid, + (unsigned) key_def->space_id, + "Sophia TREE index must be unique"); + } + if (key_def->iid != 0) { + tnt_raise(ClientError, ER_MODIFY_INDEX, + (unsigned) key_def->iid, + (unsigned) key_def->space_id, + "Sophia TREE secondary indexes are not supported"); + } + if (key_def->part_count != 1) { + tnt_raise(ClientError, ER_MODIFY_INDEX, + (unsigned) key_def->iid, + (unsigned) key_def->space_id, + "Sophia TREE index key can not be multipart"); + } + break; + default: + tnt_raise(ClientError, ER_INDEX_TYPE, + (unsigned) key_def->iid, + (unsigned) key_def->space_id); + break; + } +} + +void +SophiaFactory::txnFinish(struct txn *txn) +{ + if (txn->new_tuple) + tuple_ref(txn->new_tuple, -1); +} diff --git a/src/box/engine_sophia.h b/src/box/engine_sophia.h new file mode 100644 index 0000000000000000000000000000000000000000..c4320ada4517af084c519315d18786347262d9e0 --- /dev/null +++ b/src/box/engine_sophia.h @@ -0,0 +1,43 @@ +#ifndef TARANTOOL_BOX_ENGINE_SOPHIA_H_INCLUDED +#define TARANTOOL_BOX_ENGINE_SOPHIA_H_INCLUDED +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct SophiaFactory: public EngineFactory { + SophiaFactory(); + virtual void init(); + virtual Engine *open(); + virtual Index *createIndex(struct key_def *key_def); + virtual void dropIndex(Index *index); + virtual void keydefCheck(struct key_def *key_def); + virtual void txnFinish(struct txn *txn); + virtual void recoveryEvent(enum engine_recovery_event event); +}; + +#endif /* TARANTOOL_BOX_ENGINE_SOPHIA_H_INCLUDED */ diff --git a/src/box/index.cc b/src/box/index.cc index 4860452c3ea492598dd5419c8e77ba9a3d040cfa..13f33bc962b97ffa001b0de7ce8b2f0bf648a039 100644 --- a/src/box/index.cc +++ b/src/box/index.cc @@ -27,6 +27,11 @@ * SUCH DAMAGE. */ #include "index.h" +#include "hash_index.h" +#include "tree_index.h" +#include "bitset_index.h" +#include "sophia_index.h" +#include "tuple.h" #include "say.h" #include "exception.h" diff --git a/src/box/index.h b/src/box/index.h index 862caa578178aa0248626f1ca0c3c3fef520d8c2..6adb06236138fd1ba60e85e684329b81bfb26f32 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -83,8 +83,15 @@ iterator_type_is_reverse(enum iterator_type type) struct iterator { struct tuple *(*next)(struct iterator *); void (*free)(struct iterator *); + void (*close)(struct iterator *); }; +static inline void +iterator_close(struct iterator *it) { + if (it->close) + it->close(it); +} + /** * Check that the key has correct part count and correct part size * for use in an index iterator. @@ -142,6 +149,11 @@ class Index: public Object { */ Index(struct key_def *key_def); + /* + * Pre-allocated iterator to speed up the main case of + * box_process(). Should not be used elsewhere. + */ + struct iterator *m_position; public: virtual ~Index(); @@ -180,12 +192,6 @@ class Index: public Object { m_position = allocIterator(); return m_position; } -private: - /* - * Pre-allocated iterator to speed up the main case of - * box_process(). Should not be used elsewhere. - */ - struct iterator *m_position; }; /** diff --git a/src/box/key_def.cc b/src/box/key_def.cc index 57a396eb3f3b9548b3877ca09cb24097dd96cda0..78cc0c0eed2bd8eacfc807403c3e6cc35d6cb7f3 100644 --- a/src/box/key_def.cc +++ b/src/box/key_def.cc @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ #include "key_def.h" +#include "space.h" +#include "schema.h" #include <stdlib.h> #include <stdio.h> #include "exception.h" @@ -184,38 +186,11 @@ key_def_check(struct key_def *key_def) } } } - switch (key_def->type) { - case HASH: - if (! key_def->is_unique) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - (unsigned) key_def->iid, - (unsigned) key_def->space_id, - "HASH index must be unique"); - } - break; - case TREE: - /* TREE index has no limitations. */ - break; - case BITSET: - if (key_def->part_count != 1) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - (unsigned) key_def->iid, - (unsigned) key_def->space_id, - "BITSET index key can not be multipart"); - } - if (key_def->is_unique) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - (unsigned) key_def->iid, - (unsigned) key_def->space_id, - "BITSET can not be unique"); - } - break; - default: - tnt_raise(ClientError, ER_INDEX_TYPE, - (unsigned) key_def->iid, - (unsigned) key_def->space_id); - break; - } + struct space *space = + space_cache_find(key_def->space_id); + + /* validate key_def->type */ + space->engine->factory->keydefCheck(key_def); } void diff --git a/src/box/key_def.h b/src/box/key_def.h index 1b45972719b9d6ebb170a428394885aab81ce482..de837c8d66e69373cdf5ffe63a21fbd3a81e0997 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -194,9 +194,7 @@ key_list_del_key(struct rlist *key_list, uint32_t id); /** * Check a key definition for violation of various limits. * - * @param id space id * @param key_def key_def - * @param type_str type name (to produce a nice error) */ void key_def_check(struct key_def *key_def); diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index a2e50ed5ee838f860cd4d81bc1297e924a659b75..00346e1cfbd606121a979316549ac17ca50bac26 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -8,6 +8,7 @@ ffi.cdef[[ struct iterator { struct tuple *(*next)(struct iterator *); void (*free)(struct iterator *); + void (*close)(struct iterator *); }; struct iterator * boxffi_index_iterator(uint32_t space_id, uint32_t index_id, int type, diff --git a/src/box/request.cc b/src/box/request.cc index 21bee5b6e782059e11aad5b2b97e2b6fd539afc1..b17eb91e68faa344693a3e4002832a8ac8646482 100644 --- a/src/box/request.cc +++ b/src/box/request.cc @@ -199,6 +199,8 @@ execute_select(struct request *request, struct txn *txn, struct port *port) struct iterator *it = index->position(); key_validate(index->key_def, type, key, part_count); index->initIterator(it, type, key, part_count); + auto iterator_guard = + make_scoped_guard([=] { iterator_close(it); }); struct tuple *tuple; while ((tuple = it->next(it)) != NULL) { diff --git a/src/box/schema.cc b/src/box/schema.cc index fb38919620f258ee44e4126726f4760bc8adb879..e93d744b4a28d764fbbe9916eccc54db378b7a63 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -303,7 +303,7 @@ static inline void space_end_recover_snapshot_cb(EngineFactory *f, void *udate) { (void)udate; - f->recovery.recover = space_build_primary_key; + f->recoveryEvent(END_RECOVERY_SNAPSHOT); } void @@ -328,7 +328,7 @@ static inline void space_end_recover_cb(EngineFactory *f, void *udate) { (void)udate; - f->recovery.recover = space_build_all_keys; + f->recoveryEvent(END_RECOVERY); } void diff --git a/src/box/sophia_index.cc b/src/box/sophia_index.cc new file mode 100644 index 0000000000000000000000000000000000000000..642e9439d105dcffb4702ed20155598e13f2cbab --- /dev/null +++ b/src/box/sophia_index.cc @@ -0,0 +1,355 @@ +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sophia_index.h" +#include "say.h" +#include "tuple.h" +#include "pickle.h" +#include "scoped_guard.h" +#include "exception.h" +#include "errinj.h" + +#include "schema.h" +#include "space.h" + +#include <sophia.h> +#include <stdio.h> + +static inline int +sophia_index_compare(char *a, size_t asz __attribute__((unused)), + char *b, size_t bsz __attribute__((unused)), + void *arg) +{ + struct key_def *key_def = (struct key_def*)arg; + + int rc = tuple_compare_field(a, b, key_def->parts[0].type); + return (rc == 0) ? 0 : + ((rc > 0) ? 1 : -1); +} + +static struct tuple * +sophia_gettuple(void *db, const char *key, size_t keysize) +{ + size_t valuesize = 0; + char *value = NULL; + int rc = sp_get(db, key, keysize, (void**)&value, &valuesize); + if (rc == -1) + tnt_raise(ClientError, ER_SOPHIA, sp_error(db)); + if (rc == 0) + return NULL; + auto scoped_guard = make_scoped_guard([=] { free(value); }); + struct tuple *ret = + tuple_new(tuple_format_ber, value, value + valuesize); + tuple_ref(ret, 1); + return ret; +} + +/* {{{ SophiaIndex */ + +SophiaIndex::SophiaIndex(struct key_def *key_def_arg __attribute__((unused))) + : Index(key_def_arg) +{ + env = sp_env(); + if (env == NULL) + tnt_raise(ClientError, ER_MEMORY_ISSUE, sizeof(void*), + "SophiaIndex", "env"); + + auto env_freer = + make_scoped_guard([=] { sp_destroy(env); }); + + int rc = sp_ctl(env, SPCMP, sophia_index_compare, key_def); + if (rc == -1) + tnt_raise(ClientError, ER_SOPHIA, sp_error(env)); + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "sophia/%04d", key_def->space_id); + rc = sp_ctl(env, SPDIR, SPO_RDWR|SPO_CREAT, path); + if (rc == -1) + tnt_raise(ClientError, ER_SOPHIA, sp_error(env)); + + say_info("start sophia space '%s' recover", path); + + db = sp_open(env); + if (db == NULL) + tnt_raise(ClientError, ER_SOPHIA, sp_error(env)); + + say_info("recover complete"); + + env_freer.is_active = false; +} + +SophiaIndex::~SophiaIndex() +{ + if (m_position != NULL) { + m_position->free(m_position); + m_position = NULL; + } + + if (db) { + int rc = sp_destroy(db); + if (rc == -1) + say_info("sophia space %d close error: %s", key_def->space_id, + sp_error(env)); + } + if (env) { + sp_destroy(env); + } +} + +void +SophiaIndex::endBuild() +{ +} + +size_t +SophiaIndex::size() const +{ + return 0; +} + +size_t +SophiaIndex::memsize() const +{ + return 0; +} + +struct tuple * +SophiaIndex::findByKey(const char *key, uint32_t part_count) const +{ + assert(part_count == 1); + assert(key_def->is_unique && part_count == key_def->part_count); + const char *keyptr = key; + mp_next(&keyptr); + size_t keysize = keyptr - key; + struct tuple *ret = sophia_gettuple(db, key, keysize); + return ret; +} + +static inline uint32_t +sophia_check_dup(struct key_def *key_def, + struct tuple *old_tuple, + struct tuple *dup_tuple, enum dup_replace_mode mode) +{ + if (dup_tuple == NULL) { + if (mode == DUP_REPLACE) { + /* + * dup_replace_mode is DUP_REPLACE, and + * a tuple with the same key is not found. + */ + return ER_TUPLE_NOT_FOUND; + } + } else { /* dup_tuple != NULL */ + + int equal = old_tuple != NULL && + tuple_compare(dup_tuple, old_tuple, key_def) == 0; + + if (!equal && (old_tuple != NULL || mode == DUP_INSERT)) { + /* + * There is a duplicate of new_tuple, + * and it's not old_tuple: we can't + * possibly delete more than one tuple + * at once. + */ + return ER_TUPLE_FOUND; + } + } + return 0; +} + +struct tuple * +SophiaIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple, + enum dup_replace_mode mode) +{ + if (new_tuple) { + assert(new_tuple->refs == 0); + + const char *key = tuple_field(new_tuple, key_def->parts[0].fieldno); + const char *keyptr = key; + mp_next(&keyptr); + size_t keysize = keyptr - key; + + struct tuple *dup_tuple = sophia_gettuple(db, key, keysize); + + uint32_t errcode = + sophia_check_dup(key_def, old_tuple, dup_tuple, mode); + if (errcode) { + if (dup_tuple) + tuple_ref(dup_tuple, -1); + tnt_raise(ClientError, errcode, index_id(this)); + } + + int rc = sp_set(db, key, keysize, new_tuple->data, new_tuple->bsize); + if (rc == -1) { + if (dup_tuple) + tuple_ref(dup_tuple, -1); + tnt_raise(ClientError, ER_SOPHIA, sp_error(db)); + } + + if (dup_tuple) + return dup_tuple; + } + + if (old_tuple) { + /* delete */ + const char *key = tuple_field(old_tuple, key_def->parts[0].fieldno); + const char *keyptr = key; + mp_next(&keyptr); + size_t keysize = keyptr - key; + int rc = sp_delete(db, key, keysize); + if (rc == -1) + tnt_raise(ClientError, ER_SOPHIA, sp_error(db)); + } + + return old_tuple; +} + +struct sophia_iterator { + struct iterator base; + const char *key; + int keysize; + uint32_t part_count; + void *db; + void *cursor; +}; + +void +sophia_iterator_free(struct iterator *ptr) +{ + assert(ptr->free == sophia_iterator_free); + struct sophia_iterator *it = (struct sophia_iterator *) ptr; + if (it->cursor) + sp_destroy(it->cursor); + free(ptr); +} + +void +sophia_iterator_close(struct iterator *ptr) +{ + assert(ptr->free == sophia_iterator_free); + struct sophia_iterator *it = (struct sophia_iterator *) ptr; + if (it->cursor) { + sp_destroy(it->cursor); + it->cursor = NULL; + } +} + +struct tuple * +sophia_iterator_next(struct iterator *ptr) +{ + assert(ptr->next == sophia_iterator_next); + struct sophia_iterator *it = (struct sophia_iterator *) ptr; + assert(it->cursor != NULL); + int rc = sp_fetch(it->cursor); + if (rc == 0) + return NULL; + size_t valuesize = sp_valuesize(it->cursor); + const char *value = sp_value(it->cursor); + struct tuple *ret = + tuple_new(tuple_format_ber, value, value + valuesize); + tuple_ref(ret, 1); + return ret; +} + +struct tuple * +sophia_iterator_last(struct iterator *ptr __attribute__((unused))) +{ + return NULL; +} + +struct tuple * +sophia_iterator_eq(struct iterator *ptr) +{ + ptr->next = sophia_iterator_last; + struct sophia_iterator *it = (struct sophia_iterator *) ptr; + assert(it->cursor == NULL); + return sophia_gettuple(it->db, it->key, it->keysize); +} + +struct iterator * +SophiaIndex::allocIterator() const +{ + struct sophia_iterator *it = + (struct sophia_iterator *) calloc(1, sizeof(*it)); + if (it == NULL) { + tnt_raise(ClientError, ER_MEMORY_ISSUE, + sizeof(struct sophia_iterator), "SophiaIndex", + "iterator"); + } + it->base.next = sophia_iterator_next; + it->base.close = sophia_iterator_close; + it->base.free = sophia_iterator_free; + it->cursor = NULL; + return (struct iterator *) it; +} + +void +SophiaIndex::initIterator(struct iterator *ptr, enum iterator_type type, + const char *key, uint32_t part_count) const +{ + assert(part_count <= 1); + + struct sophia_iterator *it = (struct sophia_iterator *) ptr; + assert(it->cursor == NULL); + + size_t keysize; + if (part_count > 0) { + const char *keyptr = key; + mp_next(&keyptr); + keysize = keyptr - key; + } else { + keysize = 0; + key = NULL; + } + it->key = key; + it->keysize = keysize; + it->part_count = part_count; + it->db = db; + + sporder compare; + switch (type) { + case ITER_EQ: it->base.next = sophia_iterator_eq; + return; + case ITER_ALL: + case ITER_GE: compare = SPGTE; + break; + case ITER_GT: compare = SPGT; + break; + case ITER_LE: compare = SPLTE; + break; + case ITER_LT: compare = SPLT; + break; + default: + tnt_raise(ClientError, ER_UNSUPPORTED, + "SophiaIndex", "requested iterator type"); + } + it->cursor = sp_cursor(db, compare, key, keysize); + if (it->cursor == NULL) + tnt_raise(ClientError, ER_SOPHIA, sp_error(db)); +} + +/* }}} */ diff --git a/src/box/sophia_index.h b/src/box/sophia_index.h new file mode 100644 index 0000000000000000000000000000000000000000..547f5ef455ebe548fa0a0f2c3e8343ebdca321cb --- /dev/null +++ b/src/box/sophia_index.h @@ -0,0 +1,58 @@ +#ifndef TARANTOOL_BOX_SOPHIA_INDEX_H_INCLUDED +#define TARANTOOL_BOX_SOPHIA_INDEX_H_INCLUDED +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "index.h" + +class SophiaIndex: public Index { +public: + SophiaIndex(struct key_def *key_def); + ~SophiaIndex(); + + virtual size_t size() const; + virtual void endBuild(); + + virtual struct tuple *findByKey(const char *key, uint32_t part_count) const; + virtual struct tuple *replace(struct tuple *old_tuple, + struct tuple *new_tuple, + enum dup_replace_mode mode); + + virtual struct iterator *allocIterator() const; + virtual void initIterator(struct iterator *iterator, + enum iterator_type type, + const char *key, uint32_t part_count) const; + virtual size_t memsize() const; + +protected: + void *env; + void *db; +}; + +#endif /* TARANTOOL_BOX_SOPHIA_INDEX_H_INCLUDED */ diff --git a/src/box/space.h b/src/box/space.h index 2ea00cfa4c5bfa5ca2b09f4b199abfd8951eeff5..7999a4b06205fec7fd00651e7d4aec1e35e93984 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -189,10 +189,14 @@ space_replace(struct space *space, struct tuple *old_tuple, struct tuple * space_replace_no_keys(struct space*, struct tuple*, struct tuple*, enum dup_replace_mode); +struct tuple * +space_replace_primary_key(struct space*, struct tuple*, struct tuple*, + enum dup_replace_mode); void space_begin_build_primary_key(struct space *space); void space_build_primary_key(struct space *space); void space_build_all_keys(struct space *space); +void space_noop(struct space *space); uint32_t space_size(struct space *space); diff --git a/src/box/tuple.cc b/src/box/tuple.cc index c509a545a0ec1aee392128070af68699d2fb8ff4..bcb1eb0ff3171c80514a5924e222da861b1e592a 100644 --- a/src/box/tuple.cc +++ b/src/box/tuple.cc @@ -428,7 +428,7 @@ tuple_new(struct tuple_format *format, const char *data, const char *end) inline __attribute__((always_inline)) int mp_compare_uint(const char **data_a, const char **data_b); -static inline int +int tuple_compare_field(const char *field_a, const char *field_b, enum field_type type) { diff --git a/src/box/tuple.h b/src/box/tuple.h index 0f94a4c0a1053cc956cf2e9e66b887dbe23a8bab..e766bd668f82ef52283e9f997e16efd0499c28f0 100644 --- a/src/box/tuple.h +++ b/src/box/tuple.h @@ -391,6 +391,19 @@ tuple_update(struct tuple_format *new_format, const struct tuple *old_tuple, const char *expr, const char *expr_end); +/** + * @brief Compare two tuple fields using using field type definition + * @param field_a field + * @param field_b field + * @param field_type field type definition + * @retval 0 if field_a == field_b + * @retval <0 if field_a < field_b + * @retval >0 if field_a > field_b + */ +int +tuple_compare_field(const char *field_a, const char *field_b, + enum field_type type); + /** * @brief Compare two tuples using field by field using key definition * @param tuple_a tuple diff --git a/src/box/txn.cc b/src/box/txn.cc index 622a6550606f618524c35ea1e7d951f44e6b52c7..62831885d7e9593511f99738afe0375ff8da6887 100644 --- a/src/box/txn.cc +++ b/src/box/txn.cc @@ -130,6 +130,8 @@ txn_finish(struct txn *txn) { if (txn->old_tuple) tuple_ref(txn->old_tuple, -1); + if (txn->space) + txn->space->engine->factory->txnFinish(txn); TRASH(txn); } diff --git a/src/box/txn.h b/src/box/txn.h index e2e22bbb4d29eaafaadeb53133883029db723c05..c67d6ad687dde949a47532613aa9b8df02567fa4 100644 --- a/src/box/txn.h +++ b/src/box/txn.h @@ -56,4 +56,5 @@ void txn_replace(struct txn *txn, struct space *space, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode); void txn_add_redo(struct txn *txn, struct request *request); + #endif /* TARANTOOL_BOX_TXN_H_INCLUDED */ diff --git a/src/errcode.h b/src/errcode.h index 41476d99f71be24b1cf0fadc37ed805c2d3d19be..586bb944a02de0872bd07424a31ab22e37fd0809 100644 --- a/src/errcode.h +++ b/src/errcode.h @@ -107,8 +107,9 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 55 */_(ER_SPACE_ACCESS_DENIED, 2, "%s access denied for user '%s' to space '%s'") \ /* 56 */_(ER_USER_MAX, 2, "A limit on the total number of users has been reached: %u") \ /* 57 */_(ER_NO_SUCH_ENGINE, 2, "Space engine '%s' does not exist") \ - /* 57 */_(ER_RELOAD_CFG, 2, "Can't set option '%s' dynamically") \ - /* 57 */_(ER_CFG, 2, "Incorrect option value: %s") \ + /* 58 */_(ER_RELOAD_CFG, 2, "Can't set option '%s' dynamically") \ + /* 59 */_(ER_CFG, 2, "Incorrect option value: %s") \ + /* 60 */_(ER_SOPHIA, 2, "%s") \ /* diff --git a/test/big/lua.result b/test/big/lua.result index c84bab07982137e1eeb78874d1692c702301ebaf..3b334151f611623824dbc6301d077b6ce7bcfe5e 100644 --- a/test/big/lua.result +++ b/test/big/lua.result @@ -472,7 +472,7 @@ t = {} ... index:pairs('sid_t', { iterator = 'wrong_iterator_type' }) --- -- error: '[string "-- schema.lua (internal file)..."]:324: Wrong iterator type: wrong_iterator_type' +- error: '[string "-- schema.lua (internal file)..."]:325: Wrong iterator type: wrong_iterator_type' ... index = nil --- diff --git a/test/box/misc.result b/test/box/misc.result index c67e1939055ab2f237077e577bb2672908c11636..a6c0f62361a4bd710eb261e607e3f9d3ee525da8 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -196,6 +196,7 @@ t; - 'box.error.ER_NO_SUCH_INDEX : 35' - 'box.error.ER_TUPLE_FOUND : 3' - 'box.error.ER_CREATE_SPACE : 9' + - 'box.error.ER_PROC_RET : 21' - 'box.error.ER_TUPLE_FORMAT_LIMIT : 16' - 'box.error.ER_FIELD_TYPE : 23' - 'box.error.ER_CFG : 59' @@ -247,7 +248,7 @@ t; - 'box.error.ER_NO_SUCH_PROC : 33' - 'box.error.ER_SPACE_EXISTS : 10' - 'box.error.ER_PROC_LUA : 32' - - 'box.error.ER_PROC_RET : 21' + - 'box.error.ER_SOPHIA : 60' - 'box.error.ER_NO_SUCH_TRIGGER : 34' - 'box.error.ER_TUPLE_IS_TOO_LONG : 27' - 'box.error.ER_SPLICE : 25' diff --git a/test/box/sophia.result b/test/box/sophia.result new file mode 100644 index 0000000000000000000000000000000000000000..7cae8cef6e6fc90c5528fb2ef51db96264e78d82 --- /dev/null +++ b/test/box/sophia.result @@ -0,0 +1,109 @@ +space = box.schema.create_space('tweedledum', { id = 123, engine = 'sophia' }) +--- +... +space:create_index('primary', { type = 'tree', parts = {0, 'num'} }) +--- +... +for v=1, 10 do space:insert({v}) end +--- +... +t = space.index[0]:select({}, {iterator = box.index.ALL}) +--- +... +t +--- +- - [1] + - [2] + - [3] + - [4] + - [5] + - [6] + - [7] + - [8] + - [9] + - [10] +... +t = space.index[0]:select({}, {iterator = box.index.GE}) +--- +... +t +--- +- - [1] + - [2] + - [3] + - [4] + - [5] + - [6] + - [7] + - [8] + - [9] + - [10] +... +t = space.index[0]:select(4, {iterator = box.index.GE}) +--- +... +t +--- +- - [4] + - [5] + - [6] + - [7] + - [8] + - [9] + - [10] +... +t = space.index[0]:select({}, {iterator = box.index.LE}) +--- +... +t +--- +- - [10] + - [9] + - [8] + - [7] + - [6] + - [5] + - [4] + - [3] + - [2] + - [1] +... +t = space.index[0]:select(7, {iterator = box.index.LE}) +--- +... +t +--- +- - [7] + - [6] + - [5] + - [4] + - [3] + - [2] + - [1] +... +t = {} +--- +... +for v=1, 10 do table.insert(t, space:get({v})) end +--- +... +t +--- +- - [1] + - [2] + - [3] + - [4] + - [5] + - [6] + - [7] + - [8] + - [9] + - [10] +... +space:drop() +--- +... +os.execute("rm -rf sophia") +--- +- 0 +... diff --git a/test/box/sophia.test.lua b/test/box/sophia.test.lua new file mode 100644 index 0000000000000000000000000000000000000000..759fe750abd7e9d79163701fadeb2c02606a263f --- /dev/null +++ b/test/box/sophia.test.lua @@ -0,0 +1,27 @@ + +space = box.schema.create_space('tweedledum', { id = 123, engine = 'sophia' }) +space:create_index('primary', { type = 'tree', parts = {0, 'num'} }) + +for v=1, 10 do space:insert({v}) end + +t = space.index[0]:select({}, {iterator = box.index.ALL}) +t + +t = space.index[0]:select({}, {iterator = box.index.GE}) +t + +t = space.index[0]:select(4, {iterator = box.index.GE}) +t + +t = space.index[0]:select({}, {iterator = box.index.LE}) +t + +t = space.index[0]:select(7, {iterator = box.index.LE}) +t + +t = {} +for v=1, 10 do table.insert(t, space:get({v})) end +t + +space:drop() +os.execute("rm -rf sophia") diff --git a/test/module/suite.ini b/test/module/suite.ini index 0dede8fba9a77d53803c4ed063efcad5a29fc4d9..fba1bc22dc6b612d5b9dc675c36c3639258c8edb 100644 --- a/test/module/suite.ini +++ b/test/module/suite.ini @@ -1,3 +1,4 @@ [default] script = box.lua +disabled = sophia.test.lua description = tarantool/box, optional lua modules