Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

sync with tokyotyrant-1.1.20.tar.gz

  • Loading branch information...
commit c4fbf3d90a0601e19dfd70cedb6e21e2264bac16 1 parent 5398c35
@etrepum etrepum authored
View
12 ChangeLog
@@ -1,3 +1,15 @@
+2009-04-01 Mikio Hirabayashi <mikio@users.sourceforge.net>
+
+ * configure.in: a bug related to support for traditional shells was fixed.
+
+ * scrext.c (serv_stashputkeep, serv_stashputcat): new functions.
+
+ * scrext.c (serv_mapreduce, serv_mapreducemapemit): new functions.
+
+ * ttserver.c (do_put, do_out, do_get): parameter validation was enhanced.
+
+ - Release: 1.1.20
+
2009-03-14 Mikio Hirabayashi <mikio@users.sourceforge.net>
* tcrdb.c (tcrdbqrysearchget): the option for no update log was added.
View
41 configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for tokyotyrant 1.1.19.
+# Generated by GNU Autoconf 2.61 for tokyotyrant 1.1.20.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -572,8 +572,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='tokyotyrant'
PACKAGE_TARNAME='tokyotyrant'
-PACKAGE_VERSION='1.1.19'
-PACKAGE_STRING='tokyotyrant 1.1.19'
+PACKAGE_VERSION='1.1.20'
+PACKAGE_STRING='tokyotyrant 1.1.20'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -1194,7 +1194,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures tokyotyrant 1.1.19 to adapt to many kinds of systems.
+\`configure' configures tokyotyrant 1.1.20 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1255,7 +1255,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of tokyotyrant 1.1.19:";;
+ short | recursive ) echo "Configuration of tokyotyrant 1.1.20:";;
esac
cat <<\_ACEOF
@@ -1275,6 +1275,7 @@ Optional Packages:
--with-tc=DIR search DIR/include and DIR/lib for Tokyo Cabinet
--with-zlib=DIR search DIR/include and DIR/lib for ZLIB
--with-bzip=DIR search DIR/include and DIR/lib for BZIP2
+ --with-lua=DIR search DIR/include and DIR/lib for Lua
Some influential environment variables:
CC C compiler command
@@ -1349,7 +1350,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-tokyotyrant configure 1.1.19
+tokyotyrant configure 1.1.20
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1363,7 +1364,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by tokyotyrant $as_me 1.1.19, which was
+It was created by tokyotyrant $as_me 1.1.20, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -1719,7 +1720,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Package information
MYLIBVER=3
-MYLIBREV=3
+MYLIBREV=4
MYPROTVER="0.9"
# Targets
@@ -1903,6 +1904,22 @@ then
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$with_bzip/lib"
fi
+# Specify the installation path of Lua
+
+# Check whether --with-lua was given.
+if test "${with_lua+set}" = set; then
+ withval=$with_lua;
+fi
+
+if test -n "$with_lua"
+then
+ MYCPPFLAGS="$MYCPPFLAGS -I$with_lua/include"
+ MYLDFLAGS="$MYLDFLAGS -L$with_lua/lib"
+ CPATH="$CPATH:$with_lua/include"
+ LIBRARY_PATH="$LIBRARY_PATH:$with_lua/lib"
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$with_lua/lib"
+fi
+
# Messages
printf '#================================================================\n'
printf '# Configuring Tokyo Tyrant version %s%s.\n' "$PACKAGE_VERSION" "$enables"
@@ -4433,7 +4450,7 @@ _ACEOF
fi
-if test "$enable_lua" == "yes"
+if test "$enable_lua" = "yes"
then
{ echo "$as_me:$LINENO: checking for main in -llua" >&5
@@ -5300,7 +5317,7 @@ echo "$as_me: error: tcutil.h is required" >&2;}
fi
-if test "$enable_lua" == "yes"
+if test "$enable_lua" = "yes"
then
if test "${ac_cv_header_lua_h+set}" = set; then
{ echo "$as_me:$LINENO: checking for lua.h" >&5
@@ -5912,7 +5929,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by tokyotyrant $as_me 1.1.19, which was
+This file was extended by tokyotyrant $as_me 1.1.20, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -5955,7 +5972,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-tokyotyrant config.status 1.1.19
+tokyotyrant config.status 1.1.20
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
View
20 configure.in
@@ -7,11 +7,11 @@
#================================================================
# Package name
-AC_INIT(tokyotyrant, 1.1.19)
+AC_INIT(tokyotyrant, 1.1.20)
# Package information
MYLIBVER=3
-MYLIBREV=3
+MYLIBREV=4
MYPROTVER="0.9"
# Targets
@@ -165,6 +165,18 @@ then
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$with_bzip/lib"
fi
+# Specify the installation path of Lua
+AC_ARG_WITH(lua,
+ AC_HELP_STRING([--with-lua=DIR], [search DIR/include and DIR/lib for Lua]))
+if test -n "$with_lua"
+then
+ MYCPPFLAGS="$MYCPPFLAGS -I$with_lua/include"
+ MYLDFLAGS="$MYLDFLAGS -L$with_lua/lib"
+ CPATH="$CPATH:$with_lua/include"
+ LIBRARY_PATH="$LIBRARY_PATH:$with_lua/lib"
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$with_lua/lib"
+fi
+
# Messages
printf '#================================================================\n'
printf '# Configuring Tokyo Tyrant version %s%s.\n' "$PACKAGE_VERSION" "$enables"
@@ -204,7 +216,7 @@ AC_CHECK_LIB(resolv, main)
AC_CHECK_LIB(z, main)
AC_CHECK_LIB(bz2, main)
AC_CHECK_LIB(tokyocabinet, main)
-if test "$enable_lua" == "yes"
+if test "$enable_lua" = "yes"
then
AC_CHECK_LIB(lua, main)
AC_CHECK_LIB(lua$luaver, main)
@@ -217,7 +229,7 @@ AC_CHECK_HEADER(stdint.h, true, AC_MSG_ERROR([stdint.h is required]))
AC_CHECK_HEADER(unistd.h, true, AC_MSG_ERROR([unistd.h is required]))
AC_CHECK_HEADER(pthread.h, true, AC_MSG_ERROR([pthread.h is required]))
AC_CHECK_HEADER(tcutil.h, true, AC_MSG_ERROR([tcutil.h is required]))
-if test "$enable_lua" == "yes"
+if test "$enable_lua" = "yes"
then
AC_CHECK_HEADER(lua.h, true, AC_MSG_ERROR([lua.h is required]))
fi
View
7 doc/index.html
@@ -1321,6 +1321,13 @@ <h3 id="luaext_builtinfunc">Built-in Functions</h3>
<dd>Process each record atomically.</dd>
<dd>`<var>func</var>' the iterator function called for each record. It receives two parameters of the key and the value, and returns true to continue iteration or false to stop iteration.</dd>
<dd>If successful, the return value is true, else, it is false.</dd>
+<dt><code>_mapreduce(<var>sid</var>, <var>keys</var>, <var>mapper</var>, <var>reducer</var>)</code></dt>
+<dd>Perform operations based on MapReduce.</dd>
+<dd>`<var>sid</var>' specifies the session ID number, which should be positive.</dd>
+<dd>`<var>keys</var>' specifies the keys of target records. If it is not defined, every record in the database is processed.</dd>
+<dd>`<var>mapper</var>' specifies the mapper function. It is called for each target record and receives the key, the value, and the function to emit the mapped records. The emitter function receives a key and a value. The mapper function should return true normally or false on failure.</dd>
+<dd>`<var>reducer</var>' specifies the reducer function. It is called for each record generated by sorting emitted records by keys, and receives the key and an array of values. The reducer function should return true normally or false on failure.</dd>
+<dd>If successful, the return value is true, else, it is false.</dd>
<dt><code>_stashput(<var>key</var>, <var>value</var>)</code></dt>
<dd>Store a record into the stash.</dd>
<dd>`<var>key</var>' specifies the key.</dd>
View
61 ext/mapreduce.lua
@@ -0,0 +1,61 @@
+--
+-- MapReduce implementation by the Lua extension of Tokyo Tyrant
+--
+
+
+
+----------------------------------------------------------------
+-- public functions
+----------------------------------------------------------------
+
+
+-- count words of all records
+function wordcount(sid, texpr)
+ sid = tonumber(sid)
+ if not sid then
+ sid = math.floor(_time()) % 65535 + 1
+ end
+ local targets = nil
+ if texpr and #texpr > 0 then
+ targets = {}
+ table.insert(targets, texpr)
+ end
+ function mapper(key, value, mapemit)
+ for word in string.gmatch(string.lower(value), "%w+") do
+ mapemit(word, 1)
+ end
+ return true
+ end
+ local res = ""
+ function reducer(key, values)
+ res = res .. key .. "\t" .. #values .. "\n"
+ return true
+ end
+ if not _mapreduce(sid, targets, mapper, reducer) then
+ res = nil
+ end
+ return res
+end
+
+
+
+----------------------------------------------------------------
+-- private functions
+----------------------------------------------------------------
+
+
+-- call back function when starting
+function _begin()
+ _log("Lua processor started")
+ _tmpdir_ = "/tmp"
+end
+
+
+-- call back function when ending
+function _end()
+ _log("Lua processor finished")
+end
+
+
+
+-- END OF FILE
View
29 ext/senatus.lua
@@ -3,17 +3,6 @@
--
--- call back function when starting
-function _begin()
- _log("Lua processor started")
-end
-
-
--- call back function when ending
-function _end()
- _log("Lua processor finished")
-end
-
-- echo back the key and the value
function echo(key, value)
@@ -434,4 +423,22 @@ end
+----------------------------------------------------------------
+-- private functions
+----------------------------------------------------------------
+
+
+-- call back function when starting
+function _begin()
+ _log("Lua processor started")
+end
+
+
+-- call back function when ending
+function _end()
+ _log("Lua processor finished")
+end
+
+
+
-- END OF FILE
View
4 ext/usherette.lua
@@ -231,13 +231,13 @@ end
-- call back function when starting
function _begin()
- _log("Inverted index started")
+ _log("Lua processor started")
end
-- call back function when ending
function _end()
- _log("Inverted index finished")
+ _log("Lua processor finished")
end
View
321 scrext.c
@@ -145,6 +145,9 @@ char *scrextcallmethod(void *scr, const char *name,
#define SERVVAR "_serv_" // global variable name for server resources
#define ITERVAR "_iter_" // global variable name for iterator
+#define MRMAPVAR "_mrmap_" // global variable name for mapreduce mapper
+#define MRREDVAR "_mrred_" // global variable name for mapreduce reducer
+#define MRPOOLVAR "_mrpool_" // global variable name for mapreduce pool
typedef struct { // type of structure of the script extension
int thnum; // number of native threads
@@ -168,6 +171,7 @@ typedef struct { // type of structure of the server data
static void reporterror(lua_State *lua);
static int lockmtxidx(const char *kbuf, int ksiz, int lcknum);
static bool iterrec(const void *kbuf, int ksiz, const void *vbuf, int vsiz, lua_State *lua);
+static int serv_putfunc(lua_State *lua);
static int serv_log(lua_State *lua);
static int serv_put(lua_State *lua);
static int serv_putkeep(lua_State *lua);
@@ -184,7 +188,11 @@ static int serv_rnum(lua_State *lua);
static int serv_size(lua_State *lua);
static int serv_misc(lua_State *lua);
static int serv_foreach(lua_State *lua);
+static int serv_mapreduce(lua_State *lua);
+static int serv_mapreducemapemit(lua_State *lua);
static int serv_stashput(lua_State *lua);
+static int serv_stashputkeep(lua_State *lua);
+static int serv_stashputcat(lua_State *lua);
static int serv_stashout(lua_State *lua);
static int serv_stashget(lua_State *lua);
static int serv_stashvanish(lua_State *lua);
@@ -211,8 +219,17 @@ static int serv_mkdir(lua_State *lua);
void *scrextnew(int thnum, int thid, const char *path, TCADB *adb, TCULOG *ulog,
uint32_t sid, TCMDB *stash, pthread_mutex_t *lcks, int lcknum,
void (*logger)(int, const char *, void *), void *logopq){
+ char *ibuf;
int isiz;
- char *ibuf = tcreadfile(path, 0, &isiz);
+ if(*path == '@'){
+ ibuf = tcstrdup(path + 1);
+ isiz = strlen(ibuf);
+ } else if(*path != '\0'){
+ ibuf = tcreadfile(path, 0, &isiz);
+ } else {
+ ibuf = tcmemdup("", 0);
+ isiz = 0;
+ }
if(!ibuf) return NULL;
lua_State *lua = luaL_newstate();
if(!lua){
@@ -231,6 +248,7 @@ void *scrextnew(int thnum, int thid, const char *path, TCADB *adb, TCULOG *ulog,
serv->logger = logger;
serv->logopq = logopq;
lua_setglobal(lua, SERVVAR);
+ lua_register(lua, "putfunc", serv_putfunc);
lua_register(lua, "_log", serv_log);
lua_register(lua, "_put", serv_put);
lua_register(lua, "_putkeep", serv_putkeep);
@@ -247,7 +265,10 @@ void *scrextnew(int thnum, int thid, const char *path, TCADB *adb, TCULOG *ulog,
lua_register(lua, "_size", serv_size);
lua_register(lua, "_misc", serv_misc);
lua_register(lua, "_foreach", serv_foreach);
+ lua_register(lua, "_mapreduce", serv_mapreduce);
lua_register(lua, "_stashput", serv_stashput);
+ lua_register(lua, "_stashputkeep", serv_stashputkeep);
+ lua_register(lua, "_stashputcat", serv_stashputcat);
lua_register(lua, "_stashout", serv_stashout);
lua_register(lua, "_stashget", serv_stashget);
lua_register(lua, "_stashvanish", serv_stashvanish);
@@ -327,8 +348,38 @@ char *scrextcallmethod(void *scr, const char *name,
return NULL;
}
if(lua_gettop(lua) < 1) return NULL;
+ const char *rbuf = NULL;
size_t rsiz;
- const char *rbuf = lua_tolstring(lua, 1, &rsiz);
+ switch(lua_type(lua, 1)){
+ case LUA_TNUMBER:
+ case LUA_TSTRING:
+ rbuf = lua_tolstring(lua, 1, &rsiz);
+ break;
+ case LUA_TBOOLEAN:
+ if(lua_toboolean(lua, 1)){
+ rbuf = "true";
+ rsiz = strlen(rbuf);
+ }
+ break;
+ case LUA_TTABLE:
+ if(lua_objlen(lua, 1) > 0){
+ lua_rawgeti(lua, 1, 1);
+ switch(lua_type(lua, -1)){
+ case LUA_TNUMBER:
+ case LUA_TSTRING:
+ rbuf = lua_tolstring(lua, -1, &rsiz);
+ break;
+ case LUA_TBOOLEAN:
+ if(lua_toboolean(lua, -1)){
+ rbuf = "true";
+ rsiz = strlen(rbuf);
+ }
+ break;
+ }
+ lua_pop(lua, 1);
+ }
+ break;
+ }
if(!rbuf){
lua_settop(lua, 0);
return NULL;
@@ -367,9 +418,68 @@ static bool iterrec(const void *kbuf, int ksiz, const void *vbuf, int vsiz, lua_
lua_getglobal(lua, ITERVAR);
lua_pushlstring(lua, kbuf, ksiz);
lua_pushlstring(lua, vbuf, vsiz);
- bool rv = lua_pcall(lua, 2, 1, 0) == 0 ? lua_toboolean(lua, -1) : false;
+ bool err = false;
+ if(lua_pcall(lua, 2, 1, 0) == 0){
+ if(lua_gettop(lua) < 1 && !lua_toboolean(lua, 1)) err = true;
+ } else {
+ reporterror(lua);
+ err = true;
+ }
lua_settop(lua, top);
- return rv;
+ return !err;
+}
+
+
+/* call function to map records for mapreduce */
+static bool maprec(void *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz,
+ lua_State *lua){
+ lua_pushlightuserdata(lua, map);
+ lua_setglobal(lua, MRPOOLVAR);
+ int top = lua_gettop(lua);
+ lua_getglobal(lua, MRMAPVAR);
+ lua_pushlstring(lua, kbuf, ksiz);
+ lua_pushlstring(lua, vbuf, vsiz);
+ lua_pushcfunction(lua, serv_mapreducemapemit);
+ bool err = false;
+ if(lua_pcall(lua, 3, 1, 0) == 0){
+ if(lua_gettop(lua) < 1 && !lua_toboolean(lua, 1)) err = true;
+ } else {
+ reporterror(lua);
+ err = true;
+ }
+ lua_settop(lua, top);
+ return !err;
+}
+
+
+/* for putfunc function */
+static int serv_putfunc(lua_State *lua){
+ int argc = lua_gettop(lua);
+ if(argc != 2){
+ lua_pushstring(lua, "putfunc: invalid arguments");
+ lua_error(lua);
+ }
+ const char *name = lua_tostring(lua, 1);
+ const char *expr = lua_tostring(lua, 2);
+ if(!name || !expr){
+ lua_pushstring(lua, "putfunc: invalid arguments");
+ lua_error(lua);
+ }
+ lua_getglobal(lua, SERVVAR);
+ SERV *serv = lua_touserdata(lua, -1);
+ bool err = false;
+
+ printf("%s:%s\n", name, expr);
+
+
+
+ lua_settop(lua, 0);
+ if(err){
+ lua_pushnil(lua);
+ } else {
+ lua_pushstring(lua, "ok");
+ }
+ return 1;
}
@@ -390,6 +500,7 @@ static int serv_log(lua_State *lua){
lua_getglobal(lua, SERVVAR);
SERV *serv = lua_touserdata(lua, -1);
serv->logger(level, msg, serv->logopq);
+ lua_settop(lua, 0);
return 0;
}
@@ -760,13 +871,161 @@ static int serv_foreach(lua_State *lua){
SERV *serv = lua_touserdata(lua, -1);
lua_pushvalue(lua, 1);
lua_setglobal(lua, ITERVAR);
- if(tcadbforeach(serv->adb, (TCITER)iterrec, lua)){
- lua_pushboolean(lua, true);
+ bool err = false;
+ if(!tcadbforeach(serv->adb, (TCITER)iterrec, lua)) err = true;
+ lua_pushnil(lua);
+ lua_setglobal(lua, ITERVAR);
+ lua_settop(lua, 0);
+ lua_pushboolean(lua, !err);
+ return 1;
+}
+
+
+/* for _mapreduce function */
+static int serv_mapreduce(lua_State *lua){
+ int argc = lua_gettop(lua);
+ if(argc < 1){
+ lua_pushstring(lua, "_mapreduce: invalid arguments");
+ lua_error(lua);
+ }
+ int id = lua_tonumber(lua, 1);
+ if(id < 1){
+ lua_pushstring(lua, "_mapreduce: invalid arguments");
+ lua_error(lua);
+ }
+ lua_getglobal(lua, SERVVAR);
+ SERV *serv = lua_touserdata(lua, -1);
+ TCLIST *keys = NULL;
+ if(argc > 1){
+ const char *kbuf;
+ size_t ksiz;
+ int len;
+ switch(lua_type(lua, 2)){
+ case LUA_TNUMBER:
+ case LUA_TSTRING:
+ keys = tclistnew2(1);
+ kbuf = lua_tolstring(lua, 2, &ksiz);
+ tclistpush(keys, kbuf, ksiz);
+ break;
+ case LUA_TTABLE:
+ len = lua_objlen(lua, 2);
+ keys = tclistnew2(len);
+ for(int i = 1; i <= len; i++){
+ lua_rawgeti(lua, 2, i);
+ switch(lua_type(lua, -1)){
+ case LUA_TNUMBER:
+ case LUA_TSTRING:
+ kbuf = lua_tolstring(lua, -1, &ksiz);
+ tclistpush(keys, kbuf, ksiz);
+ break;
+ }
+ lua_pop(lua, 1);
+ }
+ break;
+ }
+ }
+ if(argc > 2 && lua_isfunction(lua, 3)){
+ lua_pushvalue(lua, 3);
+ } else {
+ lua_pushnil(lua);
+ }
+ lua_setglobal(lua, MRMAPVAR);
+ if(argc > 3 && lua_isfunction(lua, 4)){
+ lua_pushvalue(lua, 4);
} else {
- lua_pushboolean(lua, false);
+ lua_pushnil(lua);
+ }
+ lua_setglobal(lua, MRREDVAR);
+ bool err = false;
+ TCBDB *bdb = tcbdbnew();
+ lua_getglobal(lua, "_tmpdir_");
+ const char *tmpdir = lua_tostring(lua, -1);
+ if(!tmpdir) tmpdir = "/tmp";
+ char *path = tcsprintf("%s%c%s-%d-%d", tmpdir, MYPATHCHR, "mapbdb", getpid(), id);
+ unlink(path);
+ if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)) err = true;
+ unlink(path);
+ tcfree(path);
+ if(!tcadbmapbdb(serv->adb, keys, bdb, (ADBMAPPROC)maprec, lua, -1)) err = true;
+ if(!err){
+ BDBCUR *cur = tcbdbcurnew(bdb);
+ tcbdbcurfirst(cur);
+ const char *lbuf = NULL;
+ int lsiz = 0;
+ int lnum = 0;
+ const char *kbuf;
+ int ksiz;
+ while(!err && (kbuf = tcbdbcurkey3(cur, &ksiz)) != NULL){
+ int vsiz;
+ const char *vbuf = tcbdbcurval3(cur, &vsiz);
+ if(lbuf && lsiz == ksiz && !memcmp(lbuf, kbuf, lsiz)){
+ lua_pushlstring(lua, vbuf, vsiz);
+ lua_rawseti(lua, -2, ++lnum);
+ } else {
+ if(lbuf){
+ if(lua_pcall(lua, 2, 1, 0) != 0){
+ reporterror(lua);
+ err = true;
+ } else if(lua_gettop(lua) < 1 || !lua_toboolean(lua, 1)){
+ err = true;
+ }
+ lua_settop(lua, 0);
+ }
+ lua_getglobal(lua, MRREDVAR);
+ lua_pushlstring(lua, kbuf, ksiz);
+ lua_newtable(lua);
+ lnum = 1;
+ lua_pushlstring(lua, vbuf, vsiz);
+ lua_rawseti(lua, -2, lnum);
+ }
+ lbuf = kbuf;
+ lsiz = ksiz;
+ tcbdbcurnext(cur);
+ }
+ if(lbuf){
+ if(lua_pcall(lua, 2, 1, 0) != 0){
+ reporterror(lua);
+ err = true;
+ } else if(lua_gettop(lua) < 1 || !lua_toboolean(lua, 1)){
+ err = true;
+ }
+ lua_settop(lua, 0);
+ }
+ tcbdbcurdel(cur);
}
+ if(!tcbdbclose(bdb)) err = true;
+ tcbdbdel(bdb);
+ if(keys) tclistdel(keys);
lua_pushnil(lua);
- lua_setglobal(lua, ITERVAR);
+ lua_setglobal(lua, MRREDVAR);
+ lua_pushnil(lua);
+ lua_setglobal(lua, MRMAPVAR);
+ lua_settop(lua, 0);
+ lua_pushboolean(lua, !err);
+ return 1;
+}
+
+
+/* for _mapreduce function */
+static int serv_mapreducemapemit(lua_State *lua){
+ int argc = lua_gettop(lua);
+ if(argc != 2){
+ lua_pushstring(lua, "_mapreducemapemit: invalid arguments");
+ lua_error(lua);
+ }
+ size_t ksiz;
+ const char *kbuf = lua_tolstring(lua, 1, &ksiz);
+ size_t vsiz;
+ const char *vbuf = lua_tolstring(lua, 2, &vsiz);
+ if(!kbuf || !vbuf){
+ lua_pushstring(lua, "_mapreducemapemit: invalid arguments");
+ lua_error(lua);
+ }
+ lua_getglobal(lua, MRPOOLVAR);
+ void *map = lua_touserdata(lua, -1);
+ bool rv = tcadbmapbdbemit(map, kbuf, ksiz, vbuf, vsiz);
+ lua_settop(lua, 0);
+ lua_pushboolean(lua, rv);
return 1;
}
@@ -794,6 +1053,52 @@ static int serv_stashput(lua_State *lua){
}
+/* for _stashputkeep function */
+static int serv_stashputkeep(lua_State *lua){
+ int argc = lua_gettop(lua);
+ if(argc != 2){
+ lua_pushstring(lua, "_stashputkeep: invalid arguments");
+ lua_error(lua);
+ }
+ size_t ksiz;
+ const char *kbuf = lua_tolstring(lua, 1, &ksiz);
+ size_t vsiz;
+ const char *vbuf = lua_tolstring(lua, 2, &vsiz);
+ if(!kbuf || !vbuf){
+ lua_pushstring(lua, "_stashputkeep: invalid arguments");
+ lua_error(lua);
+ }
+ lua_getglobal(lua, SERVVAR);
+ SERV *serv = lua_touserdata(lua, -1);
+ tcmdbputkeep(serv->stash, kbuf, ksiz, vbuf, vsiz);
+ lua_pushboolean(lua, true);
+ return 1;
+}
+
+
+/* for _stashputcat function */
+static int serv_stashputcat(lua_State *lua){
+ int argc = lua_gettop(lua);
+ if(argc != 2){
+ lua_pushstring(lua, "_stashputcat: invalid arguments");
+ lua_error(lua);
+ }
+ size_t ksiz;
+ const char *kbuf = lua_tolstring(lua, 1, &ksiz);
+ size_t vsiz;
+ const char *vbuf = lua_tolstring(lua, 2, &vsiz);
+ if(!kbuf || !vbuf){
+ lua_pushstring(lua, "_stashputcat: invalid arguments");
+ lua_error(lua);
+ }
+ lua_getglobal(lua, SERVVAR);
+ SERV *serv = lua_touserdata(lua, -1);
+ tcmdbputcat(serv->stash, kbuf, ksiz, vbuf, vsiz);
+ lua_pushboolean(lua, true);
+ return 1;
+}
+
+
/* for _stashout function */
static int serv_stashout(lua_State *lua){
int argc = lua_gettop(lua);
View
43 ttserver.c
@@ -24,6 +24,8 @@
#define DEFTHNUM 8 // default thread number
#define DEFPIDPATH "ttserver.pid" // default name of the PID file
#define DEFRTSPATH "ttserver.rts" // default name of the RTS file
+#define MAXARGSIZ (32*1024*1024) // maximum size of each argument
+#define MAXARGNUM (1*1024*1024) // maximum number of arguments
#define NUMBUFSIZ 32 // size of a numeric buffer
#define LINEBUFSIZ 8192 // size of a line buffer
#define TOKENUNIT 256 // unit number of tokens
@@ -947,7 +949,7 @@ static void do_put(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
int vsiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0 || vsiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ || vsiz < 0 || vsiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_put: invalid parameters");
return;
}
@@ -985,7 +987,7 @@ static void do_putkeep(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
int vsiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0 || vsiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ || vsiz < 0 || vsiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_putkeep: invalid parameters");
return;
}
@@ -1022,7 +1024,7 @@ static void do_putcat(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
int vsiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0 || vsiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ || vsiz < 0 || vsiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_putcat: invalid parameters");
return;
}
@@ -1062,7 +1064,8 @@ static void do_putshl(TTSOCK *sock, TASKARG *arg, TTREQ *req){
int ksiz = ttsockgetint32(sock);
int vsiz = ttsockgetint32(sock);
int width = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0 || vsiz < 0 || width < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ || vsiz < 0 || vsiz > MAXARGSIZ ||
+ width < 0){
ttservlog(g_serv, TTLOGINFO, "do_putshl: invalid parameters");
return;
}
@@ -1129,7 +1132,7 @@ static void do_putnr(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
int vsiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0 || vsiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ || vsiz < 0 || vsiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_putnr: invalid parameters");
return;
}
@@ -1162,7 +1165,7 @@ static void do_out(TTSOCK *sock, TASKARG *arg, TTREQ *req){
TCULOG *ulog = arg->ulog;
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_out: invalid parameters");
return;
}
@@ -1195,7 +1198,7 @@ static void do_get(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint64_t mask = arg->mask;
TCADB *adb = arg->adb;
int ksiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_get: invalid parameters");
return;
}
@@ -1249,7 +1252,7 @@ static void do_mget(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint64_t mask = arg->mask;
TCADB *adb = arg->adb;
int rnum = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || rnum < 0){
+ if(ttsockcheckend(sock) || rnum < 0 || rnum > MAXARGNUM){
ttservlog(g_serv, TTLOGINFO, "do_mget: invalid parameters");
return;
}
@@ -1258,7 +1261,7 @@ static void do_mget(TTSOCK *sock, TASKARG *arg, TTREQ *req){
char stack[TTIOBUFSIZ];
for(int i = 0; i < rnum; i++){
int ksiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0) break;
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ) break;
char *buf = (ksiz < TTIOBUFSIZ) ? stack : tcmalloc(ksiz + 1);
pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
if(ttsockrecv(sock, buf, ksiz)) tclistpush(keys, buf, ksiz);
@@ -1313,7 +1316,7 @@ static void do_vsiz(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint64_t mask = arg->mask;
TCADB *adb = arg->adb;
int ksiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_vsiz: invalid parameters");
return;
}
@@ -1423,7 +1426,7 @@ static void do_fwmkeys(TTSOCK *sock, TASKARG *arg, TTREQ *req){
TCADB *adb = arg->adb;
int psiz = ttsockgetint32(sock);
int max = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || psiz < 0){
+ if(ttsockcheckend(sock) || psiz < 0 || psiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_fwmkeys: invalid parameters");
return;
}
@@ -1477,7 +1480,7 @@ static void do_addint(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
int anum = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || ksiz < 0){
+ if(ttsockcheckend(sock) || ksiz < 0 || ksiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_addint: invalid parameters");
return;
}
@@ -1526,7 +1529,8 @@ static void do_adddouble(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint32_t sid = arg->sid;
int ksiz = ttsockgetint32(sock);
char abuf[sizeof(uint64_t)*2];
- if(!ttsockrecv(sock, abuf, sizeof(abuf)) || ttsockcheckend(sock) || ksiz < 0){
+ if(!ttsockrecv(sock, abuf, sizeof(abuf)) || ttsockcheckend(sock) ||
+ ksiz < 0 || ksiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_adddouble: invalid parameters");
return;
}
@@ -1576,7 +1580,8 @@ static void do_ext(TTSOCK *sock, TASKARG *arg, TTREQ *req){
int opts = ttsockgetint32(sock);
int ksiz = ttsockgetint32(sock);
int vsiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || nsiz < 0 || nsiz >= TTADDRBUFSIZ || ksiz < 0 || vsiz < 0){
+ if(ttsockcheckend(sock) || nsiz < 0 || nsiz >= TTADDRBUFSIZ ||
+ ksiz < 0 || ksiz > MAXARGSIZ || vsiz < 0 || vsiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_ext: invalid parameters");
return;
}
@@ -1708,7 +1713,7 @@ static void do_copy(TTSOCK *sock, TASKARG *arg, TTREQ *req){
uint64_t mask = arg->mask;
TCADB *adb = arg->adb;
int psiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || psiz < 0){
+ if(ttsockcheckend(sock) || psiz < 0 || psiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_copy: invalid parameters");
return;
}
@@ -1745,7 +1750,7 @@ static void do_restore(TTSOCK *sock, TASKARG *arg, TTREQ *req){
TCULOG *ulog = arg->ulog;
int psiz = ttsockgetint32(sock);
uint64_t ts = ttsockgetint64(sock);
- if(ttsockcheckend(sock) || psiz < 0){
+ if(ttsockcheckend(sock) || psiz < 0 || psiz > MAXARGSIZ){
ttservlog(g_serv, TTLOGINFO, "do_restore: invalid parameters");
return;
}
@@ -1786,7 +1791,7 @@ static void do_setmst(TTSOCK *sock, TASKARG *arg, TTREQ *req){
REPLARG *sarg = arg->sarg;
int hsiz = ttsockgetint32(sock);
int port = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || hsiz < 0 || port < 0){
+ if(ttsockcheckend(sock) || hsiz < 0 || hsiz > MAXARGSIZ || port < 0){
ttservlog(g_serv, TTLOGINFO, "do_setmst: invalid parameters");
return;
}
@@ -1933,7 +1938,7 @@ static void do_misc(TTSOCK *sock, TASKARG *arg, TTREQ *req){
int nsiz = ttsockgetint32(sock);
int opts = ttsockgetint32(sock);
int rnum = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || nsiz < 0 || nsiz >= TTADDRBUFSIZ || rnum < 0){
+ if(ttsockcheckend(sock) || nsiz < 0 || nsiz >= TTADDRBUFSIZ || rnum < 0 || rnum > MAXARGNUM){
ttservlog(g_serv, TTLOGINFO, "do_misc: invalid parameters");
return;
}
@@ -1948,7 +1953,7 @@ static void do_misc(TTSOCK *sock, TASKARG *arg, TTREQ *req){
char stack[TTIOBUFSIZ];
for(int i = 0; i < rnum; i++){
int rsiz = ttsockgetint32(sock);
- if(ttsockcheckend(sock) || rsiz < 0) break;
+ if(ttsockcheckend(sock) || rsiz < 0 || rsiz > MAXARGSIZ) break;
char *buf = (rsiz < TTIOBUFSIZ) ? stack : tcmalloc(rsiz + 1);
pthread_cleanup_push(free, (buf == stack) ? NULL : buf);
if(ttsockrecv(sock, buf, rsiz)) tclistpush(args, buf, rsiz);
View
4 ttutil.h
@@ -419,8 +419,8 @@ bool ttserviskilled(TTSERV *serv);
*************************************************************************************************/
-#define _TT_VERSION "1.1.19"
-#define _TT_LIBVER 303
+#define _TT_VERSION "1.1.20"
+#define _TT_LIBVER 304
#define _TT_PROTVER "0.9"
Please sign in to comment.
Something went wrong with that request. Please try again.