diff options
author | Christian Pointner <equinox@spreadspace.org> | 2010-11-18 21:51:44 +0000 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2010-11-18 21:51:44 +0000 |
commit | 5d6eb48f9560d352962b56d8f629157d6cacdea3 (patch) | |
tree | c141584458bb8a143685979fd583c5c57f01cd30 | |
parent | rawio: fixed return value at read (diff) |
added util module with own select
core doesn't depend on lua sockets anymore
cleaned up at rawio
git-svn-id: https://svn.spreadspace.org/gcsd/trunk@39 ac14a137-c7f1-4531-abe0-07747231d213
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/gcsd.c | 2 | ||||
-rw-r--r-- | src/l_rawio.c | 10 | ||||
-rw-r--r-- | src/l_util.c | 164 | ||||
-rw-r--r-- | src/l_util.h | 41 | ||||
-rw-r--r-- | src/main_loop.lua | 13 | ||||
-rw-r--r-- | src/module_list.lua | 2 |
7 files changed, 223 insertions, 10 deletions
diff --git a/src/Makefile b/src/Makefile index 0bb1ff4..603b3d2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -45,6 +45,7 @@ C_OBJS := log.o \ sig_handler.o \ l_sig_handler.o \ l_rawio.o \ + l_util.o \ gcsd.o C_SRCS := $(C_OBJS:%.o=%.c) @@ -43,6 +43,7 @@ #include "string_list.h" #include "log.h" #include "l_rawio.h" +#include "l_util.h" #include "l_log.h" #include "l_sig_handler.h" @@ -62,6 +63,7 @@ static const luaL_Reg gcsd_lualibs[] = { {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_RAWIOLIBNAME, luaopen_rawio}, + {LUA_UTILLIBNAME, luaopen_util}, {LUA_LOGLIBNAME, luaopen_log}, {LUA_SIGNALLIBNAME, luaopen_signal}, {NULL, NULL} diff --git a/src/l_rawio.c b/src/l_rawio.c index 889aeb7..779d6ae 100644 --- a/src/l_rawio.c +++ b/src/l_rawio.c @@ -62,7 +62,7 @@ static int l_rawio_open(lua_State *L) static int l_rawio_setnonblock(lua_State *L) { - int fd = luaL_checkinteger(L,1); + int fd = luaL_checkint(L,1); int ret = fcntl(fd, F_SETFL, O_NONBLOCK); if(ret == -1) { @@ -77,7 +77,7 @@ static int l_rawio_setnonblock(lua_State *L) static int l_rawio_write(lua_State *L) { - int fd = luaL_checkinteger(L,1); + int fd = luaL_checkint(L,1); size_t len = 0; const char* data = luaL_checklstring(L, 2, &len); @@ -95,8 +95,8 @@ static int l_rawio_write(lua_State *L) static int l_rawio_read(lua_State *L) { - int fd = luaL_checkinteger(L,1); - size_t len = luaL_checkinteger(L,2); + int fd = luaL_checkint(L,1); + size_t len = luaL_checkint(L,2); char* data = malloc(len); if(!data) { lua_pushnil(L); @@ -120,7 +120,7 @@ static int l_rawio_read(lua_State *L) static int l_rawio_close(lua_State *L) { - close(luaL_checkinteger(L,1)); + close(luaL_checkint(L,1)); return 0; } diff --git a/src/l_util.c b/src/l_util.c new file mode 100644 index 0000000..778c5b7 --- /dev/null +++ b/src/l_util.c @@ -0,0 +1,164 @@ +/* + * gcsd + * + * gcsd the generic command sequencer daemon can be used to serialize + * commands sent over various paralell communication channels to a + * single command output. It can be seen as a multiplexer for any + * kind of communication between a single resource and various clients + * which want to submit commands to it or query information from it. + * gcsd is written in C and Lua. The goal is to provide an easy to + * understand high level API based on Lua which can be used to + * implement the business logic of the so formed multiplexer daemon. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@spreadspace.org> + * Christian Pointner <equinox@spreadspace.org> + * + * This file is part of gcsd. + * + * gcsd is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * gcsd is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gcsd. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lua.h> +#include <lauxlib.h> + +#include <sys/select.h> +#include <errno.h> +#include <string.h> + +#include "l_util.h" + +static int get_fd(lua_State *L) +{ + if(!lua_istable(L, -1)) + return -1; + + lua_pushstring(L, "getfd"); + lua_gettable(L, -2); + if(lua_isnil(L, -1)) { + lua_pop(L,1); + return -1; + } + lua_pushvalue(L, -2); // self + lua_call(L, 1, 1); + int fd = luaL_checkint(L, -1); + lua_pop(L, 1); + return fd; +} + +static int collect_fds(lua_State *L, int table_idx, fd_set* fds, int max_fd) +{ + FD_ZERO(fds); + int i; + for(i = 1;;i++) { + int fd; + lua_pushinteger(L, i); + lua_gettable(L, table_idx); + if(lua_isnil(L,-1)) { + lua_pop(L, 1); + break; + } + fd = get_fd(L); + if(fd >= 0) { + FD_SET(fd, fds); + max_fd = fd > max_fd ? fd : max_fd; + } + lua_pop(L,1); + } + return max_fd; +} + +static void return_fds(lua_State *L, int table_idx, fd_set* fds) +{ + lua_newtable(L); + int i, j = 1; + for(i = 1;;i++) { + int fd; + lua_pushinteger(L, i); + lua_gettable(L, table_idx); + if(lua_isnil(L,-1)) { + lua_pop(L, 1); + break; + } + fd = get_fd(L); + if(fd >= 0 && FD_ISSET(fd, fds)) { + lua_pushinteger(L, j++); + lua_insert(L, -2); + lua_settable(L, -3); + } + else + lua_pop(L,1); + } +} + +static int l_util_select(lua_State *L) +{ + if(!lua_istable(L, 1)) + luaL_error(L, "table expected as first argument"); + if(!lua_istable(L, 2)) + luaL_error(L, "table expected as second argument"); + int ms = luaL_optint(L, 3, -1); + + fd_set readables, writeables; + int max_fd = collect_fds(L, 1, &readables, 0); + max_fd = collect_fds(L, 2, &writeables, max_fd); + + struct timeval tv; + struct timeval* timeout = NULL; + if(timeout > 0) { + tv.tv_sec = 0; + tv.tv_usec = ms * 1000; + timeout = &tv; + } + int ret = select(max_fd+1, &readables, &writeables, NULL, timeout); + if(ret <= 0) { + lua_pushnil(L); + lua_pushnil(L); + if(!ret) + lua_pushstring(L, "timeout"); + else if(errno == EINTR) + lua_pushstring(L, "signal"); + else + lua_pushstring(L, strerror(errno)); // FIXXXXXME: strerror is not threadsafe!!! + return 3; + } + return_fds(L, 1, &readables); + return_fds(L, 2, &writeables); + return 2; +} + +static int l_util_exec(lua_State *L) +{ + //TODO: implement fork/exec + return 0; +} + +static int l_util_waitpid(lua_State *L) +{ + //TODO: implement waitpid + return 0; +} + +static const struct luaL_reg util_funcs [] = { + { "select", l_util_select }, + { "exec", l_util_exec }, + { "waitpid", l_util_waitpid }, + { NULL, NULL } +}; + +LUALIB_API int luaopen_util(lua_State *L) +{ + luaL_register(L, LUA_UTILLIBNAME, util_funcs); + return 1; +} diff --git a/src/l_util.h b/src/l_util.h new file mode 100644 index 0000000..c0b558a --- /dev/null +++ b/src/l_util.h @@ -0,0 +1,41 @@ +/* + * gcsd + * + * gcsd the generic command sequencer daemon can be used to serialize + * commands sent over various paralell communication channels to a + * single command output. It can be seen as a multiplexer for any + * kind of communication between a single resource and various clients + * which want to submit commands to it or query information from it. + * gcsd is written in C and Lua. The goal is to provide an easy to + * understand high level API based on Lua which can be used to + * implement the business logic of the so formed multiplexer daemon. + * + * + * Copyright (C) 2009-2010 Markus Grueneis <gimpf@spreadspace.org> + * Christian Pointner <equinox@spreadspace.org> + * + * This file is part of gcsd. + * + * gcsd is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * gcsd is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gcsd. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GCSD_l_util_h_INCLUDED +#define GCSD_l_util_h_INCLUDED + +#include <lua.h> + +#define LUA_UTILLIBNAME "util" +LUALIB_API int luaopen_util(lua_State *L); + +#endif diff --git a/src/main_loop.lua b/src/main_loop.lua index ec68b70..c310cdb 100644 --- a/src/main_loop.lua +++ b/src/main_loop.lua @@ -30,7 +30,6 @@ -- along with gcsd. If not, see <http://www.gnu.org/licenses/>. -- -local socket = require("socket") local defines = require("defines") function get_readables() @@ -83,10 +82,16 @@ function main_loop(opt) end while return_value == 0 do - local readable, writeable, err = socket.select({ sig, unpack(get_readables()) }, get_writeables()) + local readable, writeable, err = util.select({ sig, unpack(get_readables()) }, get_writeables(), 10) if(err) then - log.printf(log.ERROR, "select returned with error: %s", err) - return_value = -1 + if(err == "timeout") then + -- TODO: handle timeouts + elseif(err == "signal") then + -- ignore this + else + log.printf(log.ERROR, "select returned with error: %s", err) + return_value = -1 + end else for _, reader in ipairs(readable) do if(reader == sig) then diff --git a/src/module_list.lua b/src/module_list.lua index 89d4920..5b35fe9 100644 --- a/src/module_list.lua +++ b/src/module_list.lua @@ -43,7 +43,7 @@ function mt.__index(table, key) log.printf(log.DEBUG, "load module class: %s", key) local old_path = package.path - package.path = "./modules/?.lua" + package.path = package.path .. ";./modules/?.lua" value = require(key) package.path = old_path |