int lsb_heka_timer_event(lsb_heka_sandbox *hsb, time_t t, bool shutdown) { static const char *func_name = "timer_event"; if (!hsb || (hsb->type != 'o' && hsb->type != 'a')) { return 1; } lua_State *lua = lsb_get_lua(hsb->lsb); if (!lua) return 1; if (lsb_pcall_setup(hsb->lsb, func_name)) { char err[LSB_ERROR_SIZE]; snprintf(err, LSB_ERROR_SIZE, "%s() function was not found", func_name); lsb_terminate(hsb->lsb, err); return 1; } // todo change if we need more than 1 sec resolution lua_pushnumber(lua, t * 1e9); lua_pushboolean(lua, shutdown); unsigned long long start, end; start = lsb_get_time(); if (lua_pcall(lua, 2, 0, 0) != 0) { char err[LSB_ERROR_SIZE]; size_t len = snprintf(err, LSB_ERROR_SIZE, "%s() %s", func_name, lua_tostring(lua, -1)); if (len >= LSB_ERROR_SIZE) { err[LSB_ERROR_SIZE - 1] = 0; } lsb_terminate(hsb->lsb, err); return 1; } end = lsb_get_time(); lsb_update_running_stats(&hsb->stats.te, (double)(end - start)); lsb_pcall_teardown(hsb->lsb); lua_gc(lua, LUA_GCCOLLECT, 0); return 0; }
static int process_message(lsb_heka_sandbox *hsb, lsb_heka_message *msg, lua_State *lua, int nargs, bool profile) { unsigned long long start, end; hsb->msg = msg; if (profile) { start = lsb_get_time(); } if (lua_pcall(lua, nargs, 2, 0) != 0) { char err[LSB_ERROR_SIZE]; const char *em = lua_tostring(lua, -1); if (hsb->type == 'i' && strcmp(em, LSB_SHUTTING_DOWN) == 0) { return 0; } size_t len = snprintf(err, LSB_ERROR_SIZE, "%s() %s", pm_func_name, em); if (len >= LSB_ERROR_SIZE) { err[LSB_ERROR_SIZE - 1] = 0; } lsb_terminate(hsb->lsb, err); return 1; } if (profile) { end = lsb_get_time(); lsb_update_running_stats(&hsb->stats.pm, (double)(end - start)); } hsb->msg = NULL; if (lua_type(lua, 1) != LUA_TNUMBER) { char err[LSB_ERROR_SIZE]; size_t len = snprintf(err, LSB_ERROR_SIZE, "%s() must return a numeric status code", pm_func_name); if (len >= LSB_ERROR_SIZE) { err[LSB_ERROR_SIZE - 1] = 0; } lsb_terminate(hsb->lsb, err); return 1; } int status = (int)lua_tointeger(lua, 1); switch (lua_type(lua, 2)) { case LUA_TNIL: lsb_set_error(hsb->lsb, NULL); break; case LUA_TSTRING: lsb_set_error(hsb->lsb, lua_tostring(lua, 2)); break; default: { char err[LSB_ERROR_SIZE]; int len = snprintf(err, LSB_ERROR_SIZE, "%s() must return a nil or string error message", pm_func_name); if (len >= LSB_ERROR_SIZE || len < 0) { err[LSB_ERROR_SIZE - 1] = 0; } lsb_terminate(hsb->lsb, err); return 1; } break; } lua_pop(lua, 2); lsb_pcall_teardown(hsb->lsb); if (status > 0) { char err[LSB_ERROR_SIZE]; size_t len = snprintf(err, LSB_ERROR_SIZE, "%s() received a termination status code", pm_func_name); if (len >= LSB_ERROR_SIZE) { err[LSB_ERROR_SIZE - 1] = 0; } lsb_terminate(hsb->lsb, err); return 1; } else if (status == LSB_HEKA_PM_FAIL) { ++hsb->stats.pm_cnt; ++hsb->stats.pm_failures; } else if (hsb->type != 'o' || status != LSB_HEKA_PM_RETRY) { ++hsb->stats.pm_cnt; } return status; }
static int output_message(hs_output_plugin *p, lsb_heka_message *msg) { int ret = 0, te_ret = 0; bool sample = p->sample; time_t current_t = time(NULL); unsigned long long start; if (msg->raw.s) { // non idle/empty message unsigned long long mmdelta = 0; if (sample) start = lsb_get_time(); bool matched = lsb_eval_message_matcher(p->mm, msg); if (sample) { mmdelta = lsb_get_time() - start; } if (matched) { if (p->async_len) { int i = p->sequence_id % p->async_len; p->async_cp[i].input.id = p->cur.input.id; p->async_cp[i].input.offset = p->cur.input.offset; p->async_cp[i].analysis.id = p->cur.analysis.id; p->async_cp[i].analysis.offset = p->cur.analysis.offset; } ret = lsb_heka_pm_output(p->hsb, msg, (void *)p->sequence_id, sample); if (ret <= 0) { if (ret == LSB_HEKA_PM_SENT) { p->batching = false; } else if (ret == LSB_HEKA_PM_BATCH) { p->batching = true; } else if (ret == LSB_HEKA_PM_SENT && !p->async_len) { lsb_heka_terminate_sandbox(p->hsb, "cannot use async checkpointing " "without a configured buffer"); ret = 1; } else if (ret == LSB_HEKA_PM_FAIL) { const char *err = lsb_heka_get_error(p->hsb); if (strlen(err) > 0) { hs_log(NULL, p->name, 4, "process_message returned: %d %s", ret, err); } } if (ret != LSB_HEKA_PM_RETRY) ++p->sequence_id; } } // advance the checkpoint if not batching/async if (ret <= 0 && !p->batching) { update_checkpoint(p); } if (mmdelta) { pthread_mutex_lock(&p->cp_lock); lsb_update_running_stats(&p->mms, mmdelta); p->sample = false; pthread_mutex_unlock(&p->cp_lock); } } if (ret <= 0 && p->ticker_interval && current_t >= p->ticker_expires) { te_ret = lsb_heka_timer_event(p->hsb, current_t, false); p->ticker_expires = current_t + p->ticker_interval; } if (ret > 0 || te_ret > 0) { hs_log(NULL, p->name, 3, "terminated: %s", lsb_heka_get_error(p->hsb)); return 1; } return ret; }