root/src/modules/lua.c

Revision 327712134f74d1a3209f8beee3b0f593e721c8f6, 19.4 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

cleanup solaris bits, refs #32

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