Created
May 29, 2012 00:57
-
-
Save kazupon/2821950 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- global variables | |
kt = __kyototycoon__ | |
db = kt.db | |
function toboolean (v) | |
return (type(v) == 'string' and v == 'true') or (type(v) == 'number' and v ~= 0) or (type(v) == 'boolean' and v) | |
end | |
function usage (outmap) | |
local buf = {} | |
table.insert(buf, 'usage:') | |
table.insert(buf, ' ktremotemgr script test pattern order rnd [true|false] etc [true|false] rnum [num]') | |
table.insert(buf, ' ktremotemgr script test pattern wicked it [num] rnum [num]') | |
table.insert(buf, '') | |
outmap.message = table.concat(buf, '\n') | |
return kt.RVSUCCESS | |
end | |
-- perform formatted output | |
function printf (format, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) | |
if type(a) ~= 'number' then a = tostring(a) end | |
if type(b) ~= 'number' then b = tostring(b) end | |
if type(c) ~= 'number' then c = tostring(c) end | |
if type(d) ~= 'number' then d = tostring(d) end | |
if type(e) ~= 'number' then e = tostring(e) end | |
if type(f) ~= 'number' then f = tostring(f) end | |
if type(g) ~= 'number' then g = tostring(g) end | |
if type(h) ~= 'number' then h = tostring(h) end | |
if type(i) ~= 'number' then i = tostring(i) end | |
if type(j) ~= 'number' then j = tostring(j) end | |
if type(k) ~= 'number' then k = tostring(k) end | |
if type(l) ~= 'number' then l = tostring(l) end | |
if type(m) ~= 'number' then m = tostring(m) end | |
if type(n) ~= 'number' then n = tostring(n) end | |
if type(o) ~= 'number' then o = tostring(o) end | |
if type(p) ~= 'number' then p = tostring(p) end | |
kt.log('debug', string.format(format, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)) | |
end | |
-- print the error message of the database | |
function dberrprint (db, func) | |
local err = db:error() | |
printf('%s: %s: %s: %s', func, err:code(), err:name(), err:message()) | |
end | |
-- print members of a database | |
function dbmetaprint (db, verbose) | |
if verbose then | |
local status = db:status() | |
if status then | |
for key, value in pairs(status) do | |
printf('%s: %s', key, value) | |
end | |
end | |
else | |
printf('count: %d', db:count()) | |
printf('size: %d', db:size()) | |
end | |
end | |
-- main routine | |
function main (inmap, outmap) | |
local pattern = inmap.pattern | |
if not pattern then return usage(outmap) end | |
local rv | |
if pattern == 'order' then | |
rv = runorder(inmap, outmap) | |
elseif pattern == 'wicked' then | |
rv = runwicked(inmap, outmap) | |
else | |
return usage(outmap) | |
end | |
collectgarbage('collect') | |
return rv | |
end | |
-- parse arguments of order command | |
function runorder (inmap, outmap) | |
local rnum = inmap.rnum and tonumber(inmap.rnum) or 0 | |
local rnd = inmap.rnd and toboolean(inmap.rnd) or false | |
local etc = inmap.etc and toboolean(inmap.etc) or false | |
printf('runorder: rnum=%s, rnd=%s, etc=%s', rnum, rnd, etc) | |
if rnum < 1 then return usage(outmap) end | |
return procorder(rnum, rnd, etc, outmap) | |
end | |
-- parse arguments of wicked command | |
function runwicked (inmap, outmap) | |
local rnum = inmap.rnum and tonumber(inmap.rnum) or 0 | |
local itnum = inmap.it and tonumber(inmap.it) or 0 | |
printf('runwicked: rnum=%s, itnum=%s', rnum, itnum) | |
if rnum < 1 then return usage(outmap) end | |
return procwicked(rnum, itnum, outmap) | |
end | |
-- perform write command | |
function procorder (rnum, rnd, etc, outmap) | |
printf('<In-order Test> rnum=%s rnd=%s etc=%s', rnum, rnd, etc) | |
local err = false | |
local stime = kt.time() | |
for i = 1, rnum do | |
if err then break end | |
local key = string.format('%08d', rnd and math.random(rnum) or i) | |
if not db:set(key, key) then | |
dberrprint(db, "DB::set") | |
err = true | |
end | |
end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
if etc then | |
printf('adding records:') | |
stime = kt.time() | |
for i = 1, rnum do | |
if err then break end | |
local key = string.format('%08d', rnd and math.random(rnum) or i) | |
if not db:add(key, key) and db:error():code() ~= kt.Error.DUPREC then | |
dberrprint(db, 'DB::add') | |
err = true | |
end | |
end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
end | |
if etc then | |
printf('appending records:') | |
stime = kt.time() | |
for i = 1, rnum do | |
if err then break end | |
local key = string.format('%08d', rnd and math.random(rnum) or i) | |
if not db:append(key, key) then | |
dberrprint(db, 'DB::append') | |
err = true | |
end | |
end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
end | |
if etc then | |
printf('accepting visitors:') | |
stime = kt.time() | |
local cnt = 0 | |
local function visit(key, value) | |
cnt = cnt + 1 | |
local rv = kt.Visitor.NOP | |
if rnd then | |
local num = math.random(7) | |
if num == 1 then | |
rv = tostring(cnt) | |
elseif num == 2 then | |
rv = kt.Visitor.REMOVE | |
end | |
end | |
return rv | |
end | |
for i = 1, rnum do | |
if err then break end | |
local key = string.format('%08d', rnd and math.random(rnum) or i) | |
if not db:accept(key, visit, rnd) then | |
dberrprint(db, 'DB::append') | |
err = true | |
end | |
end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
end | |
printf('getting records:') | |
stime = kt.time() | |
for i = 1, rnum do | |
if err then break end | |
local key = string.format('%08d', rnd and math.random(rnum) or i) | |
if not db:get(key) and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'DB::get') | |
err = true | |
end | |
end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
if etc then | |
printf('traversing the database by the inner iterator:') | |
stime = kt.time() | |
local cnt = 0 | |
local function visit(key, value) | |
cnt = cnt + 1 | |
local rv = kt.Visitor.NOP | |
if rnd then | |
local num = math.random(7) | |
if num == 1 then | |
rv = tostring(cnt) .. tostring(cnt) | |
elseif num == 2 then | |
rv = kt.Visitor.REMOVE | |
end | |
end | |
return rv | |
end | |
if not db:iterate(visit, rnd) then | |
dberrprint(db, 'DB::iterate') | |
err = true | |
end | |
if rnd then printf('(end)') end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
end | |
if etc then | |
printf('traversing the database by the outer cursor:') | |
stime = kt.time() | |
local cnt = 0 | |
local function visit(key, value) | |
cnt = cnt + 1 | |
local rv = kt.Visitor.NOP | |
if rnd then | |
local num = math.random(7) | |
if num == 1 then | |
rv = tostring(cnt) .. tostring(cnt) | |
elseif num == 2 then | |
rv = kt.Visitor.REMOVE | |
end | |
end | |
return rv | |
end | |
local cur = db:cursor() | |
if not cur:jump() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::jump') | |
err = true | |
end | |
while cur:accept(visit, rnd, false) do | |
if not cur:step() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::step') | |
err = true | |
end | |
end | |
if db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::accept') | |
err = true | |
end | |
if not rnd or math.random(2) == 1 then cur:disable() end | |
if rnd then printf('(end)') end | |
etime = kt.time() | |
dbmetaprint(db, false) | |
printf('time: %.3f', etime - stime) | |
end | |
printf('removing records:') | |
stime = kt.time() | |
for i = 1, rnum do | |
if err then break end | |
local key = string.format('%08d', rnd and math.random(rnum) or i) | |
if not db:remove(key) and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'DB::remove') | |
err = true | |
end | |
end | |
etime = kt.time() | |
dbmetaprint(db, true) | |
printf('time: %.3f', etime - stime) | |
printf('%s', err and 'error' or 'ok') | |
return err and 1 or kt.RVSUCCESS | |
end | |
-- perform wicked command | |
function procwicked(rnum, itnum, outmap) | |
printf('<Wicked Test> rnum=%s itnum=%s', rnum, itnum) | |
local VisitorImpl = {} | |
function VisitorImpl:new(rnd) | |
local obj = {} | |
obj.cnt = 0 | |
obj.rnd = rnd | |
function obj:visit_full(key, value) | |
self.cnt = self.cnt + 1 | |
local rv = kt.Visitor.NOP | |
if self.rnd then | |
local num = math.random(7) | |
if num == 1 then | |
rv = self.cnt | |
elseif num == 2 then | |
rv = kt.Visitor.REMOVE | |
end | |
end | |
return rv | |
end | |
function obj:visit_empty(key) | |
return self:visit_full(key, key) | |
end | |
local base = kt.Visitor:new() | |
setmetatable(obj, { __index = base }) | |
return obj | |
end | |
local err = false | |
for itcnt = 1, itnum do | |
if itnum > 1 then printf('iteration %d:', itcnt) end | |
local stime = kt.time() | |
local cur = db:cursor() | |
for i = 1, rnum do | |
if err then break end | |
local tran = math.random(100) == 1 | |
if tran and not db:begin_transaction(math.random(rnum) == 1) then | |
dberrprint(db, 'DB::begin_transaction') | |
tran = false | |
err = true | |
end | |
local key = string.format('%08d', math.random(rnum)) | |
local cmd = math.random(12) | |
if cmd == 1 then | |
if not db:set(key, key) then | |
dberrprint(db, 'DB::set') | |
err = true | |
end | |
elseif cmd == 2 then | |
if not db:add(key, key) and db:error():code() ~= kt.Error.DUPREC then | |
dberrprint(db, 'DB::add') | |
err = true | |
end | |
elseif cmd == 3 then | |
if not db:replace(key, key) and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'DB::replace') | |
err = true | |
end | |
elseif cmd == 4 then | |
if not db:append(key, key) then | |
dberrprint(db, 'DB::append') | |
err = true | |
end | |
elseif cmd == 5 then | |
if math.random(2) == 1 then | |
local num = math.random(10) | |
if not db:increment(key, num) and db:error():code() ~= kt.Error.LOGIC then | |
dberrprint(db, 'DB::increment') | |
err = true | |
end | |
else | |
local num = math.random() * 10 | |
if not db:increment_double(key, num) and db:error():code() ~= kt.Error.LOGIC then | |
dberrprint(db, 'DB::increment_double') | |
err = true | |
end | |
end | |
elseif cmd == 6 then | |
if not db:cas(key, key, key) and db:error():code() ~= kt.Error.LOGIC then | |
dberrprint(db, 'DB::cas') | |
err = true | |
end | |
elseif cmd == 7 then | |
if not db:remove(key) and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'DB::remove') | |
err = true | |
end | |
elseif cmd == 8 then | |
local visitor = VisitorImpl:new(1) | |
if not db:accept(key, visitor, true) then | |
dberrprint(db, 'DB::accept') | |
err = true | |
end | |
elseif cmd == 9 then | |
if math.random(10) == 1 then | |
if math.random(4) == 1 then | |
if not cur:jump_back() and db:error():code() ~= kt.Error.NOIMPL and | |
db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::jump_back') | |
err = true | |
end | |
else | |
if not cur:jump() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::jump') | |
err = true | |
end | |
end | |
else | |
cmd = math.random(6) | |
if cmd == 1 then | |
if not cur:get_key() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::get_key') | |
err = true | |
end | |
elseif cmd == 2 then | |
if not cur:get_value() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::get_value') | |
err = true | |
end | |
elseif cmd == 3 then | |
if not cur:get() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::get') | |
err = true | |
end | |
elseif cmd == 4 then | |
if not cur:remove() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::remove') | |
err = true | |
end | |
else | |
local visitor = VisitorImpl:new(1) | |
if not cur:accept(visitor, true, math.random(2) == 1) and | |
db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::accept') | |
err = true | |
end | |
end | |
end | |
if math.random(2) == 1 then | |
if not cur:step() and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'Cursor::step') | |
err = true | |
end | |
end | |
if math.random(rnum / 50 + 1) == 1 then | |
prefix = string.sub(key, 1, -2) | |
if not db:match_prefix(prefix, math.random(10)) then | |
dberrprint(db, 'DB::match_prefix') | |
err = true | |
end | |
end | |
if math.random(rnum / 50 + 1) == 1 then | |
regex = string.sub(key, 1, -2) | |
if not db:match_regex(regex, math.random(10)) and | |
db:error():code() ~= kt.Error.LOGIC then | |
dberrprint(db, 'DB::match_regex') | |
err = true | |
end | |
end | |
if math.random(rnum / 50 + 1) == 1 then | |
origin = string.sub(key, 1, -2) | |
if not db:match_similar(origin, 3, math.random(2) == 0, math.random(10)) then | |
dberrprint(db, 'DB::match_similar') | |
err = true | |
end | |
end | |
else | |
if not db:get(key) and db:error():code() ~= kt.Error.NOREC then | |
dberrprint(db, 'DB::get') | |
err = true | |
end | |
end | |
if tran and not db:end_transaction(math.random(10) > 1) then | |
dberrprint(db, 'DB::end_transaction') | |
err = true | |
end | |
end | |
cur:disable() | |
dbmetaprint(db, itcnt == itnum) | |
end | |
printf('%s', err and 'error' or 'ok') | |
return err and 1 or kt.RVSUCCESS | |
end | |
-- procedure | |
function test (inmap, outmap) | |
math.randomseed(kt.time() * 1000) | |
local stime = kt.time() | |
local rv = main(inmap, outmap) | |
local etime = kt.time() | |
printf('proc time: %s', (etime - stime)) | |
return rv | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment