From 06e714c90e8cff2efd916bceeac133001ec78629 Mon Sep 17 00:00:00 2001
From: Dmitry Simonenko <pmwkaa@gmail.com>
Date: Fri, 26 Sep 2014 20:08:24 +0400
Subject: [PATCH] sophia: implement index:random(), closes #509

---
 src/box/sophia_index.cc           | 25 +++++++++++++++++++++
 src/box/sophia_index.h            |  3 +--
 test/sophia/crud.result           |  9 ++++++++
 test/sophia/crud.test.lua         |  7 ++++++
 test/sophia/index_random_test.lua | 36 +++++++++++++++++++++++++++++++
 test/sophia/suite.ini             |  2 +-
 6 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 test/sophia/index_random_test.lua

diff --git a/src/box/sophia_index.cc b/src/box/sophia_index.cc
index 527a3f7ccf..b50bf1c2c1 100644
--- a/src/box/sophia_index.cc
+++ b/src/box/sophia_index.cc
@@ -176,6 +176,31 @@ SophiaIndex::~SophiaIndex()
 	}
 }
 
+struct tuple *
+SophiaIndex::random(uint32_t rnd) const
+{
+	void *o = sp_object(db);
+	if (o == NULL)
+		tnt_raise(ClientError, ER_SOPHIA, sp_error(db));
+	sp_set(o, "key", &rnd, sizeof(rnd));
+	void *c = sp_cursor(db, "random", o);
+	if (c == NULL)
+		tnt_raise(ClientError, ER_SOPHIA, sp_error(db));
+	auto scoped_guard =
+		make_scoped_guard([=] { sp_destroy(c); });
+	o = sp_get(c);
+	if (o == NULL)
+		return NULL;
+	struct space *space = space_cache_find(key_def->space_id);
+	int valuesize;
+	void *value = sp_get(o, "value", &valuesize);
+	struct tuple *ret =
+		tuple_new(space->format, (char*)value,
+		          (char*)value + valuesize);
+	tuple_ref(ret, 1);
+	return ret;
+}
+
 void
 SophiaIndex::endBuild()
 {
diff --git a/src/box/sophia_index.h b/src/box/sophia_index.h
index 063961d790..322db9d97b 100644
--- a/src/box/sophia_index.h
+++ b/src/box/sophia_index.h
@@ -38,12 +38,11 @@ class SophiaIndex: public Index {
 
 	virtual size_t size() const;
 	virtual void endBuild();
-
+	virtual struct tuple *random(uint32_t rnd) const;
 	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,
diff --git a/test/sophia/crud.result b/test/sophia/crud.result
index 236262ca5b..52822918ea 100644
--- a/test/sophia/crud.result
+++ b/test/sophia/crud.result
@@ -1161,9 +1161,18 @@ index:select(7,  {iterator = box.index.LT})
   - [2]
   - [1]
 ...
+-- random
+dofile('index_random_test.lua')
+---
+...
+index_random_test(space, 'primary')
+---
+- true
+...
 space:drop()
 ---
 ...
+--
 sophia_rmdir()
 ---
 ...
diff --git a/test/sophia/crud.test.lua b/test/sophia/crud.test.lua
index 204853e301..191a580578 100644
--- a/test/sophia/crud.test.lua
+++ b/test/sophia/crud.test.lua
@@ -43,6 +43,13 @@ index:select(7,  {iterator = box.index.LE})
 index:select({}, {iterator = box.index.LT})
 index:select(7,  {iterator = box.index.LT})
 
+-- random
+
+dofile('index_random_test.lua')
+index_random_test(space, 'primary')
+
 space:drop()
 
+--
+
 sophia_rmdir()
diff --git a/test/sophia/index_random_test.lua b/test/sophia/index_random_test.lua
new file mode 100644
index 0000000000..5fb09f03c2
--- /dev/null
+++ b/test/sophia/index_random_test.lua
@@ -0,0 +1,36 @@
+
+function index_random_test(space, index_no)
+	local COUNT = 1028
+	-- clear the space
+	space:truncate()
+	-- randomize
+	math.randomseed(os.time())
+	-- insert values into the index
+	for k=1,COUNT,1 do space:insert{k}  end
+	local rnd_start = math.random(4294967296)
+	-- try to get all values from the index using index.random
+	local tuples = {}
+	local found = 0
+	while found < COUNT do
+		local rnd = math.random(4294967296)
+		if rnd == rnd_start then
+			error('too many iterations')
+			return nil
+		end
+
+		local tuple = space.index[index_no]:random(rnd)
+		if tuple == nil then
+			error('nil returned')
+			return nil
+		end
+		print(tuple)
+
+		local k = tuple[1]
+		if tuples[k] == nil then
+			found = found + 1
+		end
+		tuples[k] = 1
+	end
+
+	return true
+end
diff --git a/test/sophia/suite.ini b/test/sophia/suite.ini
index 5139d0b87a..ddf62d5dad 100644
--- a/test/sophia/suite.ini
+++ b/test/sophia/suite.ini
@@ -5,5 +5,5 @@ script = box.lua
 disabled =
 valgrind_disabled =
 release_disabled =
-lua_libs =
+lua_libs = index_random_test.lua
 use_unix_sockets = True
-- 
GitLab