Skip to content

Commit 3214905

Browse files
committed
Rewrite client in a register workload
- replace READ operation by a sequence of SQL commands - replace WRITE operation by a Lua routine with native UPSERT and use it as an SQL command - manage table in client's setup and teardown Closes #31
1 parent f964e35 commit 3214905

File tree

3 files changed

+49
-74
lines changed

3 files changed

+49
-74
lines changed

resources/tarantool/jepsen.lua

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ local function bootstrap()
3131
box.schema.user.grant('jepsen', 'write', 'space', '_schema')
3232
box.schema.user.grant('jepsen', 'write', 'space', '_space')
3333

34-
box.schema.space.create('JEPSEN', {engine = '%TARANTOOL_DATA_ENGINE%'})
35-
box.space['JEPSEN']:create_index('primary', {parts = {1, 'unsigned' }})
36-
3734
--[[ Function implements a CAS (Compare And Set) operation, which takes a key,
3835
old value, and new value and sets the key to the new value if and only if the
3936
old value matches what's currently there, and returns a detailed response
@@ -44,61 +41,39 @@ box.schema.func.create('_CAS',
4441
{language = 'LUA',
4542
returns = 'boolean',
4643
body = [[function(id, old_value, new_value, table)
47-
local rc = false
48-
box.begin()
49-
local tuple = box.space[table]:get{id}
50-
if tuple then
51-
if tuple[2] == old_value then
52-
box.space[table]:update({id}, {{'=', 2, new_value}})
53-
rc = true
54-
end
55-
end
56-
box.commit()
44+
local rc = false
45+
box.begin()
46+
local tuple = box.space[table]:get{id}
47+
if tuple then
48+
if tuple[2] == old_value then
49+
box.space[table]:update({id}, {{'=', 2, new_value}})
50+
rc = true
51+
end
52+
end
53+
box.commit()
5754
58-
return rc
59-
end]],
55+
return rc
56+
end]],
6057
is_sandboxed = false,
6158
param_list = {'integer', 'integer', 'integer', 'string'},
6259
exports = {'LUA', 'SQL'},
6360
is_deterministic = true})
6461

65-
--[[ Function implements an WRITE operation, which takes a key and value
66-
and sets the key to the value if and only if the key is already exists, and
67-
insert value if it is absent.
68-
Example: SELECT _WRITE(1, 3, 'JEPSEN')
62+
--[[ Function implements a UPSERT operation, which takes a key and value
63+
and sets the key to the value if key exists or insert new key with that value.
64+
Example: SELECT _UPSERT(1, 3, 4, 'JEPSEN')
6965
]]
70-
box.schema.func.create('_WRITE',
66+
box.schema.func.create('_UPSERT',
7167
{language = 'LUA',
72-
returns = 'integer',
73-
body = [[function (id, value, table)
74-
box.space[table]:upsert({id, value}, {{'=', 1, 1}, {'=', 2, value}})
75-
return value
68+
returns = 'boolean',
69+
body = [[function(id, value, table)
70+
box.space[table]:upsert({id, value}, {{'=', 2, value}})
71+
return true
7672
end]],
7773
is_sandboxed = false,
7874
param_list = {'integer', 'integer', 'string'},
7975
exports = {'LUA', 'SQL'},
8076
is_deterministic = true})
81-
82-
--[[ Function implements an READ operation, which takes a key and returns a
83-
value.
84-
Example: SELECT _READ(1, 'JEPSEN')
85-
]]
86-
box.schema.func.create('_READ',
87-
{language = 'LUA',
88-
returns = 'integer',
89-
body = [[function (id, table)
90-
box.begin()
91-
local tuple = box.space[table]:get{id}
92-
if tuple then
93-
return tuple[2]
94-
end
95-
box.commit()
96-
return nil
97-
end]],
98-
is_sandboxed = false,
99-
param_list = {'integer', "string"},
100-
exports = {'LUA', 'SQL'},
101-
is_deterministic = true})
10277
end
10378

10479
box.once('jepsen', bootstrap)

src/tarantool/client.clj

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,6 @@
2727
[node test]
2828
(j/get-datasource (conn-spec node)))
2929

30-
(defn read-v-by-k
31-
"Reads the current value of a key."
32-
[conn k]
33-
(first (vals (first (j/execute! conn ["SELECT _READ(?, 'JEPSEN')" k])))))
34-
35-
(defn write-v-by-k
36-
"Writes the current value of a key."
37-
[conn k v]
38-
(j/execute! conn ["SELECT _WRITE(?, ?, 'JEPSEN')"
39-
k v]))
40-
41-
(defn compare-and-set
42-
[conn id old new]
43-
(first (vals (first (j/execute! conn ["SELECT _CAS(?, ?, ?, 'JEPSEN')"
44-
id old new])))))
45-
4630
(defmacro with-error-handling
4731
"Common error handling for errors, including txn aborts."
4832
[op & body]

src/tarantool/register.clj

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212
[nemesis :as nemesis]
1313
[tests :as tests]
1414
[util :refer [timeout meh]]]
15+
[next.jdbc :as j]
16+
[next.jdbc.sql :as sql]
1517
[knossos.model :as model]
1618
[jepsen.checker.timeline :as timeline]
1719
[jepsen.os.ubuntu :as ubuntu]
1820
[tarantool.client :as cl]
1921
[tarantool.db :as db]))
2022

23+
(def table-name "register")
24+
2125
(defn r [_ _] {:type :invoke, :f :read, :value nil})
2226
(defn w [_ _] {:type :invoke, :f :write, :value (rand-int 5)})
2327
(defn cas [_ _] {:type :invoke, :f :cas, :value [(rand-int 5) (rand-int 5)]})
@@ -33,27 +37,39 @@
3337
(setup! [this test node]
3438
(let [conn (cl/open node test)]
3539
(assert conn)
36-
;(when (= node (jepsen/primary test))
37-
; (j/execute! conn ["CREATE TABLE IF NOT EXISTS jepsen (key INT, value INT, PRIMARY KEY (key))"])
38-
; (j/execute! conn ["CREATE INDEX IF NOT EXISTS idx ON jepsen (key)"]))
40+
(cl/with-conn-failure-retry conn
41+
(j/execute! conn [(str "CREATE TABLE IF NOT EXISTS " table-name
42+
" (id INT NOT NULL PRIMARY KEY,
43+
value INT NOT NULL)")]))
3944
(assoc this :conn conn :node node)))
4045

4146
(invoke! [this test op]
4247
(case (:f op)
43-
:read (assoc op
44-
:type :ok
45-
:value (cl/read-v-by-k conn 1))
46-
:write (do (let [con (cl/open (jepsen/primary test) test)]
47-
(cl/write-v-by-k con 1 (:value op)))
48-
(assoc op :type :ok))
48+
:read (let [value (:VALUE
49+
(first (sql/query conn
50+
[(str "SELECT value FROM " table-name " WHERE id = 1")])))]
51+
(assoc op :type :ok :value value))
52+
53+
:write (do (let [con (cl/open (jepsen/primary test) test)
54+
table (clojure.string/upper-case table-name)]
55+
(j/execute! con
56+
[(str "SELECT _UPSERT(1, " (:value op) ", '" table "')")])
57+
(assoc op :type :ok)))
58+
4959
:cas (let [[old new] (:value op)
50-
con (cl/open (jepsen/primary test) test)]
51-
(assoc op :type (if (cl/compare-and-set con 1 old new)
60+
con (cl/open (jepsen/primary test) test)
61+
table (clojure.string/upper-case table-name)]
62+
(assoc op :type (if (->> (j/execute! conn
63+
[(str "SELECT _CAS(1, " old ", " new ", '" table "')")])
64+
(first)
65+
(vals)
66+
(first))
5267
:ok
5368
:fail)))))
5469

55-
(teardown! [this test])
56-
;(j/execute! conn ["DROP TABLE jepsen"]))
70+
(teardown! [_ test]
71+
(cl/with-conn-failure-retry conn
72+
(j/execute! conn [(str "DROP TABLE IF EXISTS " table-name)])))
5773

5874
(close! [_ test]))
5975

0 commit comments

Comments
 (0)