root/src/modules/lua.c

Revision fc9516a2d8a7585aaaffbaab77009199ca907c90, 18.7 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 7 years ago)

make loaders have configs, add a directory config to lua for pulling scripts, refs #28

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include "noit_conf.h"
9 #include "noit_module.h"
10 #include "noit_check.h"
11 #include "noit_check_tools.h"
12 #include "utils/noit_log.h"
13 #include "lua_noit.h"
14
15 #include <assert.h>
16
17 static noit_log_stream_t nlerr = NULL;
18 static noit_log_stream_t nldeb = NULL;
19 static noit_hash_table noit_coros = NOIT_HASH_EMPTY;
20
21 struct loader_conf {
22   char *script_dir;
23 };
24 static struct loader_conf *__get_loader_conf(noit_module_loader_t *self) {
25   struct loader_conf *c;
26   c = noit_image_get_userdata(&self->hdr);
27   if(!c) {
28     c = calloc(1, sizeof(*c));
29     noit_image_set_userdata(&self->hdr, c);
30   }
31   return c;
32 }
33 static void
34 noit_lua_loader_set_directory(noit_module_loader_t *self, char *dir) {
35   struct loader_conf *c = __get_loader_conf(self);
36   if(c->script_dir) free(c->script_dir);
37   c->script_dir = strdup(dir);
38 }
39 static const char *
40 noit_lua_loader_get_directory(noit_module_loader_t *self) {
41   struct loader_conf *c = __get_loader_conf(self);
42   return c->script_dir;
43 }
44
45 noit_lua_check_info_t *
46 get_ci(lua_State *L) {
47   noit_lua_check_info_t *v = NULL;
48   if(noit_hash_retrieve(&noit_coros, (const char *)&L, sizeof(L), (void **)&v))
49     return v;
50   return NULL;
51 }
52
53 static void
54 noit_event_dispose(void *ev) {
55   int mask;
56   eventer_t *value = ev;
57   eventer_t e = *value;
58   if(e->fd >= 0) e->opset->close(e->fd, &mask, e);
59   if(e->mask && eventer_remove(e)) eventer_free(e);
60   if(!e->mask) eventer_free(e);
61   free(ev);
62 }
63 void
64 noit_lua_check_register_event(noit_lua_check_info_t *ci, eventer_t e) {
65   eventer_t *eptr;
66   eptr = calloc(1, sizeof(*eptr));
67   memcpy(eptr, &e, sizeof(*eptr));
68   if(!ci->events) ci->events = calloc(1, sizeof(*ci->events));
69   assert(noit_hash_store(ci->events, (const char *)eptr, sizeof(*eptr), eptr));
70 }
71 void
72 noit_lua_check_deregister_event(noit_lua_check_info_t *ci, eventer_t e,
73                                 int tofree) {
74   assert(ci->events);
75   assert(noit_hash_delete(ci->events, (const char *)&e, sizeof(e),
76                           NULL, tofree ? noit_event_dispose : free));
77 }
78 void
79 noit_lua_check_clean_events(noit_lua_check_info_t *ci) {
80   noit_hash_destroy(ci->events, NULL, noit_event_dispose);
81   free(ci->events);
82   ci->events = NULL;
83 }
84
85 static void
86 noit_lua_hash_to_table(lua_State *L,
87                        noit_hash_table *t) {
88   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
89   const char *key, *value;
90   int klen;
91   lua_createtable(L, 0, t ? t->size : 0);
92   if(t) {
93     while(noit_hash_next(t, &iter, &key, &klen, (void **)&value)) {
94       lua_pushlstring(L, value, strlen(value));
95       lua_setfield(L, -2, key);
96     }
97   }
98   return;
99 }
100 static int
101 noit_module_index_func(lua_State *L) {
102   int n;
103   n = lua_gettop(L);    /* number of arguments */
104   assert(n == 2);
105   if(!luaL_checkudata(L, 1, "noit_module_t")) {
106     luaL_error(L, "metatable error, arg1 not a noit_module_t!");
107   }
108   return 0;
109 }
110 static int
111 noit_lua_set_available(lua_State *L) {
112   noit_check_t *check;
113   noit_lua_check_info_t *ci;
114   if(lua_gettop(L)) luaL_error(L, "wrong number of arguments");
115   check = lua_touserdata(L, lua_upvalueindex(1));
116   ci = check->closure;
117   ci->current.available = lua_tointeger(L, lua_upvalueindex(2));
118   return 0;
119 }
120 static int
121 noit_lua_set_state(lua_State *L) {
122   noit_check_t *check;
123   noit_lua_check_info_t *ci;
124   if(lua_gettop(L)) luaL_error(L, "wrong number of arguments");
125   check = lua_touserdata(L, lua_upvalueindex(1));
126   ci = check->closure;
127   ci->current.state = lua_tointeger(L, lua_upvalueindex(2));
128   return 0;
129 }
130 static int
131 noit_lua_set_status(lua_State *L) {
132   noit_check_t *check;
133   noit_lua_check_info_t *ci;
134   if(lua_gettop(L) != 1) luaL_error(L, "wrong number of arguments");
135   check = lua_touserdata(L, lua_upvalueindex(1));
136   ci = check->closure;
137   ci->current.status = strdup(lua_tostring(L, 1));
138   return 0;
139 }
140 static int
141 noit_lua_set_metric(lua_State *L) {
142   noit_check_t *check;
143   noit_lua_check_info_t *ci;
144   const char *metric_name;
145   metric_type_t metric_type;
146
147   double __n;
148   int32_t __i;
149   u_int32_t __I;
150   int64_t __l;
151   u_int64_t __L;
152
153   if(lua_gettop(L) != 2) luaL_error(L, "wrong number of arguments");
154   check = lua_touserdata(L, lua_upvalueindex(1));
155   ci = check->closure;
156   if(!lua_isstring(L, 1)) luaL_error(L, "argument #1 must be a string");
157   metric_name = lua_tostring(L, 1);
158   metric_type = lua_tointeger(L, lua_upvalueindex(2));
159   if(lua_isnil(L, 2)) {
160     noit_stats_set_metric(&ci->current, metric_name, metric_type, NULL);
161     return 0;
162   }
163   switch(metric_type) {
164     case METRIC_GUESS:
165     case METRIC_STRING:
166       noit_stats_set_metric(&ci->current, metric_name, metric_type,
167                             (void *)lua_tostring(L, 2));
168       break;
169     case METRIC_INT32:
170       __i = luaL_optinteger(L, 2, 0);
171       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__i);
172       break;
173     case METRIC_UINT32:
174       __I = luaL_optinteger(L, 2, 0);
175       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__I);
176       break;
177     case METRIC_INT64:
178       __l = luaL_optinteger(L, 2, 0);
179       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__l);
180       break;
181     case METRIC_UINT64:
182       __L = luaL_optinteger(L, 2, 0);
183       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__L);
184       break;
185     case METRIC_DOUBLE:
186       __n = luaL_optnumber(L, 2, 0);
187       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__n);
188       break;
189   }
190   return 0;
191 }
192 static int
193 noit_check_index_func(lua_State *L) {
194   int n;
195   const char *k;
196   noit_check_t **udata, *check;
197   n = lua_gettop(L);    /* number of arguments */
198   assert(n == 2);
199   if(!luaL_checkudata(L, 1, "noit_check_t")) {
200     luaL_error(L, "metatable error, arg1 not a noit_check_t!");
201   }
202   udata = lua_touserdata(L, 1);
203   check = *udata;
204   if(!lua_isstring(L, 2)) {
205     luaL_error(L, "metatable error, arg2 not a string!");
206   }
207   k = lua_tostring(L, 2);
208   switch(*k) {
209     case 'a':
210       if(!strcmp(k, "available")) {
211         lua_pushlightuserdata(L, check);
212         lua_pushinteger(L, NP_AVAILABLE);
213         lua_pushcclosure(L, noit_lua_set_available, 2);
214       }
215       else break;
216       return 1;
217     case 'b':
218       if(!strcmp(k, "bad")) {
219         lua_pushlightuserdata(L, check);
220         lua_pushinteger(L, NP_BAD);
221         lua_pushcclosure(L, noit_lua_set_state, 2);
222       }
223       else break;
224       return 1;
225     case 'c':
226       if(!strcmp(k, "config")) noit_lua_hash_to_table(L, check->config);
227       else break;
228       return 1;
229     case 'g':
230       if(!strcmp(k, "good")) {
231         lua_pushlightuserdata(L, check);
232         lua_pushinteger(L, NP_GOOD);
233         lua_pushcclosure(L, noit_lua_set_state, 2);
234       }
235       else break;
236       return 1;
237     case 'm':
238       if(!strcmp(k, "module")) lua_pushstring(L, check->module);
239
240 #define IF_METRIC_BLOCK(name,type) \
241       if(!strcmp(k, name)) { \
242         lua_pushlightuserdata(L, check); \
243         lua_pushinteger(L, type); \
244         lua_pushcclosure(L, noit_lua_set_metric, 2); \
245       }
246
247       else IF_METRIC_BLOCK("metric", METRIC_GUESS)
248       else IF_METRIC_BLOCK("metric_string", METRIC_STRING)
249       else IF_METRIC_BLOCK("metric_int32", METRIC_INT32)
250       else IF_METRIC_BLOCK("metric_uint32", METRIC_UINT32)
251       else IF_METRIC_BLOCK("metric_int64", METRIC_INT64)
252       else IF_METRIC_BLOCK("metric_uint64", METRIC_UINT64)
253       else IF_METRIC_BLOCK("metric_double", METRIC_DOUBLE)
254       else break;
255       return 1;
256     case 'n':
257       if(!strcmp(k, "name")) lua_pushstring(L, check->name);
258       else break;
259       return 1;
260     case 'p':
261       if(!strcmp(k, "period")) lua_pushinteger(L, check->period);
262       else break;
263       return 1;
264     case 's':
265       if(!strcmp(k, "status")) {
266         lua_pushlightuserdata(L, check);
267         lua_pushcclosure(L, noit_lua_set_status, 1);
268       }
269       else break;
270       return 1;
271     case 't':
272       if(!strcmp(k, "target")) lua_pushstring(L, check->target);
273       else if(!strcmp(k, "timeout")) lua_pushinteger(L, check->timeout);
274       else break;
275       return 1;
276     case 'u':
277       if(!strcmp(k, "unavailable")) {
278         lua_pushlightuserdata(L, check);
279         lua_pushinteger(L, NP_UNAVAILABLE);
280         lua_pushcclosure(L, noit_lua_set_available, 2);
281       }
282       else break;
283       return 1;
284     default:
285       break;
286   }
287   luaL_error(L, "noit_check_t no such element: %s", k);
288   return 0;
289 }
290 static void
291 noit_lua_setup_module(lua_State *L,
292                       noit_module_t *mod) {
293   noit_module_t **addr;
294   addr = (noit_module_t **)lua_newuserdata(L, sizeof(mod));
295   *addr = mod;
296   if(luaL_newmetatable(L, "noit_module_t") == 1) {
297     lua_pushcclosure(L, noit_module_index_func, 0);
298     lua_setfield(L, -2, "__index");
299   }
300   lua_setmetatable(L, -2);
301 }
302 static void
303 noit_lua_setup_check(lua_State *L,
304                      noit_check_t *check) {
305   noit_check_t **addr;
306   addr = (noit_check_t **)lua_newuserdata(L, sizeof(check));
307   *addr = check;
308   if(luaL_newmetatable(L, "noit_check_t") == 1) {
309     lua_pushcclosure(L, noit_check_index_func, 0);
310     lua_setfield(L, -2, "__index");
311   }
312   lua_setmetatable(L, -2);
313 }
314 static int
315 noit_lua_module_onload(noit_image_t *i) {
316   lua_State *L;
317   lua_module_closure_t *lmc;
318   lmc = noit_image_get_userdata(i);
319   L = lmc->lua_state;
320   if(luaL_dofile(L, lmc->script)) {
321     int i;
322     noitL(nlerr, "lua: %s.onload failed\n", lmc->object);
323     i = lua_gettop(L);
324     if(i>0) {
325       if(lua_isstring(L, i)) {
326         const char *err;
327         size_t len;
328         err = lua_tolstring(L, i, &len);
329         noitL(nlerr, "lua: %s\n", err);
330       }
331     }
332     return -1;
333   }
334
335   lua_getfield(L, LUA_GLOBALSINDEX, lmc->object);
336   if(lua_isnil(L, -1)) {
337     lua_pop(L, 1);
338     noitL(nlerr, "lua: no such object %s\n", lmc->object);
339     return -1;
340   }
341   lua_getfield(L, -1, "onload");
342   lua_remove(L, -2);
343   if(!lua_isfunction(L, -1)) {
344     lua_pop(L, 1);
345     /* No onload */
346     return 0;
347   }
348   noit_lua_setup_module(L, (noit_module_t *)i);
349   lua_pcall(L, 1, 1, 0);
350   if(lua_isnumber(L, -1)) {
351     int rv;
352     rv = lua_tointeger(L, -1);
353     lua_pop(L, 1);
354     return rv;
355   } else {
356     lua_pop(L,1);
357     noitL(nlerr, "%s.onload must return a integer\n", lmc->object);
358     return -1;
359   }
360   return 0;
361 }
362 #define LMC_DECL(L, mod) \
363   lua_State *L; \
364   lua_module_closure_t *lmc; \
365   lmc = noit_module_get_userdata(mod); \
366   L = lmc->lua_state
367 #define SETUP_CALL(L, func, failure) do { \
368   lua_getfield(L, LUA_GLOBALSINDEX, lmc->object); \
369   lua_getfield(L, -1, func); \
370   lua_remove(L, -2); \
371   if(!lua_isfunction(L, -1)) { \
372     lua_pop(L, 1); \
373     failure; \
374   } \
375 } while(0)
376 #define RETURN_INT(L, func) do { \
377   if(lua_isnumber(L, -1)) { \
378     int rv; \
379     rv = lua_tointeger(L, -1); \
380     lua_pop(L, 1); \
381     return rv; \
382   } \
383   lua_pop(L,1); \
384   noitL(nlerr, "%s.%s must return a integer\n", lmc->object, func); \
385 } while(0)
386
387 static int
388 noit_lua_module_config(noit_module_t *mod,
389                        noit_hash_table *options) {
390   LMC_DECL(L, mod);
391   SETUP_CALL(L, "config", return 0);
392
393   noit_lua_setup_module(L, mod);
394   noit_lua_hash_to_table(L, options);
395   lua_pcall(L, 2, 1, 0);
396
397   RETURN_INT(L, "config");
398   return -1;
399 }
400 static int
401 noit_lua_module_init(noit_module_t *mod) {
402   LMC_DECL(L, mod);
403   SETUP_CALL(L, "init", return 0);
404
405   noit_lua_setup_module(L, mod);
406   lua_pcall(L, 1, 1, 0);
407
408   RETURN_INT(L, "init");
409   return -1;
410 }
411 static void
412 noit_lua_module_cleanup(noit_module_t *mod, noit_check_t *check) {
413   noit_lua_check_info_t *ci = check->closure;
414   LMC_DECL(L, mod);
415   SETUP_CALL(L, "cleanup", goto clean);
416
417   noit_lua_setup_module(L, mod);
418   noit_lua_setup_check(L, check);
419   lua_pcall(L, 2, 0, 0);
420
421  clean:
422   if(ci) {
423     noit_lua_check_clean_events(ci);
424     free(ci);
425     check->closure = NULL;
426   }
427 }
428
429 /* Here is where the magic starts */
430 static void
431 noit_lua_log_results(noit_module_t *self, noit_check_t *check) {
432   noit_lua_check_info_t *ci = check->closure;
433   struct timeval duration;
434   u_int32_t duration_ms;
435
436   gettimeofday(&ci->finish_time, NULL);
437   sub_timeval(ci->finish_time, check->last_fire_time, &duration);
438
439   memcpy(&ci->current.whence, &ci->finish_time, sizeof(ci->current.whence));
440   ci->current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
441   duration_ms = ci->current.duration;
442
443   noit_check_set_stats(self, check, &ci->current);
444 }
445 int
446 noit_lua_yield(noit_lua_check_info_t *ci, int nargs) {
447   noitL(nldeb, "lua: %p yielding\n", ci->coro_state);
448   return lua_yield(ci->coro_state, nargs);
449 }
450 int
451 noit_lua_resume(noit_lua_check_info_t *ci, int nargs) {
452   int result, base;
453   noit_check_t *check;
454   check = ci->check;
455
456   noitL(nldeb, "lua: %p resuming\n", ci->coro_state);
457   result = lua_resume(ci->coro_state, nargs);
458   switch(result) {
459     case 0: /* success */
460       break;
461     case LUA_YIELD: /* The complicated case */
462       /* The person yielding had better setup an event
463        * to wake up the coro...
464        */
465       lua_gc(ci->lmc->lua_state, LUA_GCCOLLECT, 0);
466       goto done;
467     default: /* Errors */
468       noitL(nlerr, "lua resume returned: %d\n", result);
469       ci->current.status = ci->timed_out ? "timeout" : "unknown error";
470       ci->current.available = NP_UNAVAILABLE;
471       ci->current.state = NP_BAD;
472       base = lua_gettop(ci->coro_state);
473       if(base>0) {
474         if(lua_isstring(ci->coro_state, base)) {
475           const char *err;
476           err = lua_tostring(ci->coro_state, base);
477           if(err) ci->current.status = (char *)err;
478         }
479       }
480       break;
481   }
482   noit_lua_log_results(ci->self, ci->check);
483   noit_lua_module_cleanup(ci->self, ci->check);
484   check->flags &= ~NP_RUNNING;
485
486   lua_getglobal(ci->lmc->lua_state, "noit_coros");
487   luaL_unref(ci->lmc->lua_state, -1, ci->coro_state_ref);
488   lua_pop(ci->lmc->lua_state, 2);
489
490  done:
491   lua_gc(ci->lmc->lua_state, LUA_GCCOLLECT, 0);
492   return result;
493 }
494 static int
495 noit_lua_check_timeout(eventer_t e, int mask, void *closure,
496                        struct timeval *now) {
497   noit_check_t *check;
498   noit_lua_check_info_t *ci = closure;
499   check = ci->check;
500   noitL(nldeb, "lua: %p ->check_timeout\n", ci->coro_state);
501   ci->timed_out = 1;
502   noit_lua_check_deregister_event(ci, e, 0);
503   if(ci->coro_state) {
504     /* Our coro is still "in-flight". To fix this we will unreference
505      * it, garbage collect it and then ensure that it failes a resume
506      */
507     lua_getglobal(ci->lmc->lua_state, "noit_coros");
508     luaL_unref(ci->lmc->lua_state, -1, ci->coro_state_ref);
509     lua_pop(ci->lmc->lua_state, 2);
510     lua_gc(ci->lmc->lua_state, LUA_GCCOLLECT, 0);
511     assert(2 == noit_lua_resume(ci, 0));
512   } else {
513     noit_lua_log_results(ci->self, ci->check);
514     noit_lua_module_cleanup(ci->self, ci->check);
515     check->flags &= ~NP_RUNNING;
516   }
517   return 0;
518 }
519 static int
520 noit_lua_initiate(noit_module_t *self, noit_check_t *check) {
521   LMC_DECL(L, self);
522   noit_lua_check_info_t *ci;
523   struct timeval p_int, __now;
524   eventer_t e;
525
526   if(!check->closure) check->closure = calloc(1, sizeof(noit_lua_check_info_t));
527   ci = check->closure;
528
529   /* We cannot be running */
530   assert(!(check->flags & NP_RUNNING));
531   check->flags |= NP_RUNNING;
532
533   ci->self = self;
534   ci->check = check;
535   noit_check_stats_clear(&ci->current);
536
537   gettimeofday(&__now, NULL);
538   memcpy(&check->last_fire_time, &__now, sizeof(__now));
539
540   e = eventer_alloc();
541   e->mask = EVENTER_TIMER;
542   e->callback = noit_lua_check_timeout;
543   e->closure = ci;
544   memcpy(&e->whence, &__now, sizeof(__now));
545   p_int.tv_sec = check->timeout / 1000;
546   p_int.tv_usec = (check->timeout % 1000) * 1000;
547   add_timeval(e->whence, p_int, &e->whence);
548   noit_lua_check_register_event(ci, e);
549   eventer_add(e);
550
551   ci->lmc = lmc;
552   lua_getglobal(L, "noit_coros");
553   ci->coro_state = lua_newthread(L);
554   noit_hash_store(&noit_coros,
555                   (const char *)&ci->coro_state, sizeof(ci->coro_state),
556                   ci);
557   ci->coro_state_ref = luaL_ref(L, -2);
558   lua_pop(L, 1); /* pops noit_coros */
559
560   SETUP_CALL(ci->coro_state, "initiate", goto fail);
561   noit_lua_setup_module(ci->coro_state, ci->self);
562   noit_lua_setup_check(ci->coro_state, ci->check);
563   noit_lua_resume(ci, 2);
564
565   return 0;
566
567  fail:
568   noit_lua_log_results(ci->self, ci->check);
569   noit_lua_module_cleanup(ci->self, ci->check);
570   check->flags &= ~NP_RUNNING;
571   return -1;
572 }
573 /* This is the standard wrapper */
574 static int
575 noit_lua_module_initiate_check(noit_module_t *self, noit_check_t *check,
576                                int once, noit_check_t *cause) {
577   if(!check->closure) check->closure = calloc(1, sizeof(noit_lua_check_info_t));
578   INITIATE_CHECK(noit_lua_initiate, self, check);
579   return 0;
580 }
581 static noit_module_t *
582 noit_lua_loader_load(noit_module_loader_t *loader,
583                      char *module_name,
584                      noit_conf_section_t section) {
585   noit_module_t *m;
586   lua_State *L;
587   lua_module_closure_t *lmc;
588   char *script;
589   char *object;
590   char scriptfile[MAXPATHLEN];
591  
592   noitL(nldeb, "Loading lua module: %s\n", module_name);
593   if(noit_conf_get_string(section, "@object", &object) == 0) {
594     noitL(nlerr, "Lua module %s require object attribute.\n", module_name);
595     return NULL;
596   }
597   if(noit_conf_get_string(section, "@script", &script) == 0) {
598     noitL(nlerr, "Lua module %s require script attribute.\n", module_name);
599     free(object);
600     return NULL;
601   }
602   snprintf(scriptfile, sizeof(scriptfile), "%s/%s",
603            noit_lua_loader_get_directory(loader), script);
604   free(script);
605
606   m = noit_blank_module();
607   m->hdr.magic = NOIT_MODULE_MAGIC;
608   m->hdr.version = NOIT_MODULE_ABI_VERSION;
609   m->hdr.name = strdup(module_name);
610   m->hdr.description = strdup("Lua module");
611   m->hdr.onload = noit_lua_module_onload;
612   lmc = calloc(1, sizeof(*lmc));
613   lmc->object = object;
614   lmc->script = strdup(scriptfile);
615
616   L = lmc->lua_state = lua_open();
617   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
618   luaL_openlibs(L);  /* open libraries */
619   luaopen_noit(L);
620   lua_newtable(L);
621   lua_setglobal(L, "noit_coros");
622   lua_gc(L, LUA_GCRESTART, 0);
623
624   noit_image_set_userdata(&m->hdr, lmc);
625   if(m->hdr.onload(&m->hdr) == -1) {
626     free(m->hdr.name);
627     free(m->hdr.description);
628     free(lmc->object);
629     free(lmc->script);
630     free(lmc);
631     /* FIXME: We leak the opaque_handler in the module here... */
632     free(m);
633     return NULL;
634   }
635
636   m->config = noit_lua_module_config;
637   m->init = noit_lua_module_init;
638   m->initiate_check = noit_lua_module_initiate_check;
639   m->cleanup = noit_lua_module_cleanup;
640
641   noit_register_module(m);
642   return m;
643 }
644
645 static int
646 noit_lua_loader_config(noit_module_loader_t *self, noit_hash_table *o) {
647   char *dir = ".";
648   noit_hash_retrieve(o, "directory", strlen("directory"), (void **)&dir);
649   noit_lua_loader_set_directory(self, dir);
650   return 0;
651 }
652 static int
653 noit_lua_loader_onload(noit_image_t *self) {
654   nlerr = noit_log_stream_find("error/serf");
655   nldeb = noit_log_stream_find("debug/serf");
656   if(!nlerr) nlerr = noit_stderr;
657   if(!nldeb) nldeb = noit_debug;
658   return 0;
659 }
660
661 noit_module_loader_t lua = {
662   {
663     NOIT_LOADER_MAGIC,
664     NOIT_LOADER_ABI_VERSION,
665     "lua",
666     "Lua check loader",
667     noit_lua_loader_onload,
668   },
669   noit_lua_loader_config,
670   NULL,
671   noit_lua_loader_load
672 };
Note: See TracBrowser for help on using the browser.