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