--- /dev/null
+/*
+ * Copyright (c) 2012, 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <murphy/common/debug.h>
+
+#include "cpu.h"
+
+
+typedef struct {
+ uint64_t user;
+ uint64_t nice;
+ uint64_t system;
+ uint64_t idle;
+ uint64_t iowait;
+ uint64_t irq;
+ uint64_t softirq;
+ uint64_t steal;
+ uint64_t guest;
+ uint64_t guest_nice;
+} cpu_ticks_t;
+
+
+typedef struct {
+ cpu_ticks_t ticks[2];
+ int curr;
+ int statfd;
+} cpu_load_t;
+
+
+
+static cpu_load_t load = { .statfd = -1 };
+
+
+int read_ticks(int fd, cpu_ticks_t *t)
+{
+ char buf[256], *p, *n;
+ int len;
+
+ lseek(fd, 0, SEEK_SET);
+
+ if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
+ return -1;
+
+ buf[len] = '\0';
+ p = buf;
+
+ if (p[0] != 'c' || p[1] != 'p' || p[2] != 'u' || p[3] != ' ') {
+ errno = EILSEQ;
+ return -1;
+ }
+
+ n = NULL;
+
+ p += 4;
+ t->user = strtoll(p, &n, 10);
+
+ if (*n != ' ')
+ return -1;
+
+ t->nice = strtoll((p = n), &n, 10);
+
+ if (*n != ' ')
+ return -1;
+
+ t->system = strtoll((p = n), &n, 10);
+
+ if (*n != ' ')
+ return -1;
+
+ t->idle = strtoll((p = n), &n, 10);
+
+ if (*n != ' ')
+ return -1;
+
+ t->iowait = strtoll((p = n), &n, 10);
+
+ if (*n != ' ')
+ return -1;
+
+ t->irq = strtoll((p = n), &n, 10);
+
+ if (*n != ' ')
+ return -1;
+
+ t->softirq = strtoll((p = n), &n, 10);
+
+ if (*n == '\n') {
+ t->steal = t->guest = t->guest_nice = 0;
+ return 0;
+ }
+ if (*n != ' ')
+ return -1;
+
+ t->steal = strtoll((p = n), &n, 10);
+
+ if (*n == '\n') {
+ t->guest = t->guest_nice = 0;
+ return 0;
+ }
+ if (*n != ' ')
+ return -1;
+
+ t->guest = strtoll((p = n), &n, 10);
+
+ if (*n == '\n') {
+ t->guest_nice = 0;
+ return 0;
+ }
+ if (*n != ' ')
+ return -1;
+
+ t->guest_nice = strtoll((p = n), &n, 10);
+
+ if (*n == '\n')
+ return 0;
+
+ return -1;
+}
+
+
+static void dump_ticks(char *msg, cpu_ticks_t *t)
+{
+ mrp_debug("%s: user=%lld, nice=%lld, system=%lld", msg,
+ t->user, t->nice, t->system);
+ mrp_debug("%s: idle=%lld, iowait=%lld, irq=%lld", msg,
+ t->idle, t->iowait, t->irq);
+ mrp_debug("%s: softirq=%lld, (%lld, %lld, %lld)", msg,
+ t->softirq, t->steal, t->guest, t->guest_nice);
+}
+
+
+int cpu_get_load(int *loadp, int *idlep, int *iowaitp)
+{
+ cpu_ticks_t *prev, *curr;
+ uint64_t usr, nic, sys, idl, iow, total;
+
+ if (load.statfd < 0) {
+ load.statfd = open("/proc/stat", O_RDONLY);
+
+ if (load.statfd < 0)
+ return -1;
+
+ if (read_ticks(load.statfd, load.ticks) < 0)
+ return -1;
+
+ errno = EAGAIN;
+ return -1;
+ }
+
+ prev = load.ticks + !!load.curr;
+ curr = load.ticks + !!!load.curr;
+
+ if (read_ticks(load.statfd, curr) < 0)
+ return -1;
+
+ dump_ticks("prev: ", prev);
+ dump_ticks("curr: ", curr);
+
+#define DIFF(_fld) (curr->_fld - prev->_fld)
+
+ total = (usr = DIFF(user)) + (nic = DIFF(nice)) + (sys = DIFF(system)) +
+ (idl = DIFF(idle)) + (iow = DIFF(iowait)) + DIFF(irq) + DIFF(softirq) +
+ DIFF(steal) + DIFF(guest) + DIFF(guest_nice);
+
+
+#undef DIFF
+
+ if (idlep != NULL)
+ *idlep = (int)floor(0.5 + 100.0 * idl / total);
+
+ if (iowaitp != NULL)
+ *iowaitp = (int)floor(0.5 + 100.0 * iow / total);
+
+ if (loadp != NULL)
+ *loadp = (int)(0.5 + 100.0 * (usr + nic + sys + iow) / total);
+
+ load.curr = !load.curr;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2012, 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <murphy/common/macros.h>
+#include <murphy/common/debug.h>
+#include <murphy/common/log.h>
+#include <murphy/common/mm.h>
+#include <murphy/common/list.h>
+#include <murphy/common/mainloop.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+#include <murphy/core/lua-bindings/murphy.h>
+
+#include "cpu.h"
+
+#define MIN_INTERVAL 1000 /* minimal sampling interval */
+#define DEFAULT_INTERVAL 5000 /* default sampling interval */
+
+typedef struct sysmon_s sysmon_t;
+typedef struct sysmon_lua_s sysmon_lua_t;
+typedef struct cpu_watch_s cpu_watch_t;
+typedef struct mem_watch_s mem_watch_t;
+
+static int sysmon_lua_create(lua_State *L);
+static void sysmon_lua_destroy(void *data);
+static void sysmon_lua_changed(void *data, lua_State *L, int member);
+static ssize_t sysmon_lua_tostring(mrp_lua_tostr_mode_t mode, char *buf,
+ size_t size, lua_State *L, void *data);
+
+static int sysmon_lua_add_cpu_watch(lua_State *L);
+static int sysmon_lua_del_cpu_watch(lua_State *L);
+static int sysmon_lua_add_mem_watch(lua_State *L);
+static int sysmon_lua_del_mem_watch(lua_State *L);
+
+
+/*
+ * Lua system-monitor object
+ */
+
+#define SYSMON_LUA_CLASS MRP_LUA_CLASS(sysmon, lua)
+
+struct sysmon_lua_s {
+ mrp_context_t *ctx; /* murphy context */
+ lua_State *L; /* Lua execution context */
+ mrp_list_hook_t cpu_watches; /* active CPU watches */
+ mrp_list_hook_t mem_watches; /* active memory watches */
+ int interval; /* sampling interval */
+ mrp_timer_t *t; /* sampling timer */
+ int next_id; /* next watch id */
+};
+
+
+/*
+ * CPU load monitor
+ */
+
+typedef struct {
+ char *name; /* limit name */
+ int limit; /* upper limit */
+} cpu_limit_t;
+
+typedef enum {
+ CPU_WATCH_INVALID,
+ CPU_WATCH_LOAD, /* track overall CPU load */
+ CPU_WATCH_IDLE, /* track CPU idle state */
+ CPU_WATCH_IOWAIT /* track CPU I/O wait state */
+} cpu_watch_type_t;
+
+struct cpu_watch_s {
+ mrp_list_hook_t hook; /* to list of watches */
+ int id; /* watch id */
+ cpu_watch_type_t type; /* watch type, what to track */
+ cpu_limit_t *limits; /* limits for this watch */
+ int nlimit; /* number of limits */
+ cpu_limit_t *limit; /* limit index of last sampled value */
+ int callback; /* reference to callback */
+ int data; /* reference to callback data */
+};
+
+
+/*
+ * Lua system-monitor class
+ */
+
+#define OFFS(m) MRP_OFFSET(sysmon_lua_t, m)
+#define NOTIFY MRP_LUA_CLASS_NOTIFY
+
+MRP_LUA_METHOD_LIST_TABLE(sysmon_lua_methods,
+ MRP_LUA_METHOD_CONSTRUCTOR(sysmon_lua_create)
+ MRP_LUA_METHOD(add_cpu_watch, sysmon_lua_add_cpu_watch)
+ MRP_LUA_METHOD(del_cpu_watch, sysmon_lua_del_cpu_watch)
+ MRP_LUA_METHOD(add_mem_watch, sysmon_lua_add_mem_watch)
+ MRP_LUA_METHOD(add_mem_watch, sysmon_lua_del_mem_watch));
+
+MRP_LUA_METHOD_LIST_TABLE(sysmon_lua_overrides,
+ MRP_LUA_OVERRIDE_CALL(sysmon_lua_create));
+
+MRP_LUA_MEMBER_LIST_TABLE(sysmon_lua_members,
+ MRP_LUA_CLASS_INTEGER("interval", OFFS(interval), NULL, NULL, NOTIFY));
+
+MRP_LUA_DEFINE_CLASS(sysmon, lua, sysmon_lua_t, sysmon_lua_destroy,
+ sysmon_lua_methods, sysmon_lua_overrides,
+ sysmon_lua_members, NULL, sysmon_lua_changed,
+ sysmon_lua_tostring, NULL, MRP_LUA_CLASS_EXTENSIBLE);
+
+MRP_LUA_CLASS_CHECKER(sysmon_lua_t, sysmon_lua, SYSMON_LUA_CLASS);
+
+typedef enum {
+ SYSMON_MEMBER_INTERVAL,
+} sysmon_member_t;
+
+
+static inline cpu_watch_type_t cpu_watch_type(const char *name)
+{
+ if (!strcmp(name, "load")) return CPU_WATCH_LOAD;
+ else if (!strcmp(name, "idle")) return CPU_WATCH_IDLE;
+ else if (!strcmp(name, "iowait")) return CPU_WATCH_IOWAIT;
+ else return CPU_WATCH_INVALID;
+}
+
+
+static inline const char *cpu_watch_name(cpu_watch_type_t type)
+{
+ switch (type) {
+ case CPU_WATCH_LOAD: return "load";
+ case CPU_WATCH_IDLE: return "idle";
+ case CPU_WATCH_IOWAIT: return "iowait";
+ default: return "<invalid>";
+ }
+}
+
+
+static int cmp_limits(const void *ptr1, const void *ptr2)
+{
+ cpu_limit_t *l1 = (cpu_limit_t *)ptr1;
+ cpu_limit_t *l2 = (cpu_limit_t *)ptr2;
+
+ return l1->limit - l2->limit;
+}
+
+
+static cpu_watch_t *cpu_watch_create(sysmon_lua_t *sm, char *ebuf, size_t esize)
+{
+ lua_State *L = sm->L;
+ cpu_watch_t *w;
+ const char *kname;
+ int ktype, limit, i;
+ size_t klen;
+ bool has_max;
+
+ if ((w = mrp_allocz(sizeof(*w))) == NULL) {
+ snprintf(ebuf, esize, "faled to allocate CPU watch");
+ return NULL;
+ }
+
+ mrp_list_init(&w->hook);
+ w->callback = LUA_NOREF;
+ w->data = LUA_NOREF;
+
+ if ((w->type = cpu_watch_type(lua_tostring(L, 2))) == CPU_WATCH_INVALID) {
+ snprintf(ebuf, esize, "invalid CPU watch type %s", lua_tostring(L, 2));
+ goto fail;
+ }
+
+ has_max = false;
+
+ MRP_LUA_FOREACH_ALL(L, i, 3, ktype, kname, klen) {
+ if (ktype != LUA_TSTRING || lua_type(L, -1) != LUA_TNUMBER) {
+ snprintf(ebuf, esize, "invalid CPU watch limit entry #%d", i);
+ goto fail;
+ }
+
+ if ((limit = lua_tointeger(L, -1)) < 0 || limit > 100) {
+ snprintf(ebuf, esize, "CPU watch limit #%d (%d %%) out of range",
+ i, limit);
+ goto fail;
+ }
+
+ if (mrp_reallocz(w->limits, w->nlimit, w->nlimit + 1) == NULL) {
+ snprintf(ebuf, esize, "failed to extend CPU watch limit table");
+ goto fail;
+ }
+
+ if ((w->limits[i].name = mrp_strdup(kname)) == NULL) {
+ snprintf(ebuf, esize, "failed to extend CPU watch limit table");
+ goto fail;
+ }
+
+ w->limits[i].limit = limit;
+ w->nlimit++;
+
+ if (limit == 100)
+ has_max = true;
+ }
+
+ if (w->nlimit < 1) {
+ snprintf(ebuf, esize, "expecting at least 1 CPU watch limit");
+ goto fail;
+ }
+
+ if (!has_max) {
+ if (mrp_reallocz(w->limits, w->nlimit, w->nlimit + 1) == NULL) {
+ snprintf(ebuf, esize, "failed to add CPU watch limit 100");
+ goto fail;
+ }
+
+ if ((w->limits[w->nlimit].name = mrp_strdup("full")) == NULL) {
+ snprintf(ebuf, esize, "failed to add CPU watch limit 100");
+ goto fail;
+ }
+
+ w->limits[w->nlimit].limit = 100;
+ w->nlimit++;
+ }
+
+ qsort(w->limits, w->nlimit, sizeof(w->limits[0]), cmp_limits);
+ w->limit = w->limits;
+
+ w->id = sm->next_id++;
+ w->callback = mrp_lua_object_ref_value(sm, L, 4);
+ w->data = mrp_lua_object_ref_value(sm, L, 5);
+
+ mrp_list_append(&sm->cpu_watches, &w->hook);
+
+ return w;
+
+ fail:
+ for (i = 0; i < w->nlimit; i++)
+ mrp_free(w->limits[i].name);
+ mrp_free(w->limits);
+ mrp_free(w);
+
+ return NULL;
+}
+
+
+static void cpu_watch_destroy(sysmon_lua_t *sm, cpu_watch_t *w)
+{
+ int i;
+
+ mrp_list_delete(&w->hook);
+ mrp_lua_object_unref_value(sm, sm->L, w->callback);
+ mrp_lua_object_unref_value(sm, sm->L, w->data);
+
+ for (i = 0; i < w->nlimit; i++)
+ mrp_free(w->limits[i].name);
+ mrp_free(w->limits);
+
+ mrp_free(w);
+}
+
+
+static cpu_watch_t *cpu_watch_find(sysmon_lua_t *sm, int id)
+{
+ mrp_list_hook_t *p, *n;
+ cpu_watch_t *w;
+
+ mrp_list_foreach(&sm->cpu_watches, p, n) {
+ w = mrp_list_entry(p, typeof(*w), hook);
+
+ if (w->id == id)
+ return w;
+ }
+
+ return NULL;
+}
+
+
+static void cpu_watch_notify(sysmon_lua_t *sm, cpu_watch_t *w, const char *prev,
+ const char *curr)
+{
+ if (!mrp_lua_object_deref_value(sm, sm->L, w->callback, false)) {
+ mrp_log_error("Failed to dereference Lua CPU watch callback.");
+ return;
+ }
+
+ lua_pushstring(sm->L, cpu_watch_name(w->type));
+ lua_pushstring(sm->L, prev);
+ lua_pushstring(sm->L, curr);
+ mrp_lua_object_deref_value(sm, sm->L, w->data, true);
+
+ if (lua_pcall(sm->L, 4, 0, 0) != 0)
+ mrp_log_error("Failed to notify Lua CPU watch (error: %s).",
+ lua_tostring(sm->L, -1));
+}
+
+
+static void cpu_watch_check(sysmon_lua_t *sm, cpu_watch_t *w,
+ int load, int idle, int iowait)
+{
+ cpu_limit_t *l;
+ int i, value;
+
+ switch (w->type) {
+ default:
+ case CPU_WATCH_LOAD: value = load; break;
+ case CPU_WATCH_IDLE: value = idle; break;
+ case CPU_WATCH_IOWAIT: value = iowait; break;
+ }
+
+ for (i = 0, l = w->limits; i < w->nlimit; i++, l++) {
+ if (value <= l->limit) {
+ if (w->limit != l) {
+ cpu_watch_notify(sm, w, w->limit->name, l->name);
+ w->limit = l;
+ }
+ break;
+ }
+ }
+}
+
+
+static void sample_cpu_load(mrp_timer_t *t, void *user_data)
+{
+ sysmon_lua_t *sm = (sysmon_lua_t *)user_data;
+ int idle, iowait, load;
+ mrp_list_hook_t *p, *n;
+ cpu_watch_t *w;
+
+ MRP_UNUSED(t);
+
+ if (cpu_get_load(&load, &idle, &iowait) < 0) {
+ if (errno != EAGAIN)
+ mrp_log_error("cpu_get_load failed (%d: %s)", errno,
+ strerror(errno));
+ }
+ else {
+ mrp_debug("load = %d, idle = %d, iowait = %d", load, idle, iowait);
+
+ mrp_list_foreach(&sm->cpu_watches, p, n) {
+ w = mrp_list_entry(p, typeof(*w), hook);
+ cpu_watch_check(sm, w, load, idle, iowait);
+ }
+ }
+}
+
+
+static void sysmon_lua_changed(void *data, lua_State *L, int member)
+{
+ sysmon_lua_t *sm = (sysmon_lua_t *)data;
+
+ MRP_UNUSED(L);
+
+ switch (member) {
+ case SYSMON_MEMBER_INTERVAL:
+ if (sm->interval < MIN_INTERVAL)
+ sm->interval = MIN_INTERVAL;
+
+ if (sm->t != NULL)
+ mrp_mod_timer(sm->t, sm->interval);
+
+ mrp_log_info("system-monitor: sampling interval set to %d msecs.",
+ sm->interval);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static sysmon_lua_t *singleton(lua_State *L)
+{
+ static sysmon_lua_t *sm = NULL;
+
+ if (L == NULL) {
+ mrp_debug("clearing system-monitor singleton object");
+ sm = NULL;
+ }
+ else if (sm == NULL) {
+ mrp_debug("creating system-monitor singleton object");
+ sm = (sysmon_lua_t *)mrp_lua_create_object(L, SYSMON_LUA_CLASS,
+ NULL, 0);
+ mrp_list_init(&sm->cpu_watches);
+ mrp_list_init(&sm->mem_watches);
+
+ sm->L = L;
+ sm->ctx = mrp_lua_get_murphy_context();
+ sm->next_id = 1;
+ sm->interval = DEFAULT_INTERVAL;
+ }
+
+ return sm;
+}
+
+
+static int sysmon_lua_create(lua_State *L)
+{
+ sysmon_lua_t *sm = singleton(L);
+
+ mrp_lua_push_object(L, sm);
+
+ return 1;
+}
+
+
+static int sysmon_lua_get(lua_State *L)
+{
+ return sysmon_lua_create(L);
+}
+
+
+static void sysmon_lua_destroy(void *data)
+{
+ sysmon_lua_t *sm = (sysmon_lua_t *)data;
+ mrp_list_hook_t *p, *n;
+ cpu_watch_t *w;
+
+ mrp_list_foreach(&sm->cpu_watches, p, n) {
+ w = mrp_list_entry(p, typeof(*w), hook);
+ cpu_watch_destroy(sm, w);
+ }
+
+ mrp_del_timer(sm->t);
+ sm->t = NULL;
+
+ singleton(NULL);
+}
+
+
+static int sysmon_lua_add_cpu_watch(lua_State *L)
+{
+ sysmon_lua_t *sm;
+ cpu_watch_t *w;
+ char err[256];
+ int narg;
+
+ if ((narg = lua_gettop(L)) != 5)
+ return luaL_error(L, "expecting 5 arguments, got %d", narg);
+
+ sm = sysmon_lua_check(L, 1);
+
+ luaL_checktype(L, 2, LUA_TSTRING);
+ luaL_checktype(L, 3, LUA_TTABLE);
+ luaL_checktype(L, 4, LUA_TFUNCTION);
+ luaL_checkany(L, 5);
+
+ if ((w = cpu_watch_create(sm, err, sizeof(err))) == NULL)
+ return luaL_error(L, "%s", err);
+
+ if (sm->t == NULL)
+ sm->t = mrp_add_timer(sm->ctx->ml, 2000, sample_cpu_load, sm);
+
+ lua_pushinteger(L, w->id);
+ return 1;
+}
+
+
+static int sysmon_lua_del_cpu_watch(lua_State *L)
+{
+ sysmon_lua_t *sm = sysmon_lua_check(L, 1);
+ int id = luaL_checkinteger(L, 2);
+ cpu_watch_t *w = cpu_watch_find(sm, id);
+
+ if (w != NULL) {
+ cpu_watch_destroy(sm, w);
+
+ if (mrp_list_empty(&sm->cpu_watches) &&
+ mrp_list_empty(&sm->mem_watches)) {
+ mrp_del_timer(sm->t);
+ sm->t = NULL;
+ }
+ }
+
+ return 0;
+}
+
+
+static int sysmon_lua_add_mem_watch(lua_State *L)
+{
+ MRP_UNUSED(L);
+
+ mrp_debug("should add memory usage watch...");
+
+ return 0;
+}
+
+
+static int sysmon_lua_del_mem_watch(lua_State *L)
+{
+ MRP_UNUSED(L);
+
+ mrp_debug("should delete memory usage watch...");
+
+ return 0;
+}
+
+
+static ssize_t sysmon_lua_tostring(mrp_lua_tostr_mode_t mode, char *buf,
+ size_t size, lua_State *L, void *data)
+{
+ sysmon_lua_t *sm = (sysmon_lua_t *)data;
+
+ MRP_UNUSED(L);
+
+ switch (mode & MRP_LUA_TOSTR_MODEMASK) {
+ case MRP_LUA_TOSTR_LUA:
+ default:
+ return snprintf(buf, size, "{%s system-monitor @ %d msecs}",
+ sm->t ? "active" : "inactive", sm->interval);
+ }
+}
+
+
+
+
+MURPHY_REGISTER_LUA_BINDINGS(murphy, SYSMON_LUA_CLASS,
+ { "get_system_monitor", sysmon_lua_get });