1 /*************************************************************************************************
2 * The scripting extension
3 * Copyright (C) 2009-2012 FAL Labs
4 * This file is part of Kyoto Tycoon.
5 * This program is free software: you can redistribute it and/or modify it under the terms of
6 * the GNU General Public License as published by the Free Software Foundation, either version
7 * 3 of the License, or any later version.
8 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 * See the GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License along with this program.
12 * If not, see <http://www.gnu.org/licenses/>.
13 *************************************************************************************************/
14
15
16 #include "myscript.h"
17 #include "myconf.h"
18
19
20 #if _KT_LUA
21
22
23 extern "C" {
24 #include <lua.h>
25 #include <lualib.h>
26 #include <lauxlib.h>
27 }
28
29
30 /* precedent type declaration */
31 struct ScriptProcessorCore;
32 class StringBuilder;
33 struct SoftCursor;
34 struct SoftDB;
35 class SoftVisitor;
36 class SoftFileProcessor;
37 class SoftMapReduce;
38 typedef std::map<std::string, std::string> StringMap;
39 typedef std::vector<std::string> StringVector;
40
41
42 /* function prototypes */
43 static void reporterror(ScriptProcessorCore* core, const char* name);
44 static void throwinvarg(lua_State* lua, const char* func);
45 static void setfielduint(lua_State* lua, const char* name, uint32_t num);
46 static void setfieldstr(lua_State* lua, const char* name, const char* str);
47 static void setfieldfunc(lua_State* lua, const char* name, lua_CFunction func);
48 static void setfieldvalue(lua_State* lua, const char* name, int32_t index);
49 static void define_module(lua_State* lua);
50 static int kt_atoi(lua_State* lua);
51 static int kt_atoix(lua_State* lua);
52 static int kt_atof(lua_State* lua);
53 static int kt_hash_murmur(lua_State* lua);
54 static int kt_hash_fnv(lua_State* lua);
55 static int kt_levdist(lua_State* lua);
56 static int kt_time(lua_State* lua);
57 static int kt_sleep(lua_State* lua);
58 static int kt_pack(lua_State* lua);
59 static int kt_unpack(lua_State *lua);
60 static int kt_split(lua_State *lua);
61 static int kt_codec(lua_State *lua);
62 static int kt_bit(lua_State *lua);
63 static int kt_strstr(lua_State *lua);
64 static int kt_strfwm(lua_State *lua);
65 static int kt_strbwm(lua_State *lua);
66 static int kt_regex(lua_State *lua);
67 static int kt_arraydump(lua_State *lua);
68 static int kt_arrayload(lua_State *lua);
69 static int kt_mapdump(lua_State *lua);
70 static int kt_mapload(lua_State *lua);
71 static void define_err(lua_State* lua);
72 static int err_new(lua_State* lua);
73 static int err_tostring(lua_State* lua);
74 static int err_set(lua_State* lua);
75 static int err_code(lua_State* lua);
76 static int err_name(lua_State* lua);
77 static int err_message(lua_State* lua);
78 static void define_vis(lua_State* lua);
79 static int vis_new(lua_State* lua);
80 static int vis_visit_full(lua_State* lua);
81 static int vis_visit_empty(lua_State* lua);
82 static void define_fproc(lua_State* lua);
83 static int fproc_new(lua_State* lua);
84 static int fproc_process(lua_State* lua);
85 static void define_cur(lua_State* lua);
86 static int cur_new(lua_State* lua);
87 static int cur_gc(lua_State* lua);
88 static int cur_tostring(lua_State* lua);
89 static int cur_call(lua_State* lua);
90 static int cur_disable(lua_State* lua);
91 static int cur_accept(lua_State* lua);
92 static int cur_set_value(lua_State* lua);
93 static int cur_remove(lua_State* lua);
94 static int cur_get_key(lua_State* lua);
95 static int cur_get_value(lua_State* lua);
96 static int cur_get(lua_State* lua);
97 static int cur_seize(lua_State* lua);
98 static int cur_jump(lua_State* lua);
99 static int cur_jump_back(lua_State* lua);
100 static int cur_step(lua_State* lua);
101 static int cur_step_back(lua_State* lua);
102 static int cur_db(lua_State* lua);
103 static int cur_error(lua_State* lua);
104 static void define_db(lua_State* lua);
105 static int db_new(lua_State* lua);
106 static int db_gc(lua_State* lua);
107 static int db_tostring(lua_State* lua);
108 static int db_index(lua_State* lua);
109 static int db_newindex(lua_State* lua);
110 static int db_new_ptr(lua_State* lua);
111 static int db_delete_ptr(lua_State* lua);
112 static int db_process(lua_State* lua);
113 static int db_error(lua_State* lua);
114 static int db_open(lua_State* lua);
115 static int db_close(lua_State* lua);
116 static int db_accept(lua_State* lua);
117 static int db_accept_bulk(lua_State* lua);
118 static int db_iterate(lua_State* lua);
119 static int db_set(lua_State* lua);
120 static int db_add(lua_State* lua);
121 static int db_replace(lua_State* lua);
122 static int db_append(lua_State* lua);
123 static int db_increment(lua_State* lua);
124 static int db_increment_double(lua_State* lua);
125 static int db_cas(lua_State* lua);
126 static int db_remove(lua_State* lua);
127 static int db_get(lua_State* lua);
128 static int db_check(lua_State* lua);
129 static int db_seize(lua_State* lua);
130 static int db_set_bulk(lua_State* lua);
131 static int db_remove_bulk(lua_State* lua);
132 static int db_get_bulk(lua_State* lua);
133 static int db_clear(lua_State* lua);
134 static int db_synchronize(lua_State* lua);
135 static int db_occupy(lua_State* lua);
136 static int db_copy(lua_State* lua);
137 static int db_begin_transaction(lua_State* lua);
138 static int db_end_transaction(lua_State* lua);
139 static int db_transaction(lua_State* lua);
140 static int db_dump_snapshot(lua_State* lua);
141 static int db_load_snapshot(lua_State* lua);
142 static int db_count(lua_State* lua);
143 static int db_size(lua_State* lua);
144 static int db_path(lua_State* lua);
145 static int db_status(lua_State* lua);
146 static int db_match_prefix(lua_State* lua);
147 static int db_match_regex(lua_State* lua);
148 static int db_match_similar(lua_State* lua);
149 static int db_merge(lua_State* lua);
150 static int db_mapreduce(lua_State* lua);
151 static int db_mapreduce_emit(lua_State* lua);
152 static int db_mapreduce_iter(lua_State* lua);
153 static int db_cursor(lua_State* lua);
154 static int db_cursor_process(lua_State* lua);
155 static int db_pairs(lua_State* lua);
156 static int serv_log(lua_State* lua);
157
158
159 /**
160 * ScriptProcessor internal.
161 */
162 struct ScriptProcessorCore {
163 std::string path;
164 int32_t thid;
165 kt::RPCServer* serv;
166 kt::TimedDB* dbs;
167 int32_t dbnum;
168 const std::map<std::string, int32_t>* dbmap;
169 lua_State *lua;
170 };
171
172
173 /**
174 * Wrapper of a string.
175 */
176 class StringBuilder {
177 public:
StringBuilder(lua_State * lua,int32_t index)178 StringBuilder(lua_State* lua, int32_t index) : str_(), ok_(false) {
179 char nbuf[kc::NUMBUFSIZ];
180 const char* ptr = NULL;
181 size_t size = 0;
182 switch (lua_type(lua, index)) {
183 case LUA_TNUMBER: {
184 double num = lua_tonumber(lua, index);
185 if (num == std::floor(num)) {
186 std::snprintf(nbuf, sizeof(nbuf) - 1, "%lld", (long long)num);
187 } else {
188 std::snprintf(nbuf, sizeof(nbuf) - 1, "%f", num);
189 }
190 nbuf[sizeof(nbuf)-1] = '\0';
191 ptr = nbuf;
192 size = std::strlen(ptr);
193 break;
194 }
195 case LUA_TBOOLEAN: {
196 ptr = lua_toboolean(lua, index) ? "true" : "false";
197 size = std::strlen(ptr);
198 break;
199 }
200 case LUA_TSTRING: {
201 ptr = lua_tolstring(lua, index, &size);
202 break;
203 }
204 }
205 if (ptr) {
206 str_.append(ptr, size);
207 ok_ = true;
208 }
209 }
str()210 const std::string& str() {
211 return str_;
212 }
ok()213 bool ok() {
214 return ok_;
215 }
216 private:
217 std::string str_;
218 bool ok_;
219 };
220
221
222 /**
223 * Default constructor.
224 */
ScriptProcessor()225 ScriptProcessor::ScriptProcessor() {
226 _assert_(true);
227 ScriptProcessorCore* core = new ScriptProcessorCore;
228 core->thid = 0;
229 core->serv = NULL;
230 core->dbs = NULL;
231 core->dbnum = 0;
232 core->dbmap = NULL;
233 core->lua = NULL;
234 opq_ = core;
235 }
236
237
238 /**
239 * Destructor.
240 */
~ScriptProcessor()241 ScriptProcessor::~ScriptProcessor() {
242 _assert_(true);
243 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
244 lua_State* lua = core->lua;
245 if (lua) lua_close(lua);
246 delete core;
247 }
248
249
250 /**
251 * Set domain-specific resources.
252 */
set_resources(int32_t thid,kt::RPCServer * serv,kt::TimedDB * dbs,int32_t dbnum,const std::map<std::string,int32_t> * dbmap)253 bool ScriptProcessor::set_resources(int32_t thid, kt::RPCServer* serv,
254 kt::TimedDB* dbs, int32_t dbnum,
255 const std::map<std::string, int32_t>* dbmap) {
256 _assert_(serv && dbs && dbnum >= 0 && dbmap);
257 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
258 lua_State *lua = luaL_newstate();
259 if (!lua) return false;
260 luaL_openlibs(lua);
261 lua_settop(lua, 0);
262 lua_newtable(lua);
263 define_module(lua);
264 define_err(lua);
265 define_vis(lua);
266 define_fproc(lua);
267 define_cur(lua);
268 define_db(lua);
269 lua_setglobal(lua, "__kyototycoon__");
270 lua_getglobal(lua, "__kyototycoon__");
271 lua_pushlightuserdata(lua, serv);
272 lua_setfield(lua, -2, "__serv__");
273 setfieldstr(lua, "VERSION", kt::VERSION);
274 setfielduint(lua, "RVSUCCESS", kt::RPCClient::RVSUCCESS);
275 setfielduint(lua, "RVENOIMPL", kt::RPCClient::RVENOIMPL);
276 setfielduint(lua, "RVEINVALID", kt::RPCClient::RVEINVALID);
277 setfielduint(lua, "RVELOGIC", kt::RPCClient::RVELOGIC);
278 setfielduint(lua, "RVEINTERNAL", kt::RPCClient::RVEINTERNAL);
279 setfielduint(lua, "thid", thid);
280 lua_getfield(lua, -1, "DB");
281 lua_newtable(lua);
282 for (int32_t i = 0; i < dbnum; i++) {
283 lua_getfield(lua, -2, "new");
284 lua_pushvalue(lua, -3);
285 lua_pushlightuserdata(lua, dbs + i);
286 if (lua_pcall(lua, 2, 1, 0) != 0) {
287 lua_close(lua);
288 return false;
289 }
290 lua_rawseti(lua, -2, i + 1);
291 }
292 lua_rawgeti(lua, -1, 1);
293 lua_setfield(lua, -4, "db");
294 std::map<std::string, int32_t>::const_iterator it = dbmap->begin();
295 std::map<std::string, int32_t>::const_iterator itend = dbmap->end();
296 while (it != itend) {
297 lua_rawgeti(lua, -1, it->second + 1);
298 lua_setfield(lua, -2, it->first.c_str());
299 ++it;
300 }
301 lua_setfield(lua, -3, "dbs");
302 lua_pop(lua, 1);
303 setfieldfunc(lua, "log", serv_log);
304 lua_settop(lua, 0);
305 core->thid = thid;
306 core->serv = serv;
307 core->dbs = dbs;
308 core->dbnum = dbnum;
309 core->dbmap = dbmap;
310 core->lua = lua;
311 return true;
312 }
313
314
315 /**
316 * Load a script file.
317 */
load(const std::string & path)318 bool ScriptProcessor::load(const std::string& path) {
319 _assert_(true);
320 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
321 core->path = path;
322 lua_State* lua = core->lua;
323 int64_t size;
324 char* script = kc::File::read_file(path, &size);
325 if (!script) return false;
326 bool err = false;
327 lua_settop(lua, 0);
328 if (luaL_loadstring(lua, script) != 0 || lua_pcall(lua, 0, 0, 0) != 0) {
329 reporterror(core, "(init)");
330 err = true;
331 }
332 delete[] script;
333 return !err;
334 }
335
336
337 /**
338 * Clear the internal state.
339 */
clear()340 void ScriptProcessor::clear() {
341 _assert_(true);
342 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
343 lua_State* lua = core->lua;
344 if (lua) lua_close(lua);
345 core->thid = 0;
346 core->serv = NULL;
347 core->dbs = NULL;
348 core->dbnum = 0;
349 core->dbmap = NULL;
350 core->lua = NULL;
351 }
352
353
354 /**
355 * Call a procedure.
356 */
call(const std::string & name,const std::map<std::string,std::string> & inmap,std::map<std::string,std::string> & outmap)357 kt::RPCClient::ReturnValue ScriptProcessor::call(const std::string& name,
358 const std::map<std::string, std::string>& inmap,
359 std::map<std::string, std::string>& outmap) {
360 _assert_(true);
361 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
362 lua_State* lua = core->lua;
363 lua_settop(lua, 0);
364 lua_newtable(lua);
365 lua_getglobal(lua, name.c_str());
366 if (!lua_isfunction(lua, -1)) {
367 lua_settop(lua, 0);
368 return kt::RPCClient::RVENOIMPL;
369 }
370 lua_newtable(lua);
371 std::map<std::string, std::string>::const_iterator it = inmap.begin();
372 std::map<std::string, std::string>::const_iterator itend = inmap.end();
373 while (it != itend) {
374 lua_pushlstring(lua, it->first.data(), it->first.size());
375 lua_pushlstring(lua, it->second.data(), it->second.size());
376 lua_settable(lua, -3);
377 ++it;
378 }
379 lua_pushvalue(lua, 1);
380 kt::RPCClient::ReturnValue rv;
381 if (lua_pcall(lua, 2, 1, 0) == 0) {
382 lua_pushnil(lua);
383 while (lua_next(lua, 1) != 0) {
384 StringBuilder key(lua, -2);
385 StringBuilder value(lua, -1);
386 if (key.ok() && value.ok()) outmap[key.str()] = value.str();
387 lua_pop(lua, 1);
388 }
389 rv = (kt::RPCClient::ReturnValue)lua_tointeger(lua, -1);
390 } else {
391 reporterror(core, name.c_str());
392 rv = kt::RPCClient::RVEINTERNAL;
393 }
394 lua_settop(lua, 0);
395 return rv;
396 }
397
398
399 /**
400 * Burrow of cursors no longer in use.
401 */
402 class CursorBurrow {
403 private:
404 typedef std::vector<kt::TimedDB::Cursor*> CursorList;
405 public:
CursorBurrow()406 explicit CursorBurrow() : lock_(), dcurs_() {}
~CursorBurrow()407 ~CursorBurrow() {
408 sweap();
409 }
sweap()410 void sweap() {
411 kc::ScopedSpinLock lock(&lock_);
412 if (dcurs_.size() > 0) {
413 CursorList::iterator dit = dcurs_.begin();
414 CursorList::iterator ditend = dcurs_.end();
415 while (dit != ditend) {
416 kt::TimedDB::Cursor* cur = *dit;
417 delete cur;
418 ++dit;
419 }
420 dcurs_.clear();
421 }
422 }
deposit(kt::TimedDB::Cursor * cur)423 void deposit(kt::TimedDB::Cursor* cur) {
424 kc::ScopedSpinLock lock(&lock_);
425 dcurs_.push_back(cur);
426 }
427 private:
428 kc::SpinLock lock_;
429 CursorList dcurs_;
430 } g_curbur;
431
432
433 /**
434 * Wrapper of a database.
435 */
436 struct SoftCursor {
437 kt::TimedDB::Cursor* cur;
438 };
439
440
441 /**
442 * Wrapper of a database.
443 */
444 struct SoftDB {
445 kt::TimedDB* db;
446 bool light;
447 };
448
449
450 /**
451 * Wrapper of a visitor.
452 */
453 class SoftVisitor : public kt::TimedDB::Visitor {
454 public:
SoftVisitor(lua_State * lua,bool writable)455 explicit SoftVisitor(lua_State* lua, bool writable) :
456 lua_(lua), writable_(writable), top_(0) {
457 top_ = lua_gettop(lua_);
458 }
459 private:
visit_full(const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz,size_t * sp,int64_t * xtp)460 const char* visit_full(const char* kbuf, size_t ksiz,
461 const char* vbuf, size_t vsiz, size_t* sp, int64_t* xtp) {
462 lua_settop(lua_, top_);
463 int32_t argc;
464 if (lua_istable(lua_, -1)) {
465 lua_getfield(lua_, -1, "visit_full");
466 if (!lua_isfunction(lua_, -1)) return NOP;
467 lua_pushvalue(lua_, -2);
468 lua_pushlstring(lua_, kbuf, ksiz);
469 lua_pushlstring(lua_, vbuf, vsiz);
470 lua_pushnumber(lua_, *xtp < kt::TimedDB::XTMAX ? *xtp : kt::TimedDB::XTMAX);
471 argc = 4;
472 } else {
473 if (!lua_isfunction(lua_, -1)) return NOP;
474 lua_pushvalue(lua_, -1);
475 lua_pushlstring(lua_, kbuf, ksiz);
476 lua_pushlstring(lua_, vbuf, vsiz);
477 lua_pushnumber(lua_, *xtp < kt::TimedDB::XTMAX ? *xtp : kt::TimedDB::XTMAX);
478 argc = 3;
479 }
480 const char* rv = NOP;
481 if (lua_pcall(lua_, argc, 2, 0) == 0) {
482 if (lua_islightuserdata(lua_, -2)) {
483 const char* trv = (const char*)lua_touserdata(lua_, -2);
484 if (trv == kt::TimedDB::Visitor::REMOVE) rv = kt::TimedDB::Visitor::REMOVE;
485 } else {
486 size_t rsiz;
487 const char* rbuf = lua_tolstring(lua_, -2, &rsiz);
488 if (rbuf) {
489 rv = rbuf;
490 *sp = rsiz;
491 }
492 *xtp = lua_isnumber(lua_, -1) ? lua_tonumber(lua_, -1) : -*xtp;
493 }
494 }
495 if (!writable_) rv = NULL;
496 return rv;
497 }
visit_empty(const char * kbuf,size_t ksiz,size_t * sp,int64_t * xtp)498 const char* visit_empty(const char* kbuf, size_t ksiz, size_t* sp, int64_t* xtp) {
499 lua_settop(lua_, top_);
500 int32_t argc;
501 if (lua_istable(lua_, -1)) {
502 lua_getfield(lua_, -1, "visit_empty");
503 if (!lua_isfunction(lua_, -1)) return NOP;
504 lua_pushvalue(lua_, -2);
505 lua_pushlstring(lua_, kbuf, ksiz);
506 argc = 2;
507 } else {
508 if (!lua_isfunction(lua_, -1)) return NOP;
509 lua_pushvalue(lua_, -1);
510 lua_pushlstring(lua_, kbuf, ksiz);
511 lua_pushnil(lua_);
512 argc = 2;
513 }
514 const char* rv = NOP;
515 if (lua_pcall(lua_, argc, 2, 0) == 0) {
516 if (lua_islightuserdata(lua_, -1)) {
517 const char* trv = (const char*)lua_touserdata(lua_, -1);
518 if (trv == kt::TimedDB::Visitor::REMOVE) rv = kt::TimedDB::Visitor::REMOVE;
519 } else {
520 size_t rsiz;
521 const char* rbuf = lua_tolstring(lua_, -2, &rsiz);
522 if (rbuf) {
523 rv = rbuf;
524 *sp = rsiz;
525 }
526 *xtp = lua_isnumber(lua_, -1) ? lua_tonumber(lua_, -1) : kc::INT64MAX;
527 }
528 }
529 if (!writable_) rv = NULL;
530 return rv;
531 }
visit_before()532 void visit_before() {
533 lua_settop(lua_, top_);
534 if (!lua_istable(lua_, -1)) return;
535 lua_getfield(lua_, -1, "visit_before");
536 if (!lua_isfunction(lua_, -1)) return;
537 lua_pushvalue(lua_, -2);
538 lua_pcall(lua_, 1, 0, 0);
539 }
visit_after()540 void visit_after() {
541 lua_settop(lua_, top_);
542 if (!lua_istable(lua_, -1)) return;
543 lua_getfield(lua_, -1, "visit_after");
544 if (!lua_isfunction(lua_, -1)) return;
545 lua_pushvalue(lua_, -2);
546 lua_pcall(lua_, 1, 0, 0);
547 }
548 lua_State* lua_;
549 bool writable_;
550 int32_t top_;
551 };
552
553
554 /**
555 * Wrapper of a file processor.
556 */
557 class SoftFileProcessor : public kc::BasicDB::FileProcessor {
558 public:
SoftFileProcessor(lua_State * lua)559 explicit SoftFileProcessor(lua_State* lua) : lua_(lua) {}
560 private:
process(const std::string & path,int64_t count,int64_t size)561 bool process(const std::string& path, int64_t count, int64_t size) {
562 int32_t argc;
563 if (lua_istable(lua_, -1)) {
564 lua_getfield(lua_, -1, "process");
565 lua_pushvalue(lua_, -2);
566 lua_pushstring(lua_, path.c_str());
567 lua_pushnumber(lua_, count);
568 lua_pushnumber(lua_, size);
569 argc = 4;
570 } else {
571 lua_pushvalue(lua_, -1);
572 lua_pushstring(lua_, path.c_str());
573 lua_pushnumber(lua_, count);
574 lua_pushnumber(lua_, size);
575 argc = 3;
576 }
577 bool rv = false;
578 if (lua_pcall(lua_, argc, 1, 0) == 0) rv = lua_toboolean(lua_, -1);
579 return rv;
580 }
581 lua_State* lua_;
582 };
583
584
585 class SoftMapReduce : public kt::MapReduce {
586 public:
SoftMapReduce(lua_State * lua,int32_t logidx,int32_t procidx)587 SoftMapReduce(lua_State* lua, int32_t logidx, int32_t procidx) :
588 lua_(lua), logidx_(logidx), procidx_(procidx) {}
map(const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)589 bool map(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
590 int32_t top = lua_gettop(lua_);
591 lua_pushlightuserdata(lua_, (void*)this);
592 lua_setglobal(lua_, "__mr_self");
593 lua_pushvalue(lua_, 2);
594 lua_pushlstring(lua_, kbuf, ksiz);
595 lua_pushlstring(lua_, vbuf, vsiz);
596 lua_pushcfunction(lua_, db_mapreduce_emit);
597 bool rv;
598 if (lua_pcall(lua_, 3, 1, 0) == 0) {
599 rv = lua_toboolean(lua_, -1);
600 } else {
601 rv = false;
602 }
603 lua_settop(lua_, top);
604 return rv;
605 }
reduce(const char * kbuf,size_t ksiz,ValueIterator * iter)606 bool reduce(const char* kbuf, size_t ksiz, ValueIterator* iter) {
607 int32_t top = lua_gettop(lua_);
608 lua_pushlightuserdata(lua_, (void*)iter);
609 lua_setglobal(lua_, "__mr_iter");
610 lua_pushvalue(lua_, 3);
611 lua_pushlstring(lua_, kbuf, ksiz);
612 lua_pushcfunction(lua_, db_mapreduce_iter);
613 bool rv;
614 if (lua_pcall(lua_, 2, 1, 0) == 0) {
615 rv = lua_toboolean(lua_, -1);
616 } else {
617 rv = false;
618 }
619 lua_settop(lua_, top);
620 return rv;
621 }
log(const char * name,const char * message)622 bool log(const char* name, const char* message) {
623 if (logidx_ < 1) return true;
624 int32_t top = lua_gettop(lua_);
625 lua_pushvalue(lua_, logidx_);
626 lua_pushstring(lua_, name);
627 lua_pushstring(lua_, message);
628 bool rv;
629 if (lua_pcall(lua_, 2, 1, 0) == 0) {
630 rv = lua_toboolean(lua_, -1);
631 } else {
632 rv = false;
633 }
634 lua_settop(lua_, top);
635 return rv;
636 }
preprocess()637 bool preprocess() {
638 if (procidx_ < 1) return true;
639 int32_t top = lua_gettop(lua_);
640 lua_pushlightuserdata(lua_, (void*)this);
641 lua_setglobal(lua_, "__mr_self");
642 lua_pushvalue(lua_, procidx_);
643 lua_pushcfunction(lua_, db_mapreduce_emit);
644 bool rv;
645 if (lua_pcall(lua_, 1, 1, 0) == 0) {
646 rv = lua_toboolean(lua_, -1);
647 } else {
648 rv = false;
649 }
650 lua_settop(lua_, top);
651 return rv;
652 }
midprocess()653 bool midprocess() {
654 return preprocess();
655 }
postprocess()656 bool postprocess() {
657 if (procidx_ < 1) return true;
658 int32_t top = lua_gettop(lua_);
659 lua_pushlightuserdata(lua_, (void*)this);
660 lua_setglobal(lua_, "__mr_self");
661 lua_pushvalue(lua_, procidx_);
662 bool rv;
663 if (lua_pcall(lua_, 0, 1, 0) == 0) {
664 rv = lua_toboolean(lua_, -1);
665 } else {
666 rv = false;
667 }
668 lua_settop(lua_, top);
669 return rv;
670 }
emit_public(const char * kbuf,size_t ksiz,const char * vbuf,size_t vsiz)671 bool emit_public(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) {
672 return emit(kbuf, ksiz, vbuf, vsiz);
673 }
674 private:
675 lua_State* lua_;
676 int32_t logidx_;
677 int32_t procidx_;
678 };
679
680
681 /**
682 * Report error information.
683 */
reporterror(ScriptProcessorCore * core,const char * name)684 static void reporterror(ScriptProcessorCore* core, const char* name) {
685 lua_State* lua = core->lua;
686 int argc = lua_gettop(lua);
687 core->serv->log(kt::RPCServer::Logger::ERROR, "[SCRIPT]: %s: %s",
688 name, argc > 0 ? lua_tostring(lua, argc) : "unknown");
689 }
690
691
692 /**
693 * Throw the invalid argument error.
694 */
throwinvarg(lua_State * lua,const char * func)695 static void throwinvarg(lua_State* lua, const char* func) {
696 char msg[256];
697 size_t len = std::sprintf(msg, "%s: invalid arguments", func);
698 lua_pushlstring(lua, msg, len);
699 lua_error(lua);
700 }
701
702
703 /**
704 * Set a field of unsigned integer.
705 */
setfielduint(lua_State * lua,const char * name,uint32_t num)706 static void setfielduint(lua_State* lua, const char* name, uint32_t num) {
707 lua_pushinteger(lua, num);
708 lua_setfield(lua, -2, name);
709 }
710
711
712 /**
713 * Set a field of string.
714 */
setfieldstr(lua_State * lua,const char * name,const char * str)715 static void setfieldstr(lua_State* lua, const char* name, const char* str) {
716 lua_pushstring(lua, str);
717 lua_setfield(lua, -2, name);
718 }
719
720
721 /**
722 * Set a field of function.
723 */
setfieldfunc(lua_State * lua,const char * name,lua_CFunction func)724 static void setfieldfunc(lua_State* lua, const char* name, lua_CFunction func) {
725 lua_pushcfunction(lua, func);
726 lua_setfield(lua, -2, name);
727 }
728
729
730 /**
731 * Set a field of stacked value.
732 */
setfieldvalue(lua_State * lua,const char * name,int32_t index)733 static void setfieldvalue(lua_State* lua, const char* name, int32_t index) {
734 lua_pushvalue(lua, index);
735 lua_setfield(lua, -2, name);
736 }
737
738
739 /**
740 * Define objects of the module.
741 */
define_module(lua_State * lua)742 static void define_module(lua_State* lua) {
743 setfieldfunc(lua, "atoi", kt_atoi);
744 setfieldfunc(lua, "atoix", kt_atoix);
745 setfieldfunc(lua, "atof", kt_atof);
746 setfieldfunc(lua, "hash_murmur", kt_hash_murmur);
747 setfieldfunc(lua, "hash_fnv", kt_hash_fnv);
748 setfieldfunc(lua, "levdist", kt_levdist);
749 setfieldfunc(lua, "time", kt_time);
750 setfieldfunc(lua, "sleep", kt_sleep);
751 setfieldfunc(lua, "pack", kt_pack);
752 setfieldfunc(lua, "unpack", kt_unpack);
753 setfieldfunc(lua, "split", kt_split);
754 setfieldfunc(lua, "codec", kt_codec);
755 setfieldfunc(lua, "bit", kt_bit);
756 setfieldfunc(lua, "strstr", kt_strstr);
757 setfieldfunc(lua, "strfwm", kt_strfwm);
758 setfieldfunc(lua, "strbwm", kt_strbwm);
759 setfieldfunc(lua, "regex", kt_regex);
760 setfieldfunc(lua, "arraydump", kt_arraydump);
761 setfieldfunc(lua, "arrayload", kt_arrayload);
762 setfieldfunc(lua, "mapdump", kt_mapdump);
763 setfieldfunc(lua, "mapload", kt_mapload);
764 }
765
766
767 /**
768 * Implementation of atoi.
769 */
kt_atoi(lua_State * lua)770 static int kt_atoi(lua_State* lua) {
771 int32_t argc = lua_gettop(lua);
772 if (argc != 1) throwinvarg(lua, __KCFUNC__);
773 const char* str = lua_tostring(lua, 1);
774 if (!str) return 0;
775 lua_pushnumber(lua, kc::atoi(str));
776 return 1;
777 }
778
779
780 /**
781 * Implementation of atoix.
782 */
kt_atoix(lua_State * lua)783 static int kt_atoix(lua_State* lua) {
784 int32_t argc = lua_gettop(lua);
785 if (argc != 1) throwinvarg(lua, __KCFUNC__);
786 const char* str = lua_tostring(lua, 1);
787 if (!str) return 0;
788 lua_pushnumber(lua, kc::atoix(str));
789 return 1;
790 }
791
792
793 /**
794 * Implementation of atof.
795 */
kt_atof(lua_State * lua)796 static int kt_atof(lua_State* lua) {
797 int32_t argc = lua_gettop(lua);
798 if (argc != 1) throwinvarg(lua, __KCFUNC__);
799 const char* str = lua_tostring(lua, 1);
800 if (!str) return 0;
801 lua_pushnumber(lua, kc::atof(str));
802 return 1;
803 }
804
805
806 /**
807 * Implementation of hash_murmur.
808 */
kt_hash_murmur(lua_State * lua)809 static int kt_hash_murmur(lua_State* lua) {
810 int32_t argc = lua_gettop(lua);
811 if (argc != 1) throwinvarg(lua, __KCFUNC__);
812 size_t len;
813 const char* str = lua_tolstring(lua, 1, &len);
814 if (!str) return 0;
815 lua_pushinteger(lua, kc::hashmurmur(str, len) & ((1ULL << 48) - 1));
816 return 1;
817 }
818
819
820 /**
821 * Implementation of hash_fnv.
822 */
kt_hash_fnv(lua_State * lua)823 static int kt_hash_fnv(lua_State* lua) {
824 int32_t argc = lua_gettop(lua);
825 if (argc != 1) throwinvarg(lua, __KCFUNC__);
826 size_t len;
827 const char* str = lua_tolstring(lua, 1, &len);
828 if (!str) return 0;
829 lua_pushinteger(lua, kc::hashfnv(str, len) & ((1ULL << 48) - 1));
830 return 1;
831 }
832
833
834 /**
835 * Implementation of levdist.
836 */
kt_levdist(lua_State * lua)837 static int kt_levdist(lua_State* lua) {
838 int32_t argc = lua_gettop(lua);
839 if (argc < 2) throwinvarg(lua, __KCFUNC__);
840 size_t asiz;
841 const char* abuf = lua_tolstring(lua, 1, &asiz);
842 size_t bsiz;
843 const char* bbuf = lua_tolstring(lua, 2, &bsiz);
844 if (!abuf || !bbuf) throwinvarg(lua, __KCFUNC__);
845 bool utf = argc > 2 ? lua_toboolean(lua, 3) : false;
846 size_t dist;
847 if (utf) {
848 uint32_t astack[128];
849 uint32_t* aary = asiz > sizeof(astack) / sizeof(*astack) ? new uint32_t[asiz] : astack;
850 size_t anum;
851 kc::strutftoucs(abuf, asiz, aary, &anum);
852 uint32_t bstack[128];
853 uint32_t* bary = bsiz > sizeof(bstack) / sizeof(*bstack) ? new uint32_t[bsiz] : bstack;
854 size_t bnum;
855 kc::strutftoucs(bbuf, bsiz, bary, &bnum);
856 dist = kc::strucsdist(aary, anum, bary, bnum);
857 if (bary != bstack) delete[] bary;
858 if (aary != astack) delete[] aary;
859 } else {
860 dist = kc::memdist(abuf, asiz, bbuf, bsiz);
861 }
862 lua_pushinteger(lua, dist);
863 return 1;
864 }
865
866
867 /**
868 * Implementation of hash_fnv.
869 */
kt_time(lua_State * lua)870 static int kt_time(lua_State* lua) {
871 int32_t argc = lua_gettop(lua);
872 if (argc != 0) throwinvarg(lua, __KCFUNC__);
873 lua_pushnumber(lua, kc::time());
874 return 1;
875 }
876
877
878 /**
879 * Implementation of sleep.
880 */
kt_sleep(lua_State * lua)881 static int kt_sleep(lua_State* lua) {
882 int32_t argc = lua_gettop(lua);
883 if (argc > 1) throwinvarg(lua, __KCFUNC__);
884 double sec = argc > 0 ? lua_tonumber(lua, 1) : 0;
885 if (sec > 0) {
886 kc::Thread::sleep(sec);
887 } else {
888 kc::Thread::yield();
889 }
890 return 0;
891 }
892
893
894 /**
895 * Implementation of pack.
896 */
kt_pack(lua_State * lua)897 static int kt_pack(lua_State* lua) {
898 int32_t argc = lua_gettop(lua);
899 if (argc < 1) throwinvarg(lua, __KCFUNC__);
900 const char* format = lua_tostring(lua, 1);
901 if (!format) throwinvarg(lua, __KCFUNC__);
902 lua_newtable(lua);
903 int32_t aidx = argc + 1;
904 int32_t eidx = 1;
905 for (int32_t i = 2; i <= argc; i++) {
906 size_t len;
907 switch (lua_type(lua, i)) {
908 case LUA_TNUMBER: case LUA_TSTRING: {
909 lua_pushvalue(lua, i);
910 lua_rawseti(lua, aidx, eidx++);
911 break;
912 }
913 case LUA_TTABLE: {
914 len = lua_objlen(lua, i);
915 for (size_t j = 1; j <= len; j++) {
916 lua_rawgeti(lua, i, j);
917 lua_rawseti(lua, aidx, eidx++);
918 }
919 break;
920 }
921 default: {
922 lua_pushnumber(lua, 0);
923 lua_rawseti(lua, aidx, eidx++);
924 break;
925 }
926 }
927 }
928 lua_replace(lua, 2);
929 lua_settop(lua, 2);
930 std::string xstr;
931 int32_t emax = eidx - 1;
932 eidx = 1;
933 while (*format != '\0') {
934 int32_t c = *format;
935 int32_t loop = 1;
936 if (format[1] == '*') {
937 loop = kc::INT32MAX;
938 format++;
939 } else if (format[1] >= '0' && format[1] <= '9') {
940 char* suffix;
941 loop = std::strtol(format + 1, &suffix, 10);
942 format = suffix - 1;
943 }
944 loop = loop < emax ? loop : emax;
945 int32_t end = eidx + loop - 1;
946 if (end > emax) end = emax;
947 while (eidx <= end) {
948 lua_rawgeti(lua, 2, eidx);
949 double num = lua_tonumber(lua, 3);
950 lua_pop(lua, 1);
951 uint8_t cnum;
952 uint16_t snum;
953 uint32_t inum;
954 uint64_t lnum;
955 double dnum;
956 float fnum;
957 uint64_t wnum;
958 char wbuf[kc::NUMBUFSIZ], *wp;
959 switch (c) {
960 case 'c': case 'C': {
961 cnum = num;
962 xstr.append((char*)&cnum, sizeof(cnum));
963 break;
964 }
965 case 's': case 'S': {
966 snum = num;
967 xstr.append((char*)&snum, sizeof(snum));
968 break;
969 }
970 case 'i': case 'I': {
971 inum = num;
972 xstr.append((char*)&inum, sizeof(inum));
973 break;
974 }
975 case 'l': case 'L': {
976 lnum = num;
977 xstr.append((char*)&lnum, sizeof(lnum));
978 break;
979 }
980 case 'f': case 'F': {
981 fnum = num;
982 xstr.append((char*)&fnum, sizeof(fnum));
983 break;
984 }
985 case 'd': case 'D': {
986 dnum = num;
987 xstr.append((char*)&dnum, sizeof(dnum));
988 break;
989 }
990 case 'n': {
991 snum = num;
992 snum = kc::hton16(snum);
993 xstr.append((char*)&snum, sizeof(snum));
994 break;
995 }
996 case 'N': {
997 inum = num;
998 inum = kc::hton32(inum);
999 xstr.append((char*)&inum, sizeof(inum));
1000 break;
1001 }
1002 case 'M': {
1003 lnum = num;
1004 lnum = kc::hton64(lnum);
1005 xstr.append((char*)&lnum, sizeof(lnum));
1006 break;
1007 }
1008 case 'w': case 'W': {
1009 wnum = num;
1010 wp = wbuf;
1011 if (wnum < (1ULL << 7)) {
1012 *(wp++) = wnum;
1013 } else if (wnum < (1ULL << 14)) {
1014 *(wp++) = (wnum >> 7) | 0x80;
1015 *(wp++) = wnum & 0x7f;
1016 } else if (wnum < (1ULL << 21)) {
1017 *(wp++) = (wnum >> 14) | 0x80;
1018 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1019 *(wp++) = wnum & 0x7f;
1020 } else if (wnum < (1ULL << 28)) {
1021 *(wp++) = (wnum >> 21) | 0x80;
1022 *(wp++) = ((wnum >> 14) & 0x7f) | 0x80;
1023 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1024 *(wp++) = wnum & 0x7f;
1025 } else if (wnum < (1ULL << 35)) {
1026 *(wp++) = (wnum >> 28) | 0x80;
1027 *(wp++) = ((wnum >> 21) & 0x7f) | 0x80;
1028 *(wp++) = ((wnum >> 14) & 0x7f) | 0x80;
1029 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1030 *(wp++) = wnum & 0x7f;
1031 } else if (wnum < (1ULL << 42)) {
1032 *(wp++) = (wnum >> 35) | 0x80;
1033 *(wp++) = ((wnum >> 28) & 0x7f) | 0x80;
1034 *(wp++) = ((wnum >> 21) & 0x7f) | 0x80;
1035 *(wp++) = ((wnum >> 14) & 0x7f) | 0x80;
1036 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1037 *(wp++) = wnum & 0x7f;
1038 } else if (wnum < (1ULL << 49)) {
1039 *(wp++) = (wnum >> 42) | 0x80;
1040 *(wp++) = ((wnum >> 35) & 0x7f) | 0x80;
1041 *(wp++) = ((wnum >> 28) & 0x7f) | 0x80;
1042 *(wp++) = ((wnum >> 21) & 0x7f) | 0x80;
1043 *(wp++) = ((wnum >> 14) & 0x7f) | 0x80;
1044 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1045 *(wp++) = wnum & 0x7f;
1046 } else if (wnum < (1ULL << 56)) {
1047 *(wp++) = (wnum >> 49) | 0x80;
1048 *(wp++) = ((wnum >> 42) & 0x7f) | 0x80;
1049 *(wp++) = ((wnum >> 35) & 0x7f) | 0x80;
1050 *(wp++) = ((wnum >> 28) & 0x7f) | 0x80;
1051 *(wp++) = ((wnum >> 21) & 0x7f) | 0x80;
1052 *(wp++) = ((wnum >> 14) & 0x7f) | 0x80;
1053 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1054 *(wp++) = wnum & 0x7f;
1055 } else {
1056 *(wp++) = (wnum >> 63) | 0x80;
1057 *(wp++) = ((wnum >> 49) & 0x7f) | 0x80;
1058 *(wp++) = ((wnum >> 42) & 0x7f) | 0x80;
1059 *(wp++) = ((wnum >> 35) & 0x7f) | 0x80;
1060 *(wp++) = ((wnum >> 28) & 0x7f) | 0x80;
1061 *(wp++) = ((wnum >> 21) & 0x7f) | 0x80;
1062 *(wp++) = ((wnum >> 14) & 0x7f) | 0x80;
1063 *(wp++) = ((wnum >> 7) & 0x7f) | 0x80;
1064 *(wp++) = wnum & 0x7f;
1065 }
1066 xstr.append(wbuf, wp - wbuf);
1067 break;
1068 }
1069 }
1070 eidx++;
1071 }
1072 format++;
1073 if (eidx > emax) break;
1074 }
1075 lua_pushlstring(lua, xstr.data(), xstr.size());
1076 return 1;
1077 }
1078
1079
1080 /**
1081 * Implementation of unpack.
1082 */
kt_unpack(lua_State * lua)1083 static int kt_unpack(lua_State *lua) {
1084 int32_t argc = lua_gettop(lua);
1085 if (argc != 2) throwinvarg(lua, __KCFUNC__);
1086 const char* format = lua_tostring(lua, 1);
1087 size_t size;
1088 const char* buf = lua_tolstring(lua, 2, &size);
1089 if (!format) throwinvarg(lua, __KCFUNC__);
1090 if (!buf) {
1091 buf = "";
1092 size = 0;
1093 }
1094 lua_newtable(lua);
1095 const char* rp = buf;
1096 int32_t eidx = 1;
1097 while (*format != '\0') {
1098 int32_t c = *format;
1099 int32_t loop = 1;
1100 if (format[1] == '*') {
1101 loop = kc::INT32MAX;
1102 format++;
1103 } else if (format[1] >= '0' && format[1] <= '9') {
1104 char* suffix;
1105 loop = strtol(format + 1, &suffix, 10);
1106 format = suffix - 1;
1107 }
1108 loop = loop < (int32_t)size ? loop : size;
1109 for (int32_t i = 0; i < loop && size > 0; i++) {
1110 uint8_t cnum;
1111 uint16_t snum;
1112 uint32_t inum;
1113 uint64_t lnum;
1114 float fnum;
1115 double dnum;
1116 uint64_t wnum;
1117 switch (c) {
1118 case 'c': {
1119 if (size >= sizeof(cnum)) {
1120 std::memcpy(&cnum, rp, sizeof(cnum));
1121 lua_pushnumber(lua, (int8_t)cnum);
1122 lua_rawseti(lua, 3, eidx++);
1123 rp += sizeof(cnum);
1124 size -= sizeof(cnum);
1125 } else {
1126 size = 0;
1127 }
1128 break;
1129 }
1130 case 'C': {
1131 if (size >= sizeof(cnum)) {
1132 std::memcpy(&cnum, rp, sizeof(cnum));
1133 lua_pushnumber(lua, (uint8_t)cnum);
1134 lua_rawseti(lua, 3, eidx++);
1135 rp += sizeof(cnum);
1136 size -= sizeof(cnum);
1137 } else {
1138 size = 0;
1139 }
1140 break;
1141 }
1142 case 's': {
1143 if (size >= sizeof(snum)) {
1144 std::memcpy(&snum, rp, sizeof(snum));
1145 lua_pushnumber(lua, (int16_t)snum);
1146 lua_rawseti(lua, 3, eidx++);
1147 rp += sizeof(snum);
1148 size -= sizeof(snum);
1149 } else {
1150 size = 0;
1151 }
1152 break;
1153 }
1154 case 'S': {
1155 if (size >= sizeof(snum)) {
1156 std::memcpy(&snum, rp, sizeof(snum));
1157 lua_pushnumber(lua, (uint16_t)snum);
1158 lua_rawseti(lua, 3, eidx++);
1159 rp += sizeof(snum);
1160 size -= sizeof(snum);
1161 } else {
1162 size = 0;
1163 }
1164 break;
1165 }
1166 case 'i': {
1167 if (size >= sizeof(inum)) {
1168 std::memcpy(&inum, rp, sizeof(inum));
1169 lua_pushnumber(lua, (int32_t)inum);
1170 lua_rawseti(lua, 3, eidx++);
1171 rp += sizeof(inum);
1172 size -= sizeof(inum);
1173 } else {
1174 size = 0;
1175 }
1176 break;
1177 }
1178 case 'I': {
1179 if (size >= sizeof(inum)) {
1180 std::memcpy(&inum, rp, sizeof(inum));
1181 lua_pushnumber(lua, (uint32_t)inum);
1182 lua_rawseti(lua, 3, eidx++);
1183 rp += sizeof(inum);
1184 size -= sizeof(inum);
1185 } else {
1186 size = 0;
1187 }
1188 break;
1189 }
1190 case 'l': {
1191 if (size >= sizeof(lnum)) {
1192 std::memcpy(&lnum, rp, sizeof(lnum));
1193 lua_pushnumber(lua, (int64_t)lnum);
1194 lua_rawseti(lua, 3, eidx++);
1195 rp += sizeof(lnum);
1196 size -= sizeof(lnum);
1197 } else {
1198 size = 0;
1199 }
1200 break;
1201 }
1202 case 'L': {
1203 if (size >= sizeof(lnum)) {
1204 std::memcpy(&lnum, rp, sizeof(lnum));
1205 lua_pushnumber(lua, (uint64_t)lnum);
1206 lua_rawseti(lua, 3, eidx++);
1207 rp += sizeof(lnum);
1208 size -= sizeof(lnum);
1209 } else {
1210 size = 0;
1211 }
1212 break;
1213 }
1214 case 'f': case 'F': {
1215 if (size >= sizeof(fnum)) {
1216 std::memcpy(&fnum, rp, sizeof(fnum));
1217 lua_pushnumber(lua, (float)fnum);
1218 lua_rawseti(lua, 3, eidx++);
1219 rp += sizeof(fnum);
1220 size -= sizeof(fnum);
1221 } else {
1222 size = 0;
1223 }
1224 break;
1225 }
1226 case 'd': case 'D': {
1227 if (size >= sizeof(dnum)) {
1228 std::memcpy(&dnum, rp, sizeof(dnum));
1229 lua_pushnumber(lua, (double)dnum);
1230 lua_rawseti(lua, 3, eidx++);
1231 rp += sizeof(dnum);
1232 size -= sizeof(dnum);
1233 } else {
1234 size = 0;
1235 }
1236 break;
1237 }
1238 case 'n': {
1239 if (size >= sizeof(snum)) {
1240 std::memcpy(&snum, rp, sizeof(snum));
1241 snum = kc::ntoh16(snum);
1242 lua_pushnumber(lua, (uint16_t)snum);
1243 lua_rawseti(lua, 3, eidx++);
1244 rp += sizeof(snum);
1245 size -= sizeof(snum);
1246 } else {
1247 size = 0;
1248 }
1249 break;
1250 }
1251 case 'N': {
1252 if (size >= sizeof(inum)) {
1253 std::memcpy(&inum, rp, sizeof(inum));
1254 inum = kc::ntoh32(inum);
1255 lua_pushnumber(lua, (uint32_t)inum);
1256 lua_rawseti(lua, 3, eidx++);
1257 rp += sizeof(inum);
1258 size -= sizeof(inum);
1259 } else {
1260 size = 0;
1261 }
1262 break;
1263 }
1264 case 'M': {
1265 if (size >= sizeof(lnum)) {
1266 std::memcpy(&lnum, rp, sizeof(lnum));
1267 lnum = kc::ntoh64(lnum);
1268 lua_pushnumber(lua, (uint64_t)lnum);
1269 lua_rawseti(lua, 3, eidx++);
1270 rp += sizeof(lnum);
1271 size -= sizeof(lnum);
1272 } else {
1273 size = 0;
1274 }
1275 break;
1276 }
1277 case 'w': case 'W': {
1278 wnum = 0;
1279 do {
1280 inum = *(unsigned char*)rp;
1281 wnum = wnum * 0x80 + (inum & 0x7f);
1282 rp++;
1283 size--;
1284 } while (inum >= 0x80 && size > 0);
1285 lua_pushnumber(lua, (uint64_t)wnum);
1286 lua_rawseti(lua, 3, eidx++);
1287 break;
1288 }
1289 }
1290 }
1291 format++;
1292 if (size < 1) break;
1293 }
1294 return 1;
1295 }
1296
1297
1298 /**
1299 * Implementation of split.
1300 */
kt_split(lua_State * lua)1301 static int kt_split(lua_State *lua) {
1302 int32_t argc = lua_gettop(lua);
1303 if (argc < 1) throwinvarg(lua, __KCFUNC__);
1304 size_t isiz;
1305 const char* ibuf = lua_tolstring(lua, 1, &isiz);
1306 if (!ibuf) throwinvarg(lua, __KCFUNC__);
1307 const char* delims = argc > 1 ? lua_tostring(lua, 2) : NULL;
1308 lua_newtable(lua);
1309 int32_t lnum = 1;
1310 if (delims) {
1311 const char* str = ibuf;
1312 while (true) {
1313 const char* sp = str;
1314 while (*str != '\0' && !std::strchr(delims, *str)) {
1315 str++;
1316 }
1317 lua_pushlstring(lua, sp, str - sp);
1318 lua_rawseti(lua, -2, lnum++);
1319 if (*str == '\0') break;
1320 str++;
1321 }
1322 } else {
1323 const char* ptr = ibuf;
1324 int32_t size = isiz;
1325 while (size >= 0) {
1326 const char* rp = ptr;
1327 const char* ep = ptr + size;
1328 while (rp < ep) {
1329 if (*rp == '\0') break;
1330 rp++;
1331 }
1332 lua_pushlstring(lua, ptr, rp - ptr);
1333 lua_rawseti(lua, -2, lnum++);
1334 rp++;
1335 size -= rp - ptr;
1336 ptr = rp;
1337 }
1338 }
1339 return 1;
1340 }
1341
1342
1343 /**
1344 * Implementation of codec.
1345 */
kt_codec(lua_State * lua)1346 static int kt_codec(lua_State *lua) {
1347 int32_t argc = lua_gettop(lua);
1348 if (argc != 2) throwinvarg(lua, __KCFUNC__);
1349 const char* mode = lua_tostring(lua, 1);
1350 size_t isiz;
1351 const char* ibuf = lua_tolstring(lua, 2, &isiz);
1352 if (!mode || !ibuf) throwinvarg(lua, __KCFUNC__);
1353 char* obuf = NULL;
1354 size_t osiz = 0;
1355 if (*mode == '~') {
1356 mode++;
1357 if (!kc::stricmp(mode, "url")) {
1358 obuf = kc::urldecode(ibuf, &osiz);
1359 } else if (!kc::stricmp(mode, "base")) {
1360 obuf = kc::basedecode(ibuf, &osiz);
1361 } else if (!kc::stricmp(mode, "quote")) {
1362 obuf = kc::quotedecode(ibuf, &osiz);
1363 } else if (!kc::stricmp(mode, "hex")) {
1364 obuf = kc::hexdecode(ibuf, &osiz);
1365 } else if (!kc::stricmp(mode, "zlib")) {
1366 obuf = kc::ZLIB::decompress(ibuf, isiz, &osiz, kc::ZLIB::RAW);
1367 } else if (!kc::stricmp(mode, "deflate")) {
1368 obuf = kc::ZLIB::decompress(ibuf, isiz, &osiz, kc::ZLIB::DEFLATE);
1369 } else if (!kc::stricmp(mode, "gzip")) {
1370 obuf = kc::ZLIB::decompress(ibuf, isiz, &osiz, kc::ZLIB::GZIP);
1371 }
1372 } else {
1373 if (!kc::stricmp(mode, "url")) {
1374 obuf = kc::urlencode(ibuf, isiz);
1375 osiz = obuf ? std::strlen(obuf) : 0;
1376 } else if (!kc::stricmp(mode, "base")) {
1377 obuf = kc::baseencode(ibuf, isiz);
1378 osiz = obuf ? std::strlen(obuf) : 0;
1379 } else if (!kc::stricmp(mode, "quote")) {
1380 obuf = kc::quoteencode(ibuf, isiz);
1381 osiz = obuf ? std::strlen(obuf) : 0;
1382 } else if (!kc::stricmp(mode, "hex")) {
1383 obuf = kc::hexencode(ibuf, isiz);
1384 osiz = obuf ? std::strlen(obuf) : 0;
1385 } else if (!kc::stricmp(mode, "zlib")) {
1386 obuf = kc::ZLIB::compress(ibuf, isiz, &osiz, kc::ZLIB::RAW);
1387 } else if (!kc::stricmp(mode, "deflate")) {
1388 obuf = kc::ZLIB::compress(ibuf, isiz, &osiz, kc::ZLIB::DEFLATE);
1389 } else if (!kc::stricmp(mode, "gzip")) {
1390 obuf = kc::ZLIB::compress(ibuf, isiz, &osiz, kc::ZLIB::GZIP);
1391 }
1392 }
1393 if (obuf) {
1394 lua_pushlstring(lua, obuf, osiz);
1395 delete[] obuf;
1396 } else {
1397 lua_pushnil(lua);
1398 }
1399 return 1;
1400 }
1401
1402
1403 /**
1404 * Implementation of bit.
1405 */
kt_bit(lua_State * lua)1406 static int kt_bit(lua_State *lua) {
1407 int32_t argc = lua_gettop(lua);
1408 if (argc < 2) throwinvarg(lua, __KCFUNC__);
1409 const char* mode = lua_tostring(lua, 1);
1410 uint32_t num = lua_tonumber(lua, 2);
1411 uint32_t aux = argc > 2 ? lua_tonumber(lua, 3) : 0;
1412 if (!mode) throwinvarg(lua, __KCFUNC__);
1413 if (!kc::stricmp(mode, "and")) {
1414 num &= aux;
1415 } else if (!kc::stricmp(mode, "or")) {
1416 num |= aux;
1417 } else if (!kc::stricmp(mode, "xor")) {
1418 num ^= aux;
1419 } else if (!kc::stricmp(mode, "not")) {
1420 num = ~num;
1421 } else if (!kc::stricmp(mode, "left")) {
1422 num <<= aux;
1423 } else if (!kc::stricmp(mode, "right")) {
1424 num >>= aux;
1425 }
1426 lua_pushnumber(lua, num);
1427 return 1;
1428 }
1429
1430
1431 /**
1432 * Implementation of strstr.
1433 */
kt_strstr(lua_State * lua)1434 static int kt_strstr(lua_State *lua) {
1435 int32_t argc = lua_gettop(lua);
1436 if (argc < 2) throwinvarg(lua, __KCFUNC__);
1437 const char* str = lua_tostring(lua, 1);
1438 const char* pat = lua_tostring(lua, 2);
1439 if (!str || !pat) throwinvarg(lua, __KCFUNC__);
1440 const char* alt = argc > 2 ? lua_tostring(lua, 3) : NULL;
1441 if (alt) {
1442 std::string xstr;
1443 size_t plen = std::strlen(pat);
1444 size_t alen = std::strlen(alt);
1445 if (plen > 0) {
1446 const char* pv;
1447 while ((pv = std::strstr(str, pat)) != NULL) {
1448 xstr.append(str, pv - str);
1449 xstr.append(alt, alen);
1450 str = pv + plen;
1451 }
1452 }
1453 xstr.append(str);
1454 lua_pushlstring(lua, xstr.data(), xstr.size());
1455 } else {
1456 const char* pv = std::strstr(str, pat);
1457 if (pv) {
1458 int32_t idx = pv - str + 1;
1459 lua_pushinteger(lua, idx);
1460 } else {
1461 lua_pushinteger(lua, 0);
1462 }
1463 }
1464 return 1;
1465 }
1466
1467
1468 /**
1469 * Implementation of strfwm.
1470 */
kt_strfwm(lua_State * lua)1471 static int kt_strfwm(lua_State *lua) {
1472 int32_t argc = lua_gettop(lua);
1473 if (argc < 2) throwinvarg(lua, __KCFUNC__);
1474 const char* str = lua_tostring(lua, 1);
1475 const char* pat = lua_tostring(lua, 2);
1476 if (!str || !pat) throwinvarg(lua, __KCFUNC__);
1477 lua_pushboolean(lua, kc::strfwm(str, pat));
1478 return 1;
1479 }
1480
1481
1482 /**
1483 * Implementation of strbwm.
1484 */
kt_strbwm(lua_State * lua)1485 static int kt_strbwm(lua_State *lua) {
1486 int32_t argc = lua_gettop(lua);
1487 if (argc < 2) throwinvarg(lua, __KCFUNC__);
1488 const char* str = lua_tostring(lua, 1);
1489 const char* pat = lua_tostring(lua, 2);
1490 if (!str || !pat) throwinvarg(lua, __KCFUNC__);
1491 lua_pushboolean(lua, kc::strbwm(str, pat));
1492 return 1;
1493 }
1494
1495
1496 /**
1497 * Implementation of regex.
1498 */
kt_regex(lua_State * lua)1499 static int kt_regex(lua_State *lua) {
1500 int32_t argc = lua_gettop(lua);
1501 if (argc < 2) throwinvarg(lua, __KCFUNC__);
1502 const char* str = lua_tostring(lua, 1);
1503 const char* pat = lua_tostring(lua, 2);
1504 if (!str || !pat) throwinvarg(lua, __KCFUNC__);
1505 const char* alt = argc > 2 ? lua_tostring(lua, 3) : NULL;
1506 if (alt) {
1507 std::string xstr = kc::Regex::replace(str, pat, alt);
1508 lua_pushlstring(lua, xstr.data(), xstr.size());
1509 } else {
1510 bool rv = kc::Regex::match(str, pat);
1511 lua_pushboolean(lua, rv);
1512 }
1513 return 1;
1514 }
1515
1516
1517 /**
1518 * Implementation of arraydump.
1519 */
kt_arraydump(lua_State * lua)1520 static int kt_arraydump(lua_State *lua) {
1521 int32_t argc = lua_gettop(lua);
1522 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1523 size_t rnum = lua_objlen(lua, 1);
1524 std::string rstr;
1525 rstr.reserve(rnum * 16 + 256);
1526 for (size_t i = 1; i <= rnum; i++) {
1527 lua_rawgeti(lua, 1, i);
1528 char vnbuf[kc::NUMBUFSIZ];
1529 const char* vbuf = NULL;
1530 size_t vsiz = 0;
1531 switch (lua_type(lua, -1)) {
1532 case LUA_TNUMBER: {
1533 double num = lua_tonumber(lua, -1);
1534 if (num == std::floor(num)) {
1535 vsiz = std::sprintf(vnbuf, "%lld", (long long)num);
1536 } else {
1537 vsiz = std::snprintf(vnbuf, sizeof(vnbuf), "%.6f", num);
1538 vnbuf[sizeof(vnbuf)-1] = '\0';
1539 }
1540 vbuf = vnbuf;
1541 break;
1542 }
1543 case LUA_TSTRING: {
1544 vbuf = lua_tolstring(lua, -1, &vsiz);
1545 break;
1546 }
1547 }
1548 if (vbuf) {
1549 char nbuf[kc::NUMBUFSIZ];
1550 size_t nsiz = kc::writevarnum(nbuf, vsiz);
1551 rstr.append(nbuf, nsiz);
1552 rstr.append(vbuf, vsiz);
1553 }
1554 lua_pop(lua, 1);
1555 }
1556 lua_pushlstring(lua, rstr.data(), rstr.size());
1557 return 1;
1558 }
1559
1560
1561 /**
1562 * Implementation of arrayload.
1563 */
kt_arrayload(lua_State * lua)1564 static int kt_arrayload(lua_State *lua) {
1565 int32_t argc = lua_gettop(lua);
1566 if (argc != 1) throwinvarg(lua, __KCFUNC__);
1567 size_t size;
1568 const char* rp = lua_tolstring(lua, 1, &size);
1569 if (!rp) throwinvarg(lua, __KCFUNC__);
1570 lua_newtable(lua);
1571 int32_t idx = 1;
1572 while (size > 0) {
1573 uint64_t vsiz;
1574 size_t step = kc::readvarnum(rp, size, &vsiz);
1575 rp += step;
1576 size -= step;
1577 if (vsiz > size) break;
1578 lua_pushlstring(lua, rp, vsiz);
1579 lua_rawseti(lua, -2, idx++);
1580 rp += vsiz;
1581 size -= vsiz;
1582 }
1583 return 1;
1584 }
1585
1586
1587 /**
1588 * Implementation of mapdump.
1589 */
kt_mapdump(lua_State * lua)1590 static int kt_mapdump(lua_State *lua) {
1591 int32_t argc = lua_gettop(lua);
1592 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1593 std::string rstr;
1594 rstr.reserve(512);
1595 lua_pushnil(lua);
1596 while (lua_next(lua, 1) != 0) {
1597 char knbuf[kc::NUMBUFSIZ];
1598 const char* kbuf = NULL;
1599 size_t ksiz = 0;
1600 switch (lua_type(lua, -2)) {
1601 case LUA_TNUMBER: {
1602 double num = lua_tonumber(lua, -2);
1603 if (num == std::floor(num)) {
1604 ksiz = std::sprintf(knbuf, "%lld", (long long)num);
1605 } else {
1606 ksiz = std::snprintf(knbuf, sizeof(knbuf), "%.6f", num);
1607 knbuf[sizeof(knbuf)-1] = '\0';
1608 }
1609 kbuf = knbuf;
1610 break;
1611 }
1612 case LUA_TSTRING: {
1613 kbuf = lua_tolstring(lua, -2, &ksiz);
1614 break;
1615 }
1616 }
1617 char vnbuf[kc::NUMBUFSIZ];
1618 const char* vbuf = NULL;
1619 size_t vsiz = 0;
1620 switch (lua_type(lua, -1)) {
1621 case LUA_TNUMBER: {
1622 double num = lua_tonumber(lua, -1);
1623 if (num == std::floor(num)) {
1624 vsiz = std::sprintf(vnbuf, "%lld", (long long)num);
1625 } else {
1626 vsiz = std::snprintf(vnbuf, sizeof(vnbuf), "%.6f", num);
1627 vnbuf[sizeof(vnbuf)-1] = '\0';
1628 }
1629 vbuf = vnbuf;
1630 break;
1631 }
1632 case LUA_TSTRING: {
1633 vbuf = lua_tolstring(lua, -1, &vsiz);
1634 break;
1635 }
1636 }
1637 if (kbuf && vbuf) {
1638 char nbuf[kc::NUMBUFSIZ*2];
1639 size_t nsiz = kc::writevarnum(nbuf, ksiz);
1640 nsiz += kc::writevarnum(nbuf + nsiz, vsiz);
1641 rstr.append(nbuf, nsiz);
1642 rstr.append(kbuf, ksiz);
1643 rstr.append(vbuf, vsiz);
1644 }
1645 lua_pop(lua, 1);
1646 }
1647 lua_pushlstring(lua, rstr.data(), rstr.size());
1648 return 1;
1649 }
1650
1651
1652 /**
1653 * Implementation of mapload.
1654 */
kt_mapload(lua_State * lua)1655 static int kt_mapload(lua_State *lua) {
1656 int32_t argc = lua_gettop(lua);
1657 if (argc != 1) throwinvarg(lua, __KCFUNC__);
1658 size_t size;
1659 const char* rp = lua_tolstring(lua, 1, &size);
1660 if (!rp) throwinvarg(lua, __KCFUNC__);
1661 lua_newtable(lua);
1662 while (size > 1) {
1663 uint64_t ksiz;
1664 size_t step = kc::readvarnum(rp, size, &ksiz);
1665 rp += step;
1666 size -= step;
1667 if (size < 1) break;
1668 uint64_t vsiz;
1669 step = kc::readvarnum(rp, size, &vsiz);
1670 rp += step;
1671 size -= step;
1672 size_t rsiz = ksiz + vsiz;
1673 if (rsiz > size) break;
1674 lua_pushlstring(lua, rp, ksiz);
1675 lua_pushlstring(lua, rp + ksiz, vsiz);
1676 lua_settable(lua, -3);
1677 rp += rsiz;
1678 size -= rsiz;
1679 }
1680 return 1;
1681 }
1682
1683
1684 /**
1685 * Define objects of the Error class.
1686 */
define_err(lua_State * lua)1687 static void define_err(lua_State* lua) {
1688 lua_newtable(lua);
1689 setfielduint(lua, "SUCCESS", kc::BasicDB::Error::SUCCESS);
1690 setfielduint(lua, "NOIMPL", kc::BasicDB::Error::NOIMPL);
1691 setfielduint(lua, "INVALID", kc::BasicDB::Error::INVALID);
1692 setfielduint(lua, "NOREPOS", kc::BasicDB::Error::NOREPOS);
1693 setfielduint(lua, "NOPERM", kc::BasicDB::Error::NOPERM);
1694 setfielduint(lua, "BROKEN", kc::BasicDB::Error::BROKEN);
1695 setfielduint(lua, "DUPREC", kc::BasicDB::Error::DUPREC);
1696 setfielduint(lua, "NOREC", kc::BasicDB::Error::NOREC);
1697 setfielduint(lua, "LOGIC", kc::BasicDB::Error::LOGIC);
1698 setfielduint(lua, "SYSTEM", kc::BasicDB::Error::SYSTEM);
1699 setfielduint(lua, "MISC", kc::BasicDB::Error::MISC);
1700 setfieldfunc(lua, "new", err_new);
1701 lua_newtable(lua);
1702 setfieldfunc(lua, "__tostring", err_tostring);
1703 lua_setfield(lua, -2, "meta_");
1704 lua_setfield(lua, 1, "Error");
1705 }
1706
1707
1708 /**
1709 * Implementation of new.
1710 */
err_new(lua_State * lua)1711 static int err_new(lua_State* lua) {
1712 int32_t argc = lua_gettop(lua);
1713 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1714 if (argc > 3) throwinvarg(lua, __KCFUNC__);
1715 lua_newtable(lua);
1716 if (argc > 2 && lua_isnumber(lua, 2) && lua_isstring(lua, 3)) {
1717 setfieldvalue(lua, "code_", 2);
1718 setfieldvalue(lua, "message_", 3);
1719 } else {
1720 setfielduint(lua, "code_", 0);
1721 setfieldstr(lua, "message_", "error");
1722 }
1723 setfieldfunc(lua, "set", err_set);
1724 setfieldfunc(lua, "code", err_code);
1725 setfieldfunc(lua, "name", err_name);
1726 setfieldfunc(lua, "message", err_message);
1727 lua_getfield(lua, 1, "meta_");
1728 lua_setmetatable(lua, -2);
1729 return 1;
1730 }
1731
1732
1733 /**
1734 * Implementation of __tostring.
1735 */
err_tostring(lua_State * lua)1736 static int err_tostring(lua_State* lua) {
1737 int32_t argc = lua_gettop(lua);
1738 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1739 lua_getfield(lua, 1, "code_");
1740 uint32_t code = lua_tonumber(lua, -1);
1741 lua_getfield(lua, 1, "message_");
1742 const char* message = lua_tostring(lua, -1);
1743 const char* name = kc::BasicDB::Error::codename((kc::BasicDB::Error::Code)code);
1744 lua_pushfstring(lua, "%s: %s", name, message);
1745 return 1;
1746 }
1747
1748
1749 /**
1750 * Implementation of set.
1751 */
err_set(lua_State * lua)1752 static int err_set(lua_State* lua) {
1753 int32_t argc = lua_gettop(lua);
1754 if (argc != 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1755 if (argc > 2 && lua_isnumber(lua, 2) && lua_isstring(lua, 3)) {
1756 lua_pushvalue(lua, 2);
1757 lua_setfield(lua, 1, "code_");
1758 lua_pushvalue(lua, 3);
1759 lua_setfield(lua, 1, "message_");
1760 }
1761 lua_pushnil(lua);
1762 return 1;
1763 }
1764
1765
1766 /**
1767 * Implementation of code.
1768 */
err_code(lua_State * lua)1769 static int err_code(lua_State* lua) {
1770 int32_t argc = lua_gettop(lua);
1771 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1772 lua_getfield(lua, 1, "code_");
1773 return 1;
1774 }
1775
1776
1777 /**
1778 * Implementation of name.
1779 */
err_name(lua_State * lua)1780 static int err_name(lua_State* lua) {
1781 int32_t argc = lua_gettop(lua);
1782 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1783 lua_getfield(lua, 1, "code_");
1784 uint32_t code = lua_tonumber(lua, -1);
1785 const char* name = kc::BasicDB::Error::codename((kc::BasicDB::Error::Code)code);
1786 lua_pushstring(lua, name);
1787 return 1;
1788 }
1789
1790
1791 /**
1792 * Implementation of message.
1793 */
err_message(lua_State * lua)1794 static int err_message(lua_State* lua) {
1795 int32_t argc = lua_gettop(lua);
1796 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1797 lua_getfield(lua, 1, "message_");
1798 return 1;
1799 }
1800
1801
1802 /**
1803 * Define objects of the Visitor class.
1804 */
define_vis(lua_State * lua)1805 static void define_vis(lua_State* lua) {
1806 lua_newtable(lua);
1807 lua_pushlightuserdata(lua, (void*)kt::TimedDB::Visitor::NOP);
1808 lua_setfield(lua, -2, "NOP");
1809 lua_pushlightuserdata(lua, (void*)kt::TimedDB::Visitor::REMOVE);
1810 lua_setfield(lua, -2, "REMOVE");
1811 setfieldfunc(lua, "new", vis_new);
1812 lua_newtable(lua);
1813 lua_setfield(lua, -2, "meta_");
1814 lua_setfield(lua, 1, "Visitor");
1815 }
1816
1817
1818 /**
1819 * Implementation of new.
1820 */
vis_new(lua_State * lua)1821 static int vis_new(lua_State* lua) {
1822 int32_t argc = lua_gettop(lua);
1823 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1824 lua_newtable(lua);
1825 setfieldfunc(lua, "visit_full", vis_visit_full);
1826 setfieldfunc(lua, "visit_empty", vis_visit_empty);
1827 lua_getfield(lua, 1, "meta_");
1828 lua_setmetatable(lua, -2);
1829 return 1;
1830 }
1831
1832
1833 /**
1834 * Implementation of visit_full.
1835 */
vis_visit_full(lua_State * lua)1836 static int vis_visit_full(lua_State* lua) {
1837 int32_t argc = lua_gettop(lua);
1838 if (argc != 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1839 lua_pushnil(lua);
1840 return 1;
1841 }
1842
1843
1844 /**
1845 * Implementation of visit_empty.
1846 */
vis_visit_empty(lua_State * lua)1847 static int vis_visit_empty(lua_State* lua) {
1848 int32_t argc = lua_gettop(lua);
1849 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1850 lua_pushnil(lua);
1851 return 1;
1852 }
1853
1854
1855 /**
1856 * Define objects of the FileProcessor class.
1857 */
define_fproc(lua_State * lua)1858 static void define_fproc(lua_State* lua) {
1859 lua_newtable(lua);
1860 setfieldfunc(lua, "new", fproc_new);
1861 lua_newtable(lua);
1862 lua_setfield(lua, -2, "meta_");
1863 lua_setfield(lua, 1, "FileProcessor");
1864 }
1865
1866
1867 /**
1868 * Implementation of new.
1869 */
fproc_new(lua_State * lua)1870 static int fproc_new(lua_State* lua) {
1871 int32_t argc = lua_gettop(lua);
1872 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1873 lua_newtable(lua);
1874 setfieldfunc(lua, "process", fproc_process);
1875 lua_getfield(lua, 1, "meta_");
1876 lua_setmetatable(lua, -2);
1877 return 1;
1878 }
1879
1880
1881 /**
1882 * Implementation of process.
1883 */
fproc_process(lua_State * lua)1884 static int fproc_process(lua_State* lua) {
1885 int32_t argc = lua_gettop(lua);
1886 if (argc != 4 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1887 lua_pushboolean(lua, true);
1888 return 1;
1889 }
1890
1891
1892 /**
1893 * Define objects of the Cursor class.
1894 */
define_cur(lua_State * lua)1895 static void define_cur(lua_State* lua) {
1896 lua_newtable(lua);
1897 setfieldfunc(lua, "new", cur_new);
1898 lua_newtable(lua);
1899 setfieldfunc(lua, "__tostring", cur_tostring);
1900 setfieldfunc(lua, "__call", cur_call);
1901 lua_setfield(lua, -2, "meta_");
1902 lua_setfield(lua, 1, "Cursor");
1903 }
1904
1905
1906 /**
1907 * Implementation of new.
1908 */
cur_new(lua_State * lua)1909 static int cur_new(lua_State* lua) {
1910 int32_t argc = lua_gettop(lua);
1911 if (argc != 2 || !lua_istable(lua, 1) || !lua_istable(lua, 2)) throwinvarg(lua, __KCFUNC__);
1912 lua_getfield(lua, 2, "db_ptr_");
1913 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
1914 if (!db) throwinvarg(lua, __KCFUNC__);
1915 lua_newtable(lua);
1916 g_curbur.sweap();
1917 SoftCursor* cur = (SoftCursor*)lua_newuserdata(lua, sizeof(*cur));
1918 cur->cur = db->db->cursor();
1919 lua_newtable(lua);
1920 setfieldfunc(lua, "__gc", cur_gc);
1921 lua_setmetatable(lua, -2);
1922 lua_setfield(lua, -2, "cur_ptr_");
1923 lua_pushvalue(lua, 2);
1924 lua_setfield(lua, -2, "db_");
1925 setfieldfunc(lua, "disable", cur_disable);
1926 setfieldfunc(lua, "accept", cur_accept);
1927 setfieldfunc(lua, "set_value", cur_set_value);
1928 setfieldfunc(lua, "remove", cur_remove);
1929 setfieldfunc(lua, "get_key", cur_get_key);
1930 setfieldfunc(lua, "get_value", cur_get_value);
1931 setfieldfunc(lua, "get", cur_get);
1932 setfieldfunc(lua, "seize", cur_seize);
1933 setfieldfunc(lua, "jump", cur_jump);
1934 setfieldfunc(lua, "jump_back", cur_jump_back);
1935 setfieldfunc(lua, "step", cur_step);
1936 setfieldfunc(lua, "step_back", cur_step_back);
1937 setfieldfunc(lua, "db", cur_db);
1938 setfieldfunc(lua, "error", cur_error);
1939 lua_getfield(lua, 1, "meta_");
1940 lua_setmetatable(lua, -2);
1941 return 1;
1942 }
1943
1944
1945 /**
1946 * Implementation of __gc.
1947 */
cur_gc(lua_State * lua)1948 static int cur_gc(lua_State* lua) {
1949 int32_t argc = lua_gettop(lua);
1950 if (argc < 1 || !lua_isuserdata(lua, 1)) return 0;
1951 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, 1);
1952 if (!cur) return 0;
1953 if (cur->cur) g_curbur.deposit(cur->cur);
1954 return 0;
1955 }
1956
1957
1958 /**
1959 * Implementation of __tostring.
1960 */
cur_tostring(lua_State * lua)1961 static int cur_tostring(lua_State* lua) {
1962 int32_t argc = lua_gettop(lua);
1963 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1964 lua_getfield(lua, 1, "cur_ptr_");
1965 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
1966 if (!cur) {
1967 lua_pushstring(lua, "(disabled)");
1968 return 1;
1969 }
1970 kt::TimedDB* db = cur->cur->db();
1971 std::string path = db->path();
1972 if (path.size() < 1) path = "(nil)";
1973 std::string str = kc::strprintf("%s: ", path.c_str());
1974 size_t ksiz;
1975 char* kbuf = cur->cur->get_key(&ksiz);
1976 if (kbuf) {
1977 str.append(kbuf, ksiz);
1978 delete[] kbuf;
1979 } else {
1980 str.append("(nil)");
1981 }
1982 lua_pushstring(lua, str.c_str());
1983 return 1;
1984 }
1985
1986
1987 /**
1988 * Implementation of __call.
1989 */
cur_call(lua_State * lua)1990 static int cur_call(lua_State* lua) {
1991 int32_t argc = lua_gettop(lua);
1992 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
1993 lua_getfield(lua, 1, "cur_ptr_");
1994 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
1995 if (!cur) throwinvarg(lua, __KCFUNC__);
1996 const char* vbuf;
1997 size_t ksiz, vsiz;
1998 int64_t xt;
1999 char* kbuf = cur->cur->get(&ksiz, &vbuf, &vsiz, &xt, true);
2000 if (kbuf) {
2001 lua_pushlstring(lua, kbuf, ksiz);
2002 lua_pushlstring(lua, vbuf, vsiz);
2003 delete[] kbuf;
2004 return 2;
2005 }
2006 lua_pushnil(lua);
2007 return 1;
2008 }
2009
2010
2011 /**
2012 * Implementation of disable.
2013 */
cur_disable(lua_State * lua)2014 static int cur_disable(lua_State* lua) {
2015 int32_t argc = lua_gettop(lua);
2016 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2017 lua_getfield(lua, 1, "cur_ptr_");
2018 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2019 if (!cur) throwinvarg(lua, __KCFUNC__);
2020 delete cur->cur;
2021 cur->cur = NULL;
2022 lua_pushnil(lua);
2023 lua_setfield(lua, 1, "cur_ptr_");
2024 lua_pushnil(lua);
2025 return 1;
2026 }
2027
2028
2029 /**
2030 * Implementation of accept.
2031 */
cur_accept(lua_State * lua)2032 static int cur_accept(lua_State* lua) {
2033 int32_t argc = lua_gettop(lua);
2034 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2035 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2036 lua_getfield(lua, 1, "cur_ptr_");
2037 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2038 if (!cur) throwinvarg(lua, __KCFUNC__);
2039 bool writable = argc > 2 ? lua_toboolean(lua, 3) : true;
2040 bool step = argc > 3 ? lua_toboolean(lua, 4) : false;
2041 bool rv;
2042 if (lua_istable(lua, 2) || lua_isfunction(lua, 2)) {
2043 lua_pushvalue(lua, 2);
2044 SoftVisitor visitor(lua, writable);
2045 rv = cur->cur->accept(&visitor, writable, step);
2046 } else {
2047 throwinvarg(lua, __KCFUNC__);
2048 rv = false;
2049 }
2050 lua_pushboolean(lua, rv);
2051 return 1;
2052 }
2053
2054
2055 /**
2056 * Implementation of set_value.
2057 */
cur_set_value(lua_State * lua)2058 static int cur_set_value(lua_State* lua) {
2059 int32_t argc = lua_gettop(lua);
2060 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2061 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2062 lua_getfield(lua, 1, "cur_ptr_");
2063 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2064 size_t vsiz;
2065 const char* vbuf = lua_tolstring(lua, 2, &vsiz);
2066 if (!cur || !vsiz) throwinvarg(lua, __KCFUNC__);
2067 int64_t xt = argc > 2 && !lua_isnil(lua, 3) ? lua_tonumber(lua, 3) : kc::INT64MAX;
2068 bool step = argc > 3 ? lua_toboolean(lua, 4) : false;
2069 bool rv = cur->cur->set_value(vbuf, vsiz, step, xt);
2070 lua_pushboolean(lua, rv);
2071 return 1;
2072 }
2073
2074
2075 /**
2076 * Implementation of remove.
2077 */
cur_remove(lua_State * lua)2078 static int cur_remove(lua_State* lua) {
2079 int32_t argc = lua_gettop(lua);
2080 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2081 lua_getfield(lua, 1, "cur_ptr_");
2082 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2083 if (!cur) throwinvarg(lua, __KCFUNC__);
2084 bool rv = cur->cur->remove();
2085 lua_pushboolean(lua, rv);
2086 return 1;
2087 }
2088
2089
2090 /**
2091 * Implementation of get_key.
2092 */
cur_get_key(lua_State * lua)2093 static int cur_get_key(lua_State* lua) {
2094 int32_t argc = lua_gettop(lua);
2095 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2096 if (argc > 2) throwinvarg(lua, __KCFUNC__);
2097 lua_getfield(lua, 1, "cur_ptr_");
2098 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2099 if (!cur) throwinvarg(lua, __KCFUNC__);
2100 bool step = argc > 1 ? lua_toboolean(lua, 2) : false;
2101 size_t ksiz;
2102 char* kbuf = cur->cur->get_key(&ksiz, step);
2103 if (kbuf) {
2104 lua_pushlstring(lua, kbuf, ksiz);
2105 delete[] kbuf;
2106 } else {
2107 lua_pushnil(lua);
2108 }
2109 return 1;
2110 }
2111
2112
2113 /**
2114 * Implementation of get_value.
2115 */
cur_get_value(lua_State * lua)2116 static int cur_get_value(lua_State* lua) {
2117 int32_t argc = lua_gettop(lua);
2118 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2119 if (argc > 2) throwinvarg(lua, __KCFUNC__);
2120 lua_getfield(lua, 1, "cur_ptr_");
2121 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2122 if (!cur) throwinvarg(lua, __KCFUNC__);
2123 bool step = argc > 1 ? lua_toboolean(lua, 2) : false;
2124 size_t vsiz;
2125 char* vbuf = cur->cur->get_value(&vsiz, step);
2126 if (vbuf) {
2127 lua_pushlstring(lua, vbuf, vsiz);
2128 delete[] vbuf;
2129 } else {
2130 lua_pushnil(lua);
2131 }
2132 return 1;
2133 }
2134
2135
2136 /**
2137 * Implementation of get.
2138 */
cur_get(lua_State * lua)2139 static int cur_get(lua_State* lua) {
2140 int32_t argc = lua_gettop(lua);
2141 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2142 if (argc > 2) throwinvarg(lua, __KCFUNC__);
2143 lua_getfield(lua, 1, "cur_ptr_");
2144 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2145 if (!cur) throwinvarg(lua, __KCFUNC__);
2146 bool step = argc > 1 ? lua_toboolean(lua, 2) : false;
2147 const char* vbuf;
2148 size_t ksiz, vsiz;
2149 int64_t xt;
2150 char* kbuf = cur->cur->get(&ksiz, &vbuf, &vsiz, &xt, step);
2151 if (kbuf) {
2152 lua_pushlstring(lua, kbuf, ksiz);
2153 lua_pushlstring(lua, vbuf, vsiz);
2154 lua_pushnumber(lua, xt < kt::TimedDB::XTMAX ? xt : kt::TimedDB::XTMAX);
2155 delete[] kbuf;
2156 return 3;
2157 }
2158 lua_pushnil(lua);
2159 return 1;
2160 }
2161
2162
2163 /**
2164 * Implementation of seize.
2165 */
cur_seize(lua_State * lua)2166 static int cur_seize(lua_State* lua) {
2167 int32_t argc = lua_gettop(lua);
2168 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2169 lua_getfield(lua, 1, "cur_ptr_");
2170 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2171 if (!cur) throwinvarg(lua, __KCFUNC__);
2172 const char* vbuf;
2173 size_t ksiz, vsiz;
2174 int64_t xt;
2175 char* kbuf = cur->cur->seize(&ksiz, &vbuf, &vsiz, &xt);
2176 if (kbuf) {
2177 lua_pushlstring(lua, kbuf, ksiz);
2178 lua_pushlstring(lua, vbuf, vsiz);
2179 lua_pushnumber(lua, xt < kt::TimedDB::XTMAX ? xt : kt::TimedDB::XTMAX);
2180 delete[] kbuf;
2181 return 3;
2182 }
2183 lua_pushnil(lua);
2184 return 1;
2185 }
2186
2187
2188 /**
2189 * Implementation of jump.
2190 */
cur_jump(lua_State * lua)2191 static int cur_jump(lua_State* lua) {
2192 int32_t argc = lua_gettop(lua);
2193 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2194 if (argc > 2) throwinvarg(lua, __KCFUNC__);
2195 lua_getfield(lua, 1, "cur_ptr_");
2196 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2197 if (!cur) throwinvarg(lua, __KCFUNC__);
2198 bool rv;
2199 if (argc > 1) {
2200 size_t ksiz;
2201 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2202 if (!kbuf) throwinvarg(lua, __KCFUNC__);
2203 rv = cur->cur->jump(kbuf, ksiz);
2204 } else {
2205 rv = cur->cur->jump();
2206 }
2207 lua_pushboolean(lua, rv);
2208 return 1;
2209 }
2210
2211
2212 /**
2213 * Implementation of jump_back.
2214 */
cur_jump_back(lua_State * lua)2215 static int cur_jump_back(lua_State* lua) {
2216 int32_t argc = lua_gettop(lua);
2217 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2218 if (argc > 2) throwinvarg(lua, __KCFUNC__);
2219 lua_getfield(lua, 1, "cur_ptr_");
2220 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2221 if (!cur) throwinvarg(lua, __KCFUNC__);
2222 bool rv;
2223 if (argc > 1) {
2224 size_t ksiz;
2225 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2226 if (!kbuf) throwinvarg(lua, __KCFUNC__);
2227 rv = cur->cur->jump_back(kbuf, ksiz);
2228 } else {
2229 rv = cur->cur->jump_back();
2230 }
2231 lua_pushboolean(lua, rv);
2232 return 1;
2233 }
2234
2235
2236 /**
2237 * Implementation of step.
2238 */
cur_step(lua_State * lua)2239 static int cur_step(lua_State* lua) {
2240 int32_t argc = lua_gettop(lua);
2241 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2242 lua_getfield(lua, 1, "cur_ptr_");
2243 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2244 if (!cur) throwinvarg(lua, __KCFUNC__);
2245 bool rv = cur->cur->step();
2246 lua_pushboolean(lua, rv);
2247 return 1;
2248 }
2249
2250
2251 /**
2252 * Implementation of step_back.
2253 */
cur_step_back(lua_State * lua)2254 static int cur_step_back(lua_State* lua) {
2255 int32_t argc = lua_gettop(lua);
2256 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2257 lua_getfield(lua, 1, "cur_ptr_");
2258 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2259 if (!cur) throwinvarg(lua, __KCFUNC__);
2260 bool rv = cur->cur->step_back();
2261 lua_pushboolean(lua, rv);
2262 return 1;
2263 }
2264
2265
2266 /**
2267 * Implementation of db.
2268 */
cur_db(lua_State * lua)2269 static int cur_db(lua_State* lua) {
2270 int32_t argc = lua_gettop(lua);
2271 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2272 lua_getfield(lua, 1, "cur_ptr_");
2273 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2274 if (!cur) throwinvarg(lua, __KCFUNC__);
2275 lua_getfield(lua, 1, "db_");
2276 return 1;
2277 }
2278
2279
2280 /**
2281 * Implementation of error.
2282 */
cur_error(lua_State * lua)2283 static int cur_error(lua_State* lua) {
2284 int32_t argc = lua_gettop(lua);
2285 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2286 lua_getfield(lua, 1, "cur_ptr_");
2287 SoftCursor* cur = (SoftCursor*)lua_touserdata(lua, -1);
2288 if (!cur) throwinvarg(lua, __KCFUNC__);
2289 lua_getfield(lua, 1, "db_");
2290 lua_getfield(lua, -1, "error");
2291 lua_pushvalue(lua, -2);
2292 lua_call(lua, 1, 1);
2293 return 1;
2294 }
2295
2296
2297 /**
2298 * Define objects of the DB class.
2299 */
define_db(lua_State * lua)2300 static void define_db(lua_State* lua) {
2301 lua_newtable(lua);
2302 setfielduint(lua, "OREADER", kc::BasicDB::OREADER);
2303 setfielduint(lua, "OWRITER", kc::BasicDB::OWRITER);
2304 setfielduint(lua, "OCREATE", kc::BasicDB::OCREATE);
2305 setfielduint(lua, "OTRUNCATE", kc::BasicDB::OTRUNCATE);
2306 setfielduint(lua, "OAUTOTRAN", kc::BasicDB::OAUTOTRAN);
2307 setfielduint(lua, "OAUTOSYNC", kc::BasicDB::OAUTOSYNC);
2308 setfielduint(lua, "ONOLOCK", kc::BasicDB::ONOLOCK);
2309 setfielduint(lua, "OTRYLOCK", kc::BasicDB::OTRYLOCK);
2310 setfielduint(lua, "ONOREPAIR", kc::BasicDB::ONOREPAIR);
2311 setfielduint(lua, "MSET", kc::PolyDB::MSET);
2312 setfielduint(lua, "MADD", kc::PolyDB::MADD);
2313 setfielduint(lua, "MREPLACE", kc::PolyDB::MREPLACE);
2314 setfielduint(lua, "MAPPEND", kc::PolyDB::MAPPEND);
2315 setfielduint(lua, "XNOLOCK", kc::MapReduce::XNOLOCK);
2316 setfielduint(lua, "XNOCOMP", kc::MapReduce::XNOCOMP);
2317 setfieldfunc(lua, "new", db_new);
2318 setfieldfunc(lua, "new_ptr", db_new_ptr);
2319 setfieldfunc(lua, "delete_ptr", db_delete_ptr);
2320 setfieldfunc(lua, "process", db_process);
2321 lua_newtable(lua);
2322 setfieldfunc(lua, "__tostring", db_tostring);
2323 setfieldfunc(lua, "__index", db_index);
2324 setfieldfunc(lua, "__newindex", db_newindex);
2325 lua_setfield(lua, -2, "meta_");
2326 lua_setfield(lua, 1, "DB");
2327 }
2328
2329
2330 /**
2331 * Implementation of new.
2332 */
db_new(lua_State * lua)2333 static int db_new(lua_State* lua) {
2334 int32_t argc = lua_gettop(lua);
2335 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2336 if (argc > 2) throwinvarg(lua, __KCFUNC__);
2337 lua_newtable(lua);
2338 SoftDB* db = (SoftDB*)lua_newuserdata(lua, sizeof(*db));
2339 if (argc > 1 && lua_islightuserdata(lua, 2)) {
2340 db->db = (kt::TimedDB*)lua_touserdata(lua, 2);
2341 db->light = true;
2342 } else {
2343 db->db = new kt::TimedDB;
2344 db->light = false;
2345 }
2346 lua_newtable(lua);
2347 setfieldfunc(lua, "__gc", db_gc);
2348 lua_setmetatable(lua, -2);
2349 lua_setfield(lua, -2, "db_ptr_");
2350 lua_getglobal(lua, "__kyototycoon__");
2351 lua_getfield(lua, -1, "Error");
2352 lua_setfield(lua, -3, "err_");
2353 lua_getfield(lua, -1, "Cursor");
2354 lua_setfield(lua, -3, "cur_");
2355 lua_pop(lua, 1);
2356 setfieldfunc(lua, "error", db_error);
2357 setfieldfunc(lua, "open", db_open);
2358 setfieldfunc(lua, "close", db_close);
2359 setfieldfunc(lua, "accept", db_accept);
2360 setfieldfunc(lua, "accept_bulk", db_accept_bulk);
2361 setfieldfunc(lua, "iterate", db_iterate);
2362 setfieldfunc(lua, "set", db_set);
2363 setfieldfunc(lua, "add", db_add);
2364 setfieldfunc(lua, "replace", db_replace);
2365 setfieldfunc(lua, "append", db_append);
2366 setfieldfunc(lua, "increment", db_increment);
2367 setfieldfunc(lua, "increment_double", db_increment_double);
2368 setfieldfunc(lua, "cas", db_cas);
2369 setfieldfunc(lua, "remove", db_remove);
2370 setfieldfunc(lua, "get", db_get);
2371 setfieldfunc(lua, "check", db_check);
2372 setfieldfunc(lua, "seize", db_seize);
2373 setfieldfunc(lua, "set_bulk", db_set_bulk);
2374 setfieldfunc(lua, "remove_bulk", db_remove_bulk);
2375 setfieldfunc(lua, "get_bulk", db_get_bulk);
2376 setfieldfunc(lua, "clear", db_clear);
2377 setfieldfunc(lua, "synchronize", db_synchronize);
2378 setfieldfunc(lua, "occupy", db_occupy);
2379 setfieldfunc(lua, "copy", db_copy);
2380 setfieldfunc(lua, "begin_transaction", db_begin_transaction);
2381 setfieldfunc(lua, "end_transaction", db_end_transaction);
2382 setfieldfunc(lua, "transaction", db_transaction);
2383 setfieldfunc(lua, "dump_snapshot", db_dump_snapshot);
2384 setfieldfunc(lua, "load_snapshot", db_load_snapshot);
2385 setfieldfunc(lua, "count", db_count);
2386 setfieldfunc(lua, "size", db_size);
2387 setfieldfunc(lua, "path", db_path);
2388 setfieldfunc(lua, "status", db_status);
2389 setfieldfunc(lua, "match_prefix", db_match_prefix);
2390 setfieldfunc(lua, "match_regex", db_match_regex);
2391 setfieldfunc(lua, "match_similar", db_match_similar);
2392 setfieldfunc(lua, "merge", db_merge);
2393 setfieldfunc(lua, "mapreduce", db_mapreduce);
2394 setfieldfunc(lua, "cursor", db_cursor);
2395 setfieldfunc(lua, "cursor_process", db_cursor_process);
2396 setfieldfunc(lua, "pairs", db_pairs);
2397 lua_getfield(lua, 1, "meta_");
2398 lua_setmetatable(lua, -2);
2399 return 1;
2400 }
2401
2402
2403 /**
2404 * Implementation of __gc.
2405 */
db_gc(lua_State * lua)2406 static int db_gc(lua_State* lua) {
2407 int32_t argc = lua_gettop(lua);
2408 if (argc < 1 || !lua_isuserdata(lua, 1)) return 0;
2409 SoftDB* db = (SoftDB*)lua_touserdata(lua, 1);
2410 if (!db) return 0;
2411 if (!db->light) delete db->db;
2412 return 0;
2413 }
2414
2415
2416 /**
2417 * Implementation of __tostring.
2418 */
db_tostring(lua_State * lua)2419 static int db_tostring(lua_State* lua) {
2420 int32_t argc = lua_gettop(lua);
2421 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2422 lua_getfield(lua, 1, "db_ptr_");
2423 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2424 if (!db) throwinvarg(lua, __KCFUNC__);
2425 std::string path = db->db->path();
2426 if (path.size() < 1) path = "(nil)";
2427 std::string str = kc::strprintf("%s: %lld: %lld", path.c_str(),
2428 (long long)db->db->count(), (long long)db->db->size());
2429 lua_pushstring(lua, str.c_str());
2430 return 1;
2431 }
2432
2433
2434 /**
2435 * Implementation of __index.
2436 */
db_index(lua_State * lua)2437 static int db_index(lua_State* lua) {
2438 int32_t argc = lua_gettop(lua);
2439 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2440 lua_getfield(lua, 1, "db_ptr_");
2441 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2442 size_t ksiz;
2443 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2444 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2445 size_t vsiz;
2446 char* vbuf = db->db->get(kbuf, ksiz, &vsiz);
2447 if (vbuf) {
2448 lua_pushlstring(lua, vbuf, vsiz);
2449 delete[] vbuf;
2450 } else {
2451 lua_pushnil(lua);
2452 }
2453 return 1;
2454 }
2455
2456
2457 /**
2458 * Implementation of __newindex.
2459 */
db_newindex(lua_State * lua)2460 static int db_newindex(lua_State* lua) {
2461 int32_t argc = lua_gettop(lua);
2462 if (argc != 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2463 lua_getfield(lua, 1, "db_ptr_");
2464 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2465 size_t ksiz;
2466 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2467 size_t vsiz;
2468 const char* vbuf = lua_tolstring(lua, 3, &vsiz);
2469 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2470 bool rv;
2471 if (vbuf) {
2472 rv = db->db->set(kbuf, ksiz, vbuf, vsiz);
2473 } else {
2474 rv = db->db->remove(kbuf, ksiz);
2475 }
2476 lua_pushboolean(lua, rv);
2477 return 1;
2478 }
2479
2480
2481 /**
2482 * Implementation of new_ptr.
2483 */
db_new_ptr(lua_State * lua)2484 static int db_new_ptr(lua_State* lua) {
2485 int32_t argc = lua_gettop(lua);
2486 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2487 kt::TimedDB* db = new kt::TimedDB;
2488 lua_pushlightuserdata(lua, (void*)db);
2489 return 1;
2490 }
2491
2492
2493 /**
2494 * Implementation of delete_ptr.
2495 */
db_delete_ptr(lua_State * lua)2496 static int db_delete_ptr(lua_State* lua) {
2497 int32_t argc = lua_gettop(lua);
2498 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2499 if (lua_islightuserdata(lua, 2)) {
2500 kt::TimedDB* db = (kt::TimedDB*)lua_touserdata(lua, 2);
2501 delete db;
2502 }
2503 lua_pushnil(lua);
2504 return 1;
2505 }
2506
2507
2508 /**
2509 * Implementation of process.
2510 */
db_process(lua_State * lua)2511 static int db_process(lua_State* lua) {
2512 int32_t argc = lua_gettop(lua);
2513 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2514 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2515 if (!lua_isfunction(lua, 2)) throwinvarg(lua, __KCFUNC__);
2516 lua_getfield(lua, 1, "new");
2517 lua_pushvalue(lua, 1);
2518 lua_call(lua, 1, 1);
2519 int32_t objidx = lua_gettop(lua);
2520 lua_getfield(lua, objidx, "open");
2521 lua_pushvalue(lua, objidx);
2522 if (argc > 2) lua_pushvalue(lua, 3);
2523 if (argc > 3) lua_pushvalue(lua, 4);
2524 lua_call(lua, argc - 1, 1);
2525 if (!lua_toboolean(lua, -1)) {
2526 lua_getfield(lua, objidx, "error");
2527 lua_pushvalue(lua, objidx);
2528 lua_call(lua, 1, 1);
2529 return 1;
2530 }
2531 lua_pushvalue(lua, 2);
2532 lua_pushvalue(lua, objidx);
2533 int32_t erridx = 0;
2534 if (lua_pcall(lua, 1, 0, 0) != 0) erridx = lua_gettop(lua);
2535 lua_getfield(lua, objidx, "close");
2536 lua_pushvalue(lua, objidx);
2537 lua_call(lua, 1, 1);
2538 if (erridx > 0) {
2539 lua_pushvalue(lua, erridx);
2540 lua_error(lua);
2541 }
2542 if (!lua_toboolean(lua, -1)) {
2543 lua_getfield(lua, objidx, "error");
2544 lua_pushvalue(lua, objidx);
2545 lua_call(lua, 1, 1);
2546 return 1;
2547 }
2548 lua_pushnil(lua);
2549 return 1;
2550 }
2551
2552
2553 /**
2554 * Implementation of error.
2555 */
db_error(lua_State * lua)2556 static int db_error(lua_State* lua) {
2557 int32_t argc = lua_gettop(lua);
2558 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2559 lua_getfield(lua, 1, "db_ptr_");
2560 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2561 if (!db) throwinvarg(lua, __KCFUNC__);
2562 kc::BasicDB::Error err = db->db->error();
2563 lua_getfield(lua, 1, "err_");
2564 lua_getfield(lua, -1, "new");
2565 lua_pushvalue(lua, -2);
2566 lua_pushinteger(lua, err.code());
2567 lua_pushstring(lua, err.message());
2568 lua_call(lua, 3, 1);
2569 return 1;
2570 }
2571
2572
2573 /**
2574 * Implementation of open.
2575 */
db_open(lua_State * lua)2576 static int db_open(lua_State* lua) {
2577 int32_t argc = lua_gettop(lua);
2578 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2579 if (argc > 3) throwinvarg(lua, __KCFUNC__);
2580 lua_getfield(lua, 1, "db_ptr_");
2581 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2582 if (!db) throwinvarg(lua, __KCFUNC__);
2583 const char* path = ":";
2584 if (argc > 1 && lua_isstring(lua, 2)) path = lua_tostring(lua, 2);
2585 uint32_t mode = kc::BasicDB::OWRITER | kc::BasicDB::OCREATE;
2586 if (argc > 2 && lua_isnumber(lua, 3)) mode = lua_tonumber(lua, 3);
2587 bool rv = db->db->open(path, mode);
2588 lua_pushboolean(lua, rv);
2589 return 1;
2590 }
2591
2592
2593 /**
2594 * Implementation of close.
2595 */
db_close(lua_State * lua)2596 static int db_close(lua_State* lua) {
2597 int32_t argc = lua_gettop(lua);
2598 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2599 lua_getfield(lua, 1, "db_ptr_");
2600 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2601 if (!db) throwinvarg(lua, __KCFUNC__);
2602 g_curbur.sweap();
2603 bool rv = db->db->close();
2604 lua_pushboolean(lua, rv);
2605 return 1;
2606 }
2607
2608
2609 /**
2610 * Implementation of accept.
2611 */
db_accept(lua_State * lua)2612 static int db_accept(lua_State* lua) {
2613 int32_t argc = lua_gettop(lua);
2614 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2615 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2616 lua_getfield(lua, 1, "db_ptr_");
2617 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2618 size_t ksiz;
2619 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2620 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2621 bool writable = argc > 3 ? lua_toboolean(lua, 4) : true;
2622 bool rv;
2623 if (lua_istable(lua, 3) || lua_isfunction(lua, 3)) {
2624 lua_pushvalue(lua, 3);
2625 SoftVisitor visitor(lua, writable);
2626 rv = db->db->accept(kbuf, ksiz, &visitor, writable);
2627 } else {
2628 throwinvarg(lua, __KCFUNC__);
2629 rv = false;
2630 }
2631 lua_pushboolean(lua, rv);
2632 return 1;
2633 }
2634
2635
2636 /**
2637 * Implementation of accept_bulk.
2638 */
db_accept_bulk(lua_State * lua)2639 static int db_accept_bulk(lua_State* lua) {
2640 int32_t argc = lua_gettop(lua);
2641 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2642 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2643 lua_getfield(lua, 1, "db_ptr_");
2644 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2645 if (!db || !lua_istable(lua, 2)) throwinvarg(lua, __KCFUNC__);
2646 size_t knum = lua_objlen(lua, 2);
2647 StringVector keys;
2648 keys.reserve(knum);
2649 for (size_t i = 1; i <= knum; i++) {
2650 lua_rawgeti(lua, 2, i);
2651 size_t ksiz;
2652 const char* kbuf = lua_tolstring(lua, -1, &ksiz);
2653 if (kbuf) keys.push_back(std::string(kbuf, ksiz));
2654 lua_pop(lua, 1);
2655 }
2656 bool writable = argc > 3 ? lua_toboolean(lua, 4) : true;
2657 bool rv;
2658 if (lua_istable(lua, 3) || lua_isfunction(lua, 3)) {
2659 lua_pushvalue(lua, 3);
2660 SoftVisitor visitor(lua, writable);
2661 rv = db->db->accept_bulk(keys, &visitor, writable);
2662 } else {
2663 throwinvarg(lua, __KCFUNC__);
2664 rv = false;
2665 }
2666 lua_pushboolean(lua, rv);
2667 return 1;
2668 }
2669
2670
2671 /**
2672 * Implementation of iterate.
2673 */
db_iterate(lua_State * lua)2674 static int db_iterate(lua_State* lua) {
2675 int32_t argc = lua_gettop(lua);
2676 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2677 if (argc > 3) throwinvarg(lua, __KCFUNC__);
2678 lua_getfield(lua, 1, "db_ptr_");
2679 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2680 if (!db) throwinvarg(lua, __KCFUNC__);
2681 bool writable = argc > 2 ? lua_toboolean(lua, 3) : true;
2682 bool rv;
2683 if (lua_istable(lua, 2) || lua_isfunction(lua, 2)) {
2684 lua_pushvalue(lua, 2);
2685 SoftVisitor visitor(lua, writable);
2686 rv = db->db->iterate(&visitor, writable);
2687 } else {
2688 throwinvarg(lua, __KCFUNC__);
2689 rv = false;
2690 }
2691 lua_pushboolean(lua, rv);
2692 return 1;
2693 }
2694
2695
2696 /**
2697 * Implementation of set.
2698 */
db_set(lua_State * lua)2699 static int db_set(lua_State* lua) {
2700 int32_t argc = lua_gettop(lua);
2701 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2702 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2703 lua_getfield(lua, 1, "db_ptr_");
2704 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2705 size_t ksiz;
2706 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2707 size_t vsiz;
2708 const char* vbuf = lua_tolstring(lua, 3, &vsiz);
2709 if (!db || !kbuf || !vbuf) throwinvarg(lua, __KCFUNC__);
2710 int64_t xt = argc > 3 && !lua_isnil(lua, 4) ? lua_tonumber(lua, 4) : kc::INT64MAX;
2711 bool rv = db->db->set(kbuf, ksiz, vbuf, vsiz, xt);
2712 lua_pushboolean(lua, rv);
2713 return 1;
2714 }
2715
2716
2717 /**
2718 * Implementation of add.
2719 */
db_add(lua_State * lua)2720 static int db_add(lua_State* lua) {
2721 int32_t argc = lua_gettop(lua);
2722 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2723 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2724 lua_getfield(lua, 1, "db_ptr_");
2725 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2726 size_t ksiz;
2727 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2728 size_t vsiz;
2729 const char* vbuf = lua_tolstring(lua, 3, &vsiz);
2730 if (!db || !kbuf || !vbuf) throwinvarg(lua, __KCFUNC__);
2731 int64_t xt = argc > 3 && !lua_isnil(lua, 4) ? lua_tonumber(lua, 4) : kc::INT64MAX;
2732 bool rv = db->db->add(kbuf, ksiz, vbuf, vsiz, xt);
2733 lua_pushboolean(lua, rv);
2734 return 1;
2735 }
2736
2737
2738 /**
2739 * Implementation of replace.
2740 */
db_replace(lua_State * lua)2741 static int db_replace(lua_State* lua) {
2742 int32_t argc = lua_gettop(lua);
2743 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2744 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2745 lua_getfield(lua, 1, "db_ptr_");
2746 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2747 size_t ksiz;
2748 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2749 size_t vsiz;
2750 const char* vbuf = lua_tolstring(lua, 3, &vsiz);
2751 if (!db || !kbuf || !vbuf) throwinvarg(lua, __KCFUNC__);
2752 int64_t xt = argc > 3 && !lua_isnil(lua, 4) ? lua_tonumber(lua, 4) : kc::INT64MAX;
2753 bool rv = db->db->replace(kbuf, ksiz, vbuf, vsiz, xt);
2754 lua_pushboolean(lua, rv);
2755 return 1;
2756 }
2757
2758
2759 /**
2760 * Implementation of append.
2761 */
db_append(lua_State * lua)2762 static int db_append(lua_State* lua) {
2763 int32_t argc = lua_gettop(lua);
2764 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2765 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2766 lua_getfield(lua, 1, "db_ptr_");
2767 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2768 size_t ksiz;
2769 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2770 size_t vsiz;
2771 const char* vbuf = lua_tolstring(lua, 3, &vsiz);
2772 if (!db || !kbuf || !vbuf) throwinvarg(lua, __KCFUNC__);
2773 int64_t xt = argc > 3 && !lua_isnil(lua, 4) ? lua_tonumber(lua, 4) : kc::INT64MAX;
2774 bool rv = db->db->append(kbuf, ksiz, vbuf, vsiz, xt);
2775 lua_pushboolean(lua, rv);
2776 return 1;
2777 }
2778
2779
2780 /**
2781 * Implementation of increment.
2782 */
db_increment(lua_State * lua)2783 static int db_increment(lua_State* lua) {
2784 int32_t argc = lua_gettop(lua);
2785 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2786 if (argc > 5) throwinvarg(lua, __KCFUNC__);
2787 lua_getfield(lua, 1, "db_ptr_");
2788 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2789 size_t ksiz;
2790 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2791 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2792 int64_t num = argc > 2 ? lua_tonumber(lua, 3) : 0;
2793 double orig = argc > 3 ? lua_tonumber(lua, 4) : 0;
2794 int64_t orint;
2795 if (kc::chkinf(orig)) {
2796 orint = orig >= 0 ? kc::INT64MAX : kc::INT64MIN;
2797 } else {
2798 orint = orig;
2799 }
2800 int64_t xt = argc > 4 && !lua_isnil(lua, 5) ? lua_tonumber(lua, 5) : kc::INT64MAX;
2801 num = db->db->increment(kbuf, ksiz, num, orint, xt);
2802 if (num == kc::INT64MIN) {
2803 lua_pushnil(lua);
2804 } else {
2805 lua_pushnumber(lua, num);
2806 }
2807 return 1;
2808 }
2809
2810
2811 /**
2812 * Implementation of increment_double.
2813 */
db_increment_double(lua_State * lua)2814 static int db_increment_double(lua_State* lua) {
2815 int32_t argc = lua_gettop(lua);
2816 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2817 if (argc > 5) throwinvarg(lua, __KCFUNC__);
2818 lua_getfield(lua, 1, "db_ptr_");
2819 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2820 size_t ksiz;
2821 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2822 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2823 double num = argc > 2 ? lua_tonumber(lua, 3) : 0;
2824 double orig = argc > 3 ? lua_tonumber(lua, 4) : 0;
2825 int64_t xt = argc > 4 && !lua_isnil(lua, 5) ? lua_tonumber(lua, 5) : kc::INT64MAX;
2826 num = db->db->increment_double(kbuf, ksiz, num, orig, xt);
2827 if (kc::chknan(num)) {
2828 lua_pushnil(lua);
2829 } else {
2830 lua_pushnumber(lua, num);
2831 }
2832 return 1;
2833 }
2834
2835
2836 /**
2837 * Implementation of cas.
2838 */
db_cas(lua_State * lua)2839 static int db_cas(lua_State* lua) {
2840 int32_t argc = lua_gettop(lua);
2841 if (argc < 4 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2842 if (argc > 5) throwinvarg(lua, __KCFUNC__);
2843 lua_getfield(lua, 1, "db_ptr_");
2844 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2845 size_t ksiz;
2846 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2847 size_t ovsiz;
2848 const char* ovbuf = lua_tolstring(lua, 3, &ovsiz);
2849 size_t nvsiz;
2850 const char* nvbuf = lua_tolstring(lua, 4, &nvsiz);
2851 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2852 int64_t xt = argc > 4 && !lua_isnil(lua, 5) ? lua_tonumber(lua, 5) : kc::INT64MAX;
2853 bool rv = db->db->cas(kbuf, ksiz, ovbuf, ovsiz, nvbuf, nvsiz, xt);
2854 lua_pushboolean(lua, rv);
2855 return 1;
2856 }
2857
2858
2859 /**
2860 * Implementation of remove.
2861 */
db_remove(lua_State * lua)2862 static int db_remove(lua_State* lua) {
2863 int32_t argc = lua_gettop(lua);
2864 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2865 lua_getfield(lua, 1, "db_ptr_");
2866 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2867 size_t ksiz;
2868 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2869 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2870 bool rv = db->db->remove(kbuf, ksiz);
2871 lua_pushboolean(lua, rv);
2872 return 1;
2873 }
2874
2875
2876 /**
2877 * Implementation of get.
2878 */
db_get(lua_State * lua)2879 static int db_get(lua_State* lua) {
2880 int32_t argc = lua_gettop(lua);
2881 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2882 lua_getfield(lua, 1, "db_ptr_");
2883 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2884 size_t ksiz;
2885 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2886 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2887 size_t vsiz;
2888 int64_t xt;
2889 char* vbuf = db->db->get(kbuf, ksiz, &vsiz, &xt);
2890 if (vbuf) {
2891 lua_pushlstring(lua, vbuf, vsiz);
2892 lua_pushnumber(lua, xt < kt::TimedDB::XTMAX ? xt : kt::TimedDB::XTMAX);
2893 delete[] vbuf;
2894 return 2;
2895 }
2896 lua_pushnil(lua);
2897 return 1;
2898 }
2899
2900
2901 /**
2902 * Implementation of check.
2903 */
db_check(lua_State * lua)2904 static int db_check(lua_State* lua) {
2905 int32_t argc = lua_gettop(lua);
2906 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2907 lua_getfield(lua, 1, "db_ptr_");
2908 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2909 size_t ksiz;
2910 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2911 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2912 int32_t vsiz = db->db->check(kbuf, ksiz);
2913 lua_pushnumber(lua, vsiz);
2914 return 1;
2915 }
2916
2917
2918 /**
2919 * Implementation of seize.
2920 */
db_seize(lua_State * lua)2921 static int db_seize(lua_State* lua) {
2922 int32_t argc = lua_gettop(lua);
2923 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2924 lua_getfield(lua, 1, "db_ptr_");
2925 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2926 size_t ksiz;
2927 const char* kbuf = lua_tolstring(lua, 2, &ksiz);
2928 if (!db || !kbuf) throwinvarg(lua, __KCFUNC__);
2929 size_t vsiz;
2930 int64_t xt;
2931 char* vbuf = db->db->seize(kbuf, ksiz, &vsiz, &xt);
2932 if (vbuf) {
2933 lua_pushlstring(lua, vbuf, vsiz);
2934 lua_pushnumber(lua, xt < kt::TimedDB::XTMAX ? xt : kt::TimedDB::XTMAX);
2935 delete[] vbuf;
2936 return 2;
2937 }
2938 lua_pushnil(lua);
2939 return 1;
2940 }
2941
2942
2943 /**
2944 * Implementation of set_bulk.
2945 */
db_set_bulk(lua_State * lua)2946 static int db_set_bulk(lua_State* lua) {
2947 int32_t argc = lua_gettop(lua);
2948 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
2949 if (argc > 4) throwinvarg(lua, __KCFUNC__);
2950 lua_getfield(lua, 1, "db_ptr_");
2951 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
2952 if (!db || !lua_istable(lua, 2)) throwinvarg(lua, __KCFUNC__);
2953 StringMap recs;
2954 lua_pushnil(lua);
2955 while (lua_next(lua, 2) != 0) {
2956 char knbuf[kc::NUMBUFSIZ];
2957 const char* kbuf = NULL;
2958 size_t ksiz = 0;
2959 switch (lua_type(lua, -2)) {
2960 case LUA_TNUMBER: {
2961 double num = lua_tonumber(lua, -2);
2962 if (num == std::floor(num)) {
2963 ksiz = std::sprintf(knbuf, "%lld", (long long)num);
2964 } else {
2965 ksiz = std::snprintf(knbuf, sizeof(knbuf), "%.6f", num);
2966 knbuf[sizeof(knbuf)-1] = '\0';
2967 }
2968 kbuf = knbuf;
2969 break;
2970 }
2971 case LUA_TSTRING: {
2972 kbuf = lua_tolstring(lua, -2, &ksiz);
2973 break;
2974 }
2975 }
2976 char vnbuf[kc::NUMBUFSIZ];
2977 const char* vbuf = NULL;
2978 size_t vsiz = 0;
2979 switch (lua_type(lua, -1)) {
2980 case LUA_TNUMBER: {
2981 double num = lua_tonumber(lua, -1);
2982 if (num == std::floor(num)) {
2983 vsiz = std::sprintf(vnbuf, "%lld", (long long)num);
2984 } else {
2985 vsiz = std::snprintf(vnbuf, sizeof(vnbuf), "%.6f", num);
2986 vnbuf[sizeof(vnbuf)-1] = '\0';
2987 }
2988 vbuf = vnbuf;
2989 break;
2990 }
2991 case LUA_TSTRING: {
2992 vbuf = lua_tolstring(lua, -1, &vsiz);
2993 break;
2994 }
2995 }
2996 if (kbuf && vbuf) recs[std::string(kbuf, ksiz)] = std::string(vbuf, vsiz);
2997 lua_pop(lua, 1);
2998 }
2999 int64_t xt = argc > 2 && !lua_isnil(lua, 3) ? lua_tonumber(lua, 3) : kc::INT64MAX;
3000 bool atomic = argc > 3 ? lua_toboolean(lua, 4) : true;
3001 int64_t rv = db->db->set_bulk(recs, xt, atomic);
3002 lua_pushnumber(lua, rv);
3003 return 1;
3004 }
3005
3006
3007 /**
3008 * Implementation of remove_bulk.
3009 */
db_remove_bulk(lua_State * lua)3010 static int db_remove_bulk(lua_State* lua) {
3011 int32_t argc = lua_gettop(lua);
3012 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3013 if (argc > 3) throwinvarg(lua, __KCFUNC__);
3014 lua_getfield(lua, 1, "db_ptr_");
3015 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3016 if (!db || !lua_istable(lua, 2)) throwinvarg(lua, __KCFUNC__);
3017 size_t knum = lua_objlen(lua, 2);
3018 StringVector keys;
3019 keys.reserve(knum);
3020 for (size_t i = 1; i <= knum; i++) {
3021 lua_rawgeti(lua, 2, i);
3022 size_t ksiz;
3023 const char* kbuf = lua_tolstring(lua, -1, &ksiz);
3024 if (kbuf) keys.push_back(std::string(kbuf, ksiz));
3025 lua_pop(lua, 1);
3026 }
3027 bool atomic = argc > 2 ? lua_toboolean(lua, 3) : true;
3028 int64_t rv = db->db->remove_bulk(keys, atomic);
3029 lua_pushnumber(lua, rv);
3030 return 1;
3031 }
3032
3033
3034 /**
3035 * Implementation of get_bulk.
3036 */
db_get_bulk(lua_State * lua)3037 static int db_get_bulk(lua_State* lua) {
3038 int32_t argc = lua_gettop(lua);
3039 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3040 if (argc > 3) throwinvarg(lua, __KCFUNC__);
3041 lua_getfield(lua, 1, "db_ptr_");
3042 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3043 if (!db || !lua_istable(lua, 2)) throwinvarg(lua, __KCFUNC__);
3044 size_t knum = lua_objlen(lua, 2);
3045 StringVector keys;
3046 keys.reserve(knum);
3047 for (size_t i = 1; i <= knum; i++) {
3048 lua_rawgeti(lua, 2, i);
3049 size_t ksiz;
3050 const char* kbuf = lua_tolstring(lua, -1, &ksiz);
3051 if (kbuf) keys.push_back(std::string(kbuf, ksiz));
3052 lua_pop(lua, 1);
3053 }
3054 bool atomic = argc > 2 ? lua_toboolean(lua, 3) : true;
3055 StringMap recs;
3056 int64_t rv = db->db->get_bulk(keys, &recs, atomic);
3057 if (rv < 0) {
3058 lua_pushnil(lua);
3059 } else {
3060 lua_newtable(lua);
3061 StringMap::const_iterator it = recs.begin();
3062 StringMap::const_iterator itend = recs.end();
3063 while (it != itend) {
3064 lua_pushlstring(lua, it->first.data(), it->first.size());
3065 lua_pushlstring(lua, it->second.data(), it->second.size());
3066 lua_settable(lua, -3);
3067 ++it;
3068 }
3069 }
3070 return 1;
3071 }
3072
3073
3074 /**
3075 * Implementation of clear.
3076 */
db_clear(lua_State * lua)3077 static int db_clear(lua_State* lua) {
3078 int32_t argc = lua_gettop(lua);
3079 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3080 lua_getfield(lua, 1, "db_ptr_");
3081 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3082 if (!db) throwinvarg(lua, __KCFUNC__);
3083 bool rv = db->db->clear();
3084 lua_pushboolean(lua, rv);
3085 return 1;
3086 }
3087
3088
3089 /**
3090 * Implementation of synchronize.
3091 */
db_synchronize(lua_State * lua)3092 static int db_synchronize(lua_State* lua) {
3093 int32_t argc = lua_gettop(lua);
3094 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3095 if (argc > 3) throwinvarg(lua, __KCFUNC__);
3096 lua_getfield(lua, 1, "db_ptr_");
3097 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3098 if (!db) throwinvarg(lua, __KCFUNC__);
3099 bool hard = argc > 1 ? lua_toboolean(lua, 2) : false;
3100 bool rv;
3101 if (argc > 2 && (lua_istable(lua, 3) || lua_isfunction(lua, 3))) {
3102 lua_pushvalue(lua, 3);
3103 SoftFileProcessor proc(lua);
3104 rv = db->db->synchronize(hard, &proc);
3105 } else {
3106 rv = db->db->synchronize(hard, NULL);
3107 }
3108 lua_pushboolean(lua, rv);
3109 return 1;
3110 }
3111
3112
3113 /**
3114 * Implementation of occupy.
3115 */
db_occupy(lua_State * lua)3116 static int db_occupy(lua_State* lua) {
3117 int32_t argc = lua_gettop(lua);
3118 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3119 if (argc > 3) throwinvarg(lua, __KCFUNC__);
3120 lua_getfield(lua, 1, "db_ptr_");
3121 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3122 if (!db) throwinvarg(lua, __KCFUNC__);
3123 bool writable = argc > 1 ? lua_toboolean(lua, 2) : false;
3124 bool rv;
3125 if (argc > 2 && (lua_istable(lua, 3) || lua_isfunction(lua, 3))) {
3126 lua_pushvalue(lua, 3);
3127 SoftFileProcessor proc(lua);
3128 rv = db->db->occupy(writable, &proc);
3129 } else {
3130 rv = db->db->occupy(writable, NULL);
3131 }
3132 lua_pushboolean(lua, rv);
3133 return 1;
3134 }
3135
3136
3137 /**
3138 * Implementation of copy.
3139 */
db_copy(lua_State * lua)3140 static int db_copy(lua_State* lua) {
3141 int32_t argc = lua_gettop(lua);
3142 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3143 lua_getfield(lua, 1, "db_ptr_");
3144 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3145 const char* dest = lua_tostring(lua, 2);
3146 if (!db || !dest) throwinvarg(lua, __KCFUNC__);
3147 bool rv = db->db->copy(dest);
3148 lua_pushboolean(lua, rv);
3149 return 1;
3150 }
3151
3152
3153 /**
3154 * Implementation of begin_transaction.
3155 */
db_begin_transaction(lua_State * lua)3156 static int db_begin_transaction(lua_State* lua) {
3157 int32_t argc = lua_gettop(lua);
3158 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3159 if (argc > 2) throwinvarg(lua, __KCFUNC__);
3160 lua_getfield(lua, 1, "db_ptr_");
3161 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3162 if (!db) throwinvarg(lua, __KCFUNC__);
3163 bool hard = argc > 1 ? lua_toboolean(lua, 2) : false;
3164 bool rv = db->db->begin_transaction(hard);
3165 lua_pushboolean(lua, rv);
3166 return 1;
3167 }
3168
3169
3170 /**
3171 * Implementation of end_transaction.
3172 */
db_end_transaction(lua_State * lua)3173 static int db_end_transaction(lua_State* lua) {
3174 int32_t argc = lua_gettop(lua);
3175 if (argc < 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3176 if (argc > 2) throwinvarg(lua, __KCFUNC__);
3177 lua_getfield(lua, 1, "db_ptr_");
3178 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3179 if (!db) throwinvarg(lua, __KCFUNC__);
3180 bool commit = argc > 1 ? lua_toboolean(lua, 2) : true;
3181 bool rv = db->db->end_transaction(commit);
3182 lua_pushboolean(lua, rv);
3183 return 1;
3184 }
3185
3186
3187 /**
3188 * Implementation of transaction.
3189 */
db_transaction(lua_State * lua)3190 static int db_transaction(lua_State* lua) {
3191 int32_t argc = lua_gettop(lua);
3192 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3193 if (argc > 3) throwinvarg(lua, __KCFUNC__);
3194 lua_getfield(lua, 1, "db_ptr_");
3195 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3196 if (!db) throwinvarg(lua, __KCFUNC__);
3197 bool hard = argc > 2 ? lua_toboolean(lua, 3) : false;
3198 lua_getfield(lua, 1, "begin_transaction");
3199 lua_pushvalue(lua, 1);
3200 lua_pushboolean(lua, hard);
3201 lua_call(lua, 2, 1);
3202 if (!lua_toboolean(lua, -1)) return 1;
3203 lua_pushvalue(lua, 2);
3204 int32_t erridx = 0;
3205 if (lua_pcall(lua, 0, 1, 0) != 0) erridx = lua_gettop(lua);
3206 bool commit = erridx == 0 && lua_toboolean(lua, -1);
3207 lua_getfield(lua, 1, "end_transaction");
3208 lua_pushvalue(lua, 1);
3209 lua_pushboolean(lua, commit);
3210 lua_call(lua, 2, 1);
3211 if (erridx > 0) {
3212 lua_pushvalue(lua, erridx);
3213 lua_error(lua);
3214 }
3215 return 1;
3216 }
3217
3218
3219 /**
3220 * Implementation of dump_snapshot.
3221 */
db_dump_snapshot(lua_State * lua)3222 static int db_dump_snapshot(lua_State* lua) {
3223 int32_t argc = lua_gettop(lua);
3224 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3225 lua_getfield(lua, 1, "db_ptr_");
3226 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3227 const char* dest = lua_tostring(lua, 2);
3228 if (!db || !dest) throwinvarg(lua, __KCFUNC__);
3229 bool rv = db->db->dump_snapshot(dest);
3230 lua_pushboolean(lua, rv);
3231 return 1;
3232 }
3233
3234
3235 /**
3236 * Implementation of load_snapshot.
3237 */
db_load_snapshot(lua_State * lua)3238 static int db_load_snapshot(lua_State* lua) {
3239 int32_t argc = lua_gettop(lua);
3240 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3241 lua_getfield(lua, 1, "db_ptr_");
3242 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3243 const char* src = lua_tostring(lua, 2);
3244 if (!db || !src) throwinvarg(lua, __KCFUNC__);
3245 bool rv = db->db->load_snapshot(src);
3246 lua_pushboolean(lua, rv);
3247 return 1;
3248 }
3249
3250
3251 /**
3252 * Implementation of count.
3253 */
db_count(lua_State * lua)3254 static int db_count(lua_State* lua) {
3255 int32_t argc = lua_gettop(lua);
3256 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3257 lua_getfield(lua, 1, "db_ptr_");
3258 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3259 if (!db) throwinvarg(lua, __KCFUNC__);
3260 int64_t count = db->db->count();
3261 lua_pushnumber(lua, count);
3262 return 1;
3263 }
3264
3265
3266 /**
3267 * Implementation of size.
3268 */
db_size(lua_State * lua)3269 static int db_size(lua_State* lua) {
3270 int32_t argc = lua_gettop(lua);
3271 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3272 lua_getfield(lua, 1, "db_ptr_");
3273 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3274 if (!db) throwinvarg(lua, __KCFUNC__);
3275 int64_t size = db->db->size();
3276 lua_pushnumber(lua, size);
3277 return 1;
3278 }
3279
3280
3281 /**
3282 * Implementation of path.
3283 */
db_path(lua_State * lua)3284 static int db_path(lua_State* lua) {
3285 int32_t argc = lua_gettop(lua);
3286 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3287 lua_getfield(lua, 1, "db_ptr_");
3288 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3289 if (!db) throwinvarg(lua, __KCFUNC__);
3290 const std::string& path = db->db->path();
3291 if (path.size() > 0) {
3292 lua_pushstring(lua, path.c_str());
3293 } else {
3294 lua_pushnil(lua);
3295 }
3296 return 1;
3297 }
3298
3299
3300 /**
3301 * Implementation of status.
3302 */
db_status(lua_State * lua)3303 static int db_status(lua_State* lua) {
3304 int32_t argc = lua_gettop(lua);
3305 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3306 lua_getfield(lua, 1, "db_ptr_");
3307 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3308 if (!db) throwinvarg(lua, __KCFUNC__);
3309 StringMap status;
3310 bool rv = db->db->status(&status);
3311 if (rv) {
3312 lua_newtable(lua);
3313 StringMap::const_iterator it = status.begin();
3314 StringMap::const_iterator itend = status.end();
3315 while (it != itend) {
3316 lua_pushlstring(lua, it->first.data(), it->first.size());
3317 lua_pushlstring(lua, it->second.data(), it->second.size());
3318 lua_settable(lua, -3);
3319 ++it;
3320 }
3321 } else {
3322 lua_pushnil(lua);
3323 }
3324 return 1;
3325 }
3326
3327
3328 /**
3329 * Implementation of match_prefix.
3330 */
db_match_prefix(lua_State * lua)3331 static int db_match_prefix(lua_State* lua) {
3332 int32_t argc = lua_gettop(lua);
3333 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3334 lua_getfield(lua, 1, "db_ptr_");
3335 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3336 size_t psiz;
3337 const char* pbuf = lua_tolstring(lua, 2, &psiz);
3338 if (!db || !pbuf) throwinvarg(lua, __KCFUNC__);
3339 int64_t max = argc > 2 ? lua_tonumber(lua, 3) : -1;
3340 StringVector keys;
3341 int64_t num = db->db->match_prefix(std::string(pbuf, psiz), &keys, max);
3342 if (num >= 0) {
3343 lua_newtable(lua);
3344 StringVector::const_iterator it = keys.begin();
3345 StringVector::const_iterator itend = keys.end();
3346 int32_t idx = 1;
3347 while (it != itend) {
3348 lua_pushlstring(lua, it->data(), it->size());
3349 lua_rawseti(lua, -2, idx++);
3350 ++it;
3351 }
3352 } else {
3353 lua_pushnil(lua);
3354 }
3355 return 1;
3356 }
3357
3358
3359 /**
3360 * Implementation of match_regex.
3361 */
db_match_regex(lua_State * lua)3362 static int db_match_regex(lua_State* lua) {
3363 int32_t argc = lua_gettop(lua);
3364 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3365 lua_getfield(lua, 1, "db_ptr_");
3366 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3367 size_t rsiz;
3368 const char* rbuf = lua_tolstring(lua, 2, &rsiz);
3369 if (!db || !rbuf) throwinvarg(lua, __KCFUNC__);
3370 int64_t max = argc > 2 ? lua_tonumber(lua, 3) : -1;
3371 StringVector keys;
3372 int64_t num = db->db->match_regex(std::string(rbuf, rsiz), &keys, max);
3373 if (num >= 0) {
3374 lua_newtable(lua);
3375 StringVector::const_iterator it = keys.begin();
3376 StringVector::const_iterator itend = keys.end();
3377 int32_t idx = 1;
3378 while (it != itend) {
3379 lua_pushlstring(lua, it->data(), it->size());
3380 lua_rawseti(lua, -2, idx++);
3381 ++it;
3382 }
3383 } else {
3384 lua_pushnil(lua);
3385 }
3386 return 1;
3387 }
3388
3389
3390 /**
3391 * Implementation of match_similar.
3392 */
db_match_similar(lua_State * lua)3393 static int db_match_similar(lua_State* lua) {
3394 int32_t argc = lua_gettop(lua);
3395 if (argc < 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3396 lua_getfield(lua, 1, "db_ptr_");
3397 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3398 size_t osiz;
3399 const char* obuf = lua_tolstring(lua, 2, &osiz);
3400 if (!db || !obuf) throwinvarg(lua, __KCFUNC__);
3401 int64_t range = argc > 2 ? lua_tonumber(lua, 3) : -1;
3402 bool utf = argc > 3 ? lua_toboolean(lua, 4) : false;
3403 int64_t max = argc > 4 ? lua_tonumber(lua, 5) : -1;
3404 StringVector keys;
3405 int64_t num = db->db->match_similar(std::string(obuf, osiz), range, utf, &keys, max);
3406 if (num >= 0) {
3407 lua_newtable(lua);
3408 StringVector::const_iterator it = keys.begin();
3409 StringVector::const_iterator itend = keys.end();
3410 int32_t idx = 1;
3411 while (it != itend) {
3412 lua_pushlstring(lua, it->data(), it->size());
3413 lua_rawseti(lua, -2, idx++);
3414 ++it;
3415 }
3416 } else {
3417 lua_pushnil(lua);
3418 }
3419 return 1;
3420 }
3421
3422
3423 /**
3424 * Implementation of merge.
3425 */
db_merge(lua_State * lua)3426 static int db_merge(lua_State* lua) {
3427 int32_t argc = lua_gettop(lua);
3428 if (argc < 2 || !lua_istable(lua, 1) || !lua_istable(lua, 2)) throwinvarg(lua, __KCFUNC__);
3429 if (argc > 3) throwinvarg(lua, __KCFUNC__);
3430 lua_getfield(lua, 1, "db_ptr_");
3431 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3432 if (!db) throwinvarg(lua, __KCFUNC__);
3433 uint32_t mode = kt::TimedDB::MSET;
3434 if (argc > 2 && lua_isnumber(lua, 3)) mode = lua_tonumber(lua, 3);
3435 size_t num = lua_objlen(lua, 2);
3436 if (num < 1) {
3437 lua_pushboolean(lua, true);
3438 return 1;
3439 }
3440 kt::TimedDB** srcary = new kt::TimedDB*[num];
3441 size_t srcnum = 0;
3442 for (size_t i = 1; i <= num; i++) {
3443 lua_rawgeti(lua, 2, i);
3444 if (lua_istable(lua, -1)) {
3445 lua_getfield(lua, -1, "db_ptr_");
3446 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3447 srcary[srcnum++] = db->db;
3448 lua_pop(lua, 1);
3449 }
3450 lua_pop(lua, 1);
3451 }
3452 bool rv = db->db->merge(srcary, srcnum, (kt::TimedDB::MergeMode)mode);
3453 delete[] srcary;
3454 lua_pushboolean(lua, rv);
3455 return 1;
3456 }
3457
3458
3459 /**
3460 * Implementation of mapreduce.
3461 */
db_mapreduce(lua_State * lua)3462 static int db_mapreduce(lua_State* lua) {
3463 int32_t argc = lua_gettop(lua);
3464 if (argc < 3 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3465 if (argc > 10) throwinvarg(lua, __KCFUNC__);
3466 lua_getfield(lua, 1, "db_ptr_");
3467 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3468 if (!db) throwinvarg(lua, __KCFUNC__);
3469 if (!db || !lua_isfunction(lua, 2) || !lua_isfunction(lua, 3)) throwinvarg(lua, __KCFUNC__);
3470 const char* tmppath = argc > 3 ? lua_tostring(lua, 4) : NULL;
3471 if (!tmppath) tmppath = "";
3472 uint32_t opts = argc > 4 ? lua_tonumber(lua, 5) : 0;
3473 int32_t dbnum = argc > 5 ? lua_tonumber(lua, 6) : -1;
3474 int64_t clim = argc > 6 ? lua_tonumber(lua, 7) : -1;
3475 int64_t cbnum = argc > 7 ? lua_tonumber(lua, 8) : -1;
3476 int32_t logidx = -1;
3477 if (argc > 8 && lua_isfunction(lua, 9)) logidx = 9;
3478 int32_t procidx = -1;
3479 if (argc > 9 && lua_isfunction(lua, 10)) procidx = 10;
3480 SoftMapReduce mr(lua, logidx, procidx);
3481 mr.tune_storage(dbnum, clim, cbnum);
3482 bool rv = mr.execute(db->db, tmppath, opts);
3483 lua_pushnil(lua);
3484 lua_setglobal(lua, "__mr_iter");
3485 lua_pushnil(lua);
3486 lua_setglobal(lua, "__mr_self");
3487 lua_pushboolean(lua, rv);
3488 return 1;
3489 }
3490
3491
3492 /**
3493 * Implementation of mapreduce_emit.
3494 */
db_mapreduce_emit(lua_State * lua)3495 static int db_mapreduce_emit(lua_State* lua) {
3496 int32_t argc = lua_gettop(lua);
3497 if (argc != 2) throwinvarg(lua, __KCFUNC__);
3498 size_t ksiz;
3499 const char* kbuf = lua_tolstring(lua, 1, &ksiz);
3500 size_t vsiz;
3501 const char* vbuf = lua_tolstring(lua, 2, &vsiz);
3502 if (!kbuf || !vbuf) throwinvarg(lua, __KCFUNC__);
3503 lua_getglobal(lua, "__mr_self");
3504 SoftMapReduce* mr = (SoftMapReduce*)lua_touserdata(lua, -1);
3505 bool rv;
3506 if (mr) {
3507 rv = mr->emit_public(kbuf, ksiz, vbuf, vsiz);
3508 } else {
3509 rv = false;
3510 }
3511 lua_pushboolean(lua, rv);
3512 return 1;
3513 }
3514
3515
3516 /**
3517 * Implementation of mapreduce_iter.
3518 */
db_mapreduce_iter(lua_State * lua)3519 static int db_mapreduce_iter(lua_State* lua) {
3520 int32_t argc = lua_gettop(lua);
3521 if (argc != 0) throwinvarg(lua, __KCFUNC__);
3522 lua_getglobal(lua, "__mr_iter");
3523 kc::MapReduce::ValueIterator* iter = (kc::MapReduce::ValueIterator*)lua_touserdata(lua, -1);
3524 if (iter) {
3525 size_t vsiz;
3526 const char* vbuf = iter->next(&vsiz);
3527 if (vbuf) {
3528 lua_pushlstring(lua, vbuf, vsiz);
3529 } else {
3530 lua_pushnil(lua);
3531 }
3532 } else {
3533 lua_pushnil(lua);
3534 }
3535 return 1;
3536 }
3537
3538
3539 /**
3540 * Implementation of cursor.
3541 */
db_cursor(lua_State * lua)3542 static int db_cursor(lua_State* lua) {
3543 int32_t argc = lua_gettop(lua);
3544 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3545 lua_getfield(lua, 1, "db_ptr_");
3546 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3547 if (!db) throwinvarg(lua, __KCFUNC__);
3548 lua_getfield(lua, 1, "cur_");
3549 lua_getfield(lua, -1, "new");
3550 lua_getfield(lua, 1, "cur_");
3551 lua_pushvalue(lua, 1);
3552 lua_call(lua, 2, 1);
3553 return 1;
3554 }
3555
3556
3557 /**
3558 * Implementation of cursor_process.
3559 */
db_cursor_process(lua_State * lua)3560 static int db_cursor_process(lua_State* lua) {
3561 int32_t argc = lua_gettop(lua);
3562 if (argc != 2 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3563 if (!lua_isfunction(lua, 2)) throwinvarg(lua, __KCFUNC__);
3564 lua_getfield(lua, 1, "db_ptr_");
3565 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3566 if (!db) throwinvarg(lua, __KCFUNC__);
3567 lua_getfield(lua, 1, "cur_");
3568 lua_getfield(lua, -1, "new");
3569 lua_getfield(lua, 1, "cur_");
3570 lua_pushvalue(lua, 1);
3571 lua_call(lua, 2, 1);
3572 int32_t objidx = lua_gettop(lua);
3573 lua_pushvalue(lua, 2);
3574 lua_pushvalue(lua, objidx);
3575 int32_t erridx = 0;
3576 if (lua_pcall(lua, 1, 0, 0) != 0) erridx = lua_gettop(lua);
3577 lua_getfield(lua, objidx, "disable");
3578 lua_pushvalue(lua, objidx);
3579 lua_call(lua, 1, 0);
3580 if (erridx > 0) {
3581 lua_pushvalue(lua, erridx);
3582 lua_error(lua);
3583 }
3584 return 0;
3585 }
3586
3587
3588 /**
3589 * Implementation of pairs.
3590 */
db_pairs(lua_State * lua)3591 static int db_pairs(lua_State* lua) {
3592 int32_t argc = lua_gettop(lua);
3593 if (argc != 1 || !lua_istable(lua, 1)) throwinvarg(lua, __KCFUNC__);
3594 lua_getfield(lua, 1, "db_ptr_");
3595 SoftDB* db = (SoftDB*)lua_touserdata(lua, -1);
3596 if (!db) throwinvarg(lua, __KCFUNC__);
3597 lua_getfield(lua, 1, "cur_");
3598 lua_getfield(lua, -1, "new");
3599 lua_getfield(lua, 1, "cur_");
3600 lua_pushvalue(lua, 1);
3601 lua_call(lua, 2, 1);
3602 lua_getfield(lua, -1, "jump");
3603 lua_pushvalue(lua, -2);
3604 lua_call(lua, 1, 0);
3605 lua_pushvalue(lua, 1);
3606 lua_pushnil(lua);
3607 return 3;
3608 }
3609
3610
3611 /**
3612 * Implementation of log.
3613 */
serv_log(lua_State * lua)3614 static int serv_log(lua_State* lua) {
3615 int32_t argc = lua_gettop(lua);
3616 if (argc != 2 || !lua_isstring(lua, 1)) throwinvarg(lua, __KCFUNC__);
3617 lua_getglobal(lua, "__kyototycoon__");
3618 lua_getfield(lua, -1, "__serv__");
3619 kt::RPCServer* serv = (kt::RPCServer*)lua_touserdata(lua, -1);
3620 const char* kstr = lua_tostring(lua, 1);
3621 const char* message = lua_tostring(lua, 2);
3622 if (kstr && message) {
3623 kt::RPCServer::Logger::Kind kind = kt::RPCServer::Logger::DEBUG;
3624 if (!kc::stricmp(kstr, "info")) {
3625 kind = kt::RPCServer::Logger::INFO;
3626 } else if (!kc::stricmp(kstr, "system")) {
3627 kind = kt::RPCServer::Logger::SYSTEM;
3628 } else if (!kc::stricmp(kstr, "error")) {
3629 kind = kt::RPCServer::Logger::ERROR;
3630 }
3631 serv->log(kind, "[SCRIPT]: %s", message);
3632 }
3633 return 0;
3634 }
3635
3636
3637 #else
3638
3639
3640 /**
3641 * ScriptProcessor internal.
3642 */
3643 struct ScriptProcessorCore {
3644 std::string path;
3645 int32_t thid;
3646 kt::RPCServer* serv;
3647 kt::TimedDB* dbs;
3648 int32_t dbnum;
3649 const std::map<std::string, int32_t>* dbmap;
3650 };
3651
3652
3653 /**
3654 * Default constructor.
3655 */
ScriptProcessor()3656 ScriptProcessor::ScriptProcessor() {
3657 _assert_(true);
3658 ScriptProcessorCore* core = new ScriptProcessorCore;
3659 core->thid = 0;
3660 core->serv = NULL;
3661 core->dbs = NULL;
3662 core->dbnum = 0;
3663 core->dbmap = NULL;
3664 opq_ = core;
3665 }
3666
3667
3668 /**
3669 * Destructor.
3670 */
~ScriptProcessor()3671 ScriptProcessor::~ScriptProcessor() {
3672 _assert_(true);
3673 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
3674 delete core;
3675 }
3676
3677
3678 /**
3679 * Set domain-specific resources.
3680 */
set_resources(int32_t thid,kt::RPCServer * serv,kt::TimedDB * dbs,int32_t dbnum,const std::map<std::string,int32_t> * dbmap)3681 bool ScriptProcessor::set_resources(int32_t thid, kt::RPCServer* serv,
3682 kt::TimedDB* dbs, int32_t dbnum,
3683 const std::map<std::string, int32_t>* dbmap) {
3684 _assert_(serv && dbs && dbnum >= 0 && dbmap);
3685 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
3686 core->thid = thid;
3687 core->serv = serv;
3688 core->dbs = dbs;
3689 core->dbnum = dbnum;
3690 core->dbmap = dbmap;
3691 return true;
3692 }
3693
3694
3695 /**
3696 * Load a script file.
3697 */
load(const std::string & path)3698 bool ScriptProcessor::load(const std::string& path) {
3699 _assert_(true);
3700 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
3701 core->path = path;
3702 return true;
3703 }
3704
3705
3706 /**
3707 * Clear the internal state.
3708 */
clear()3709 void ScriptProcessor::clear() {
3710 _assert_(true);
3711 ScriptProcessorCore* core = new ScriptProcessorCore;
3712 core->thid = 0;
3713 core->serv = NULL;
3714 core->dbs = NULL;
3715 core->dbnum = 0;
3716 core->dbmap = NULL;
3717 }
3718
3719
3720 /**
3721 * Call a procedure.
3722 */
call(const std::string & name,const std::map<std::string,std::string> & inmap,std::map<std::string,std::string> & outmap)3723 kt::RPCClient::ReturnValue ScriptProcessor::call(const std::string& name,
3724 const std::map<std::string, std::string>& inmap,
3725 std::map<std::string, std::string>& outmap) {
3726 _assert_(true);
3727 ScriptProcessorCore* core = (ScriptProcessorCore*)opq_;
3728 kt::RPCClient::ReturnValue rv;
3729 if (name == "echo") {
3730 std::string keys;
3731 std::map<std::string, std::string>::const_iterator it = inmap.begin();
3732 std::map<std::string, std::string>::const_iterator itend = inmap.end();
3733 while (it != itend) {
3734 if (!keys.empty()) keys.append(",");
3735 keys.append(it->first);
3736 ++it;
3737 }
3738 core->serv->log(kt::RPCServer::Logger::DEBUG, "[SCRIPT]: %s: thid=%d inmap=%s",
3739 name.c_str(), core->thid, keys.c_str());
3740 outmap.insert(inmap.begin(), inmap.end());
3741 rv = kt::RPCClient::RVSUCCESS;
3742 } else {
3743 rv = kt::RPCClient::RVENOIMPL;
3744 }
3745 return rv;
3746 }
3747
3748
3749 #endif
3750
3751
3752 // END OF FILE
3753