From eb5255939f893a5e35981e25d9ca4244eea55f5e Mon Sep 17 00:00:00 2001
From: "Dmitry E. Oboukhov" <unera@debian.org>
Date: Tue, 21 Aug 2012 13:07:12 +0400
Subject: [PATCH] box.uuid() and box.uuid_hex() functions

https://blueprints.launchpad.net/tarantool/+spec/box-uuid
---
 doc/user/stored-procedures.xml | 32 ++++++++++++++++
 mod/box/CMakeLists.txt         |  3 +-
 mod/box/box_lua.m              |  4 ++
 mod/box/box_lua_uuid.h         |  9 +++++
 mod/box/box_lua_uuid.m         | 67 ++++++++++++++++++++++++++++++++++
 test/box/lua.result            | 13 +++++++
 test/box/lua.test              |  6 +++
 7 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 mod/box/box_lua_uuid.h
 create mode 100644 mod/box/box_lua_uuid.m

diff --git a/doc/user/stored-procedures.xml b/doc/user/stored-procedures.xml
index 2e6ce5636c..f022711a1c 100644
--- a/doc/user/stored-procedures.xml
+++ b/doc/user/stored-procedures.xml
@@ -726,6 +726,38 @@ lua box.dostring('local f = function(key) t=box.select(0, 0, key); if t ~= nil t
             </para>
         </listitem>
     </varlistentry>
+    <varlistentry>
+        <term>
+            <emphasis role="lua">box.uuid()</emphasis>
+        </term>
+        <listitem>
+            <para>
+                Generates 128-bit (16 bytes) unique id.
+            </para>
+            <para>
+                Requires <emphasis>libuuid</emphasis> to be
+                installed.
+            </para>
+        </listitem>
+    </varlistentry>
+    <varlistentry>
+        <term>
+            <emphasis role="lua">box.uuid_hex()</emphasis>
+        </term>
+        <listitem>
+            <para>
+                Generates hex-string of 128-bit (16 bytes) unique id.
+                Returns 32-bytes string.
+            </para>
+            <bridgehead renderas="sect4">Example</bridgehead>
+            <programlisting>
+                lua box.uuid_hex()
+                ---
+                 - a4f29fa0eb6d11e19f7737696d7fa8ff
+                ...
+            </programlisting>
+        </listitem>
+    </varlistentry>
 </variablelist>
 
 <variablelist>
diff --git a/mod/box/CMakeLists.txt b/mod/box/CMakeLists.txt
index 9b3ec9b45f..7c99f08466 100644
--- a/mod/box/CMakeLists.txt
+++ b/mod/box/CMakeLists.txt
@@ -39,4 +39,5 @@ set_source_files_properties(memcached.m
     PROPERTIES COMPILE_FLAGS "-Wno-uninitialized")
 
 tarantool_module("box" tuple.m index.m tree.m space.m port.m request.m
-    txn.m box.m box.lua.c box_lua.m memcached.m memcached-grammar.m)
+    txn.m box.m box.lua.c box_lua.m memcached.m memcached-grammar.m
+    box_lua_uuid.m)
diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m
index 9b87474bc8..d0ea9fb50c 100644
--- a/mod/box/box_lua.m
+++ b/mod/box/box_lua.m
@@ -43,6 +43,8 @@
 #include "space.h"
 #include "port.h"
 
+#include "box_lua_uuid.h"
+
 
 /* contents of box.lua */
 extern const char box_lua[];
@@ -868,6 +870,8 @@ static int lbox_process(lua_State *L)
 
 static const struct luaL_reg boxlib[] = {
 	{"process", lbox_process},
+	{"uuid", lbox_uuid},
+	{"uuid_hex", lbox_uuid_hex},
 	{NULL, NULL}
 };
 
diff --git a/mod/box/box_lua_uuid.h b/mod/box/box_lua_uuid.h
new file mode 100644
index 0000000000..c2fbb0ba6b
--- /dev/null
+++ b/mod/box/box_lua_uuid.h
@@ -0,0 +1,9 @@
+#ifndef __BOX_LUA_UUID_H__
+#define __BOX_LUA_UUID_H__
+
+struct lua_State;
+
+int lbox_uuid(struct lua_State *L);
+int lbox_uuid_hex(struct lua_State *L);
+
+#endif /* __BOX_LUA_UUID_H__ */
diff --git a/mod/box/box_lua_uuid.m b/mod/box/box_lua_uuid.m
new file mode 100644
index 0000000000..dd4f6f0028
--- /dev/null
+++ b/mod/box/box_lua_uuid.m
@@ -0,0 +1,67 @@
+#include <dlfcn.h>
+#include <string.h>
+#include <stdio.h>
+#include "box_lua_uuid.h"
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+
+#define UUIDLIB_SOVERSION	"1"
+#define LIBNAME			( "libuuid.so." UUIDLIB_SOVERSION )
+
+typedef unsigned char uuid_t[16];
+
+static void (*uuid_generate)(uuid_t out);
+static char *error;
+
+static void check_lib(struct lua_State *L) {
+	
+	if (uuid_generate)
+		return;
+	
+	if (error)
+		luaL_error( L, "box.uuid() error: %s", error );
+
+	void *dl = dlopen(LIBNAME, RTLD_LAZY);
+	if (!dl) {
+		error = strdup( dlerror() );
+		luaL_error( L, "box.uuid() error:  %s", error );
+	}
+
+	uuid_generate = dlsym(dl, "uuid_generate");
+	if (!uuid_generate) {
+		error = strdup( dlerror() );
+		luaL_error( L, "box.uuid() error: %s", error );
+	}
+}
+
+
+int lbox_uuid(struct lua_State *L) {
+	check_lib(L);
+
+	uuid_t uuid;
+	uuid_generate(uuid);
+	lua_pushlstring( L, (char *)uuid, sizeof(uuid_t) );
+
+	return 1;
+}
+
+int lbox_uuid_hex(struct lua_State *L) {
+
+	unsigned i;
+	char uuid_hex[ sizeof(uuid_t) * 2 + 1 ];
+
+
+	check_lib(L);
+	
+	uuid_t uuid;
+	uuid_generate(uuid);
+
+	for (i = 0; i < sizeof(uuid_t); i++)
+		snprintf( uuid_hex + i * 2, 3, "%02x", (unsigned)uuid[ i ] );
+
+	lua_pushlstring( L, uuid_hex, sizeof(uuid_t) * 2 );
+	return 1;
+}
+
diff --git a/test/box/lua.result b/test/box/lua.result
index 60b5a3b842..f0d8ae6c44 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -1584,3 +1584,16 @@ lua box.dostring('return ...', 1, 2, 3)
  - 2
  - 3
 ...
+# box.uuid()
+lua box.dostring('return string.len(box.uuid())')
+---
+ - 16
+...
+lua box.dostring('return string.len(box.uuid_hex())')
+---
+ - 32
+...
+lua box.dostring('return string.match(box.uuid_hex(), "^[a-f0-9]+$")') ~= nil
+---
+ - true
+...
diff --git a/test/box/lua.test b/test/box/lua.test
index 1efa745019..2b217be496 100644
--- a/test/box/lua.test
+++ b/test/box/lua.test
@@ -534,3 +534,9 @@ exec admin "lua box.dostring('abc=2')"
 exec admin "lua box.dostring('return abc')"
 exec admin "lua box.dostring('return ...', 1, 2, 3)"
 
+
+print """# box.uuid()"""
+# exec admin "lua box.uuid()"
+exec admin "lua box.dostring('return string.len(box.uuid())')"
+exec admin "lua box.dostring('return string.len(box.uuid_hex())')"
+exec admin """lua box.dostring('return string.match(box.uuid_hex(), "^[a-f0-9]+$")') ~= nil"""
-- 
GitLab