From 0a9bb105ff1534868886e68e3309aabc6c0315c0 Mon Sep 17 00:00:00 2001 From: deva Date: Thu, 30 Jun 2011 12:56:46 +0000 Subject: Use stack manipulation through c, rather than pragram text generation/parsing to create query result values in lua maps. --- server/src/luaquerymapper.cc | 131 ++++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 33 deletions(-) diff --git a/server/src/luaquerymapper.cc b/server/src/luaquerymapper.cc index fcdce85..380960c 100644 --- a/server/src/luaquerymapper.cc +++ b/server/src/luaquerymapper.cc @@ -29,35 +29,78 @@ #include #include -static std::string loadresultstring(QueryResult &res, std::string group = "") +static bool hasField(lua_State *L, int i, std::string name) { + lua_getfield(L, i, name.c_str()); + bool ret = lua_isnil(L, lua_gettop(L)); + lua_pop(L, 1); + return ret; +} + +static void loadResult(lua_State *L, QueryResult &res, + std::vector group = std::vector()) +{ + int grp = 0; + std::vector::iterator gi = group.begin(); + while(gi != group.end()) { + const char *name = gi->c_str(); + printf("[%d: %s]", grp, name); fflush(stdout); + + if(grp == 0) grp = LUA_GLOBALSINDEX; + if(hasField(L, grp, name)) { + lua_newtable(L); + lua_setfield(L, grp, name); + lua_getfield(L, grp, name); + } + + grp = lua_gettop(L); + gi++; + } + printf("\n"); fflush(stdout); + std::string s; std::stringstream timestamp; timestamp << res.timestamp; std::map< std::string, std::string >::iterator v = res.values.begin(); while(v != res.values.end()) { - std::string grp = (*v).first; - std::string::size_type idx = -1; - while((idx = grp.find(".", idx + 1)) != std::string::npos) { - s += group + grp.substr(0, idx) + " = {}\n"; + const char *name = v->first.c_str(); + + if(grp == 0) grp = LUA_GLOBALSINDEX; + if(hasField(L, grp, name)) { + lua_newtable(L); + lua_setfield(L, grp, name); } - s += group + (*v).first + " = {}\n"; - s += group + (*v).first + ".value = \"" + (*v).second + "\"\n"; - s += group + (*v).first + ".timestamp = " + timestamp.str() + "\n"; - s += group + (*v).first + ".source = \"" + res.source + "\"\n"; + int val; + + lua_getfield(L, grp, name); + val = lua_gettop(L); + lua_pushstring(L, v->second.c_str()); + lua_setfield(L, val, "value"); + + lua_getfield(L, grp, name); + val = lua_gettop(L); + lua_pushstring(L, timestamp.str().c_str()); + lua_setfield(L, val, "timestamp"); + + lua_getfield(L, grp, name); + val = lua_gettop(L); + lua_pushstring(L, res.source.c_str()); + lua_setfield(L, val, "source"); + v++; } + while(lua_gettop(L) > 1) lua_pop(L, 1); + std::map< std::string, QueryResult >::iterator g = res.groups.begin(); while(g != res.groups.end()) { - s += group + (*g).first + " = {}\n"; - s += loadresultstring((*g).second, group + (*g).first + "."); + std::vector subgrp = group; + subgrp.push_back(g->first); + loadResult(L, g->second, subgrp); g++; } - - return s; } LUAQueryMapper::LUAQueryMapper() throw(Exception) @@ -82,21 +125,7 @@ LUAQueryMapper::~LUAQueryMapper() void LUAQueryMapper::addQueryResult(QueryResult &result) throw(Exception) { - std::string preload = loadresultstring(result); - - DEBUG(querymapper, "Preload:\n%s\n", preload.c_str()); - - if(luaL_loadbuffer(L, preload.c_str(), preload.size(), "preload")) { - error(lua_tostring(L, lua_gettop(L))); - return; - } - - // Run program (init) - if(lua_pcall(L, 0, LUA_MULTRET, 0)) { - error(lua_tostring(L, lua_gettop(L))); - return; - } - + loadResult(L, result); clean_top = lua_gettop(L); } @@ -202,7 +231,6 @@ std::string LUAQueryMapper::automap(const std::string &name) return automapstring; } - #ifdef TEST_LUAQUERYMAPPER //deps: exception.cc log.cc debug.cc //cflags: -I.. ${LUA_CFLAGS} @@ -211,22 +239,59 @@ std::string LUAQueryMapper::automap(const std::string &name) TEST_BEGIN; -QueryResult res; - time_t now = time(NULL); +{ + QueryResult res; + res.groups["test"].timestamp = now; + res.groups["test"].source = "test app"; + res.groups["test"].values["somevalue"] = "hello world"; + res.groups["test"].values["pi"] = "3.14"; + res.groups["test"].groups["subtest"].source = "test app 2"; + res.groups["test"].groups["subtest"].timestamp = now + 1; + res.groups["test"].groups["subtest"].values["somevalue"] = "hello world!"; + + LUAQueryMapper mapper; + mapper.addQueryResult(res); + + // Test simple value forwarding with nesting + std::string luamap = "return test.subtest.somevalue.value, test.subtest.somevalue.timestamp, test.subtest.somevalue.source"; + + Value value = mapper.map(luamap); + + TEST_EQUAL_STR(value.value, "hello world!", "Test value"); + TEST_EQUAL_INT(value.timestamp, now + 1, "Test timestamp"); + TEST_EQUAL_STR(value.source, "test app 2", "Test source"); + + luamap = "return test.somevalue.value, test.somevalue.timestamp, test.somevalue.source"; + + value = mapper.map(luamap); + + TEST_EQUAL_STR(value.value, "hello world", "Test value"); + TEST_EQUAL_INT(value.timestamp, now, "Test timestamp"); + TEST_EQUAL_STR(value.source, "test app", "Test source"); + + luamap = "return test.pi.value, test.pi.timestamp, test.pi.source"; + + value = mapper.map(luamap); + + TEST_EQUAL_STR(value.value, "3.14", "Test value"); + TEST_EQUAL_INT(value.timestamp, now, "Test timestamp"); + TEST_EQUAL_STR(value.source, "test app", "Test source"); +} + +QueryResult res; res.groups["test"].timestamp = now; res.groups["test"].source = "test app"; res.groups["test"].values["somevalue"] = "hello world"; res.groups["test"].values["pi"] = "3.1416"; - -//printf("%s\n", loadresultstring(res).c_str()); LUAQueryMapper mapper; mapper.addQueryResult(res); // Test simple value forwarding std::string luamap = "return test.somevalue.value, test.somevalue.timestamp, test.somevalue.source"; + Value value = mapper.map(luamap); TEST_EQUAL_STR(value.value, "hello world", "Test value"); -- cgit v1.2.3