From 4606ceaf0ed6e4c8d836b0f1011233edca1371b9 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja.osipov@gmail.com> Date: Thu, 9 Jun 2011 14:28:32 +0400 Subject: [PATCH] User guide: document Ruby connector (based on tarantool.wiki help). Tweak my previous patch for proctitle to be a bit more robust to the path length. --- doc/user/connectors.xml | 102 +++++++++++++++++++++++++++++++++++++++- doc/user/proctitle.xml | 2 +- third_party/proctitle.c | 3 +- 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/doc/user/connectors.xml b/doc/user/connectors.xml index d82278e574..9db6a195fb 100644 --- a/doc/user/connectors.xml +++ b/doc/user/connectors.xml @@ -47,9 +47,107 @@ <section> <title>Ruby</title> <para> - Please see <link - xlink:href="https://github.com/mailru/tarantool/blob/master/connector/ruby/box.rb"><filename>connector/ruby/box.rb</filename></link> in the source tree. + You need <emphasis role="strong">Ruby 1.9</emphasis> or later + to use this connector. Connector sources are located in <link + xlink:href="https://github.com/mailru/tarantool/blob/master/connector/ruby/box.rb"><filename>connector/ruby/box.rb</filename></link>. </para> + <para> + Assume, for the sake of example, that Tarantool has the + following namespace configuration: +<programlisting language="c"> +primary_port = 33013 +admin_port = 33015 +log_level = 3 +slab_alloc_arena = 0.1 + +namespace[0].enabled = 1 +namespace[0].index[0].type = "NUM" +namespace[0].index[0].key_fields[0].fieldno = 0 + +namespace[0].index[1].type = "STR" +namespace[0].index[1].key_fields[0].fieldno = 1 +</programlisting> + The only defined namespace will be used to store user + account information, such as id, name, email, and other + properties. User ID is used for the primary key, but + it's also possible to find a user by name. + </para> + <para>In Ruby, a helper class is defined to present + Tarantool to the rest of the application as a typical object + container. +<example> +<title>userbox.rb</title> +<programlisting language="ruby"><![CDATA[require 'box' + +class UserBox < Box + def initialize(host) + super(host, :namespace => 0) + end + + def insert(user) + case user + when Hash then super [user[:uid], user[:email], user[:name], user[:apple_count]] + when Array then super user + else fail "don't know what to do with #{user.class}" + end + end + + def update_fields(key, *ops) + mapping = {:uid => 0, :email => 1, :name => 2, :apple_count => 3} + ops.map do |op| + op[0] = mapping[op[0]] if op.is_a? Array + end + + super key, *ops + end + + def unpack_tuple!(data) + tuple = super data + { :uid => tuple[0].unpack(?L)[0], + :email => tuple[1], + :name => tuple[2], + :apple_count => tuple[3].unpack(?L)[0] + } + end +end]]></programlisting></example> + Here's how this helper class can be used: +<programlisting><prompt>kostja@shmita:~$ </prompt><command>irb</command> +<![CDATA[>> # Connect to the server +>> require 'userbox' +=> true +>> b = UserBox.new 'localhost:33013' +=> #<UserBox:0x870fd48 @namespace=1, @end_point=["localhost", 33013], @sock=#<TCPSocket:0x870f85c> +>> # Insert a few users +>> b.insert :uid => 1, :email => 'pupkin@mail.ru', :name => 'Vasya', :apple_count => 1 +=> 1 +>> b.insert :uid => 2, :email => 'masha@mail.ru', :name => 'Masha', :apple_count => 0 +=> 1 +>> b.insert :uid => 3, :email => 'petya@mail.ru', :name => 'Petya', :apple_count => 3 +=> 1 +>> # Perform selects +>> b.select 1 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>1}] +>> b.select 1,2,3 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>1}, {:uid=>2, :email=>"masha@mail.ru", :name=>"Masha", :apple_count=>0}, {:uid=>3, :email=>"petya@mail.ru", :name=>"Petya", :apple_count=>3}] +>> # It's possible to retrieve records by email using second index +>> b.select 'pupkin@mail.ru', 'petya@mail.ru', :index => 1 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>1}, {:uid=>3, :email=>"petya@mail.ru", :name=>"Petya", :apple_count=>3}] +Delete +>> b.delete 2 +=> 1 +>> # Update values +>> b.update_fields 1, [:apple_count, :add, 2 ] +=> 1 +>> b.select 1 +=> [{:uid=>1, :email=>"pupkin@mail.ru", :name=>"Vasya", :apple_count=>3}] +>> # It's possible to do several updates in a single atomic command +>> b.update_fields 3, [:apple_count, :add, 10], [:name, :set, "foobar"] +=> 1 +>> b.select 3 +=> [{:uid=>3, :email=>"petya@mail.ru", :name=>"foobar", :apple_count=>13}] +]]> +</programlisting> + </para> </section> </chapter> diff --git a/doc/user/proctitle.xml b/doc/user/proctitle.xml index d962bb7897..23be03ca57 100644 --- a/doc/user/proctitle.xml +++ b/doc/user/proctitle.xml @@ -50,7 +50,7 @@ <olink targetptr="primary_port"/>, <quote>sec</quote> for <olink targetptr="secondary_port"/>, <quote>adm</quote> for <olink targetptr="admin_port"/> and <quote>memcached</quote> for <olink - targetptr="memcached_port"/> respectively. + targetptr="memcached_port"/>. </para> <para> For example: diff --git a/third_party/proctitle.c b/third_party/proctitle.c index a52d93ff61..1a580765ad 100644 --- a/third_party/proctitle.c +++ b/third_party/proctitle.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <limits.h> #ifdef HAVE_SYS_PSTAT_H #include <sys/pstat.h> /* for HP-UX */ @@ -217,7 +218,7 @@ init_set_proc_title(int argc, char **argv) ps_buffer_fixed_size = 0; #else { - char basename_buf[64]; + char basename_buf[PATH_MAX]; /* * At least partially mimic FreeBSD, which for -- GitLab