Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

event_init.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2005 by Kevin L. Mitchell <klmitch@mit.edu>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 **
00018 ** @(#)$Id: event_init.c,v 1.28 2005/12/18 00:15:11 klmitch Exp $
00019 */
00027 #include "engines_int.h"
00028 
00029 #include <ltdl.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 
00033 RCSTAG("@(#)$Id: event_init.c,v 1.28 2005/12/18 00:15:11 klmitch Exp $");
00034 
00040 #define FNAME_BUF       1024
00041 
00048 #define MODULE_INIT     "engine_mod_init"
00049 
00056 #define MODULE_ENGINE   "engine_module"
00057 
00064 #define VAR_MODULES     PACKAGE_TARNAME ".modules"
00065 
00072 #define VAR_LIBPATH     PACKAGE_TARNAME ".libpath"
00073 
00080 #define VAR_MODLIST     PACKAGE_TARNAME ".modlist"
00081 
00094 #define confdir(fname)  SYSCONFDIR "/" PACKAGE_TARNAME "/" fname ".tc"
00095 
00107 #define homedir(fname)  "~/." fname ".tc"
00108 
00115 static _ev_attr_t const _ev__defattr = {
00116   EV_ATTR_MAGIC, /* magic number */
00117 
00118   /* default path */
00119   (confdir(PACKAGE_TARNAME) ":" homedir(PACKAGE_TARNAME) ":"
00120    confdir("%p") ":" homedir("%p")),
00121 
00122   /* default library search path */
00123   PKGLIBDIR,
00124 
00125   /* default library module list */
00126   "select", /* XXX need to figure this one out...configure test? */
00127 
00128   0, 0, 0 /* initialize varlist, ovars, and application engine lists... */
00129 };
00130 const _ev_attr_t const *_ev_defattr = &_ev__defattr;
00131 
00151 static int
00152 new_modvar(treeconf_ctx_t *ctx, treeconf_node_t *parent, treeconf_str_t *name,
00153            int elements)
00154 {
00155   /* exactly two remaining elements... */
00156   return !(tn_type(parent) & TC_NODETYPE_IMPLICIT) && elements == 2;
00157 }
00158 
00188 static ev_err_t
00189 engine_load(ev_ctx_t *ctx, treeconf_str_t *path, int path_cnt,
00190             treeconf_str_t *module, ev_flags_t *flag_p)
00191 {
00192   ev_err_t err = 0;
00193   ev_engine_t *eng;
00194   ev_flags_t init_flags = 0;
00195   const char *mname, *fls = 0;
00196   int mname_len, fl_len = 0, cmp;
00197 
00198   ev_trace();
00199 
00200   /* First, let's process the name */
00201   mname = ts_string(module, 0);
00202   for (mname_len = ts_length(module, 0); mname_len; mname_len--)
00203     if (mname[mname_len - 1] == ':') { /* there are flags */
00204       fls = mname + mname_len; /* remember them and bail out */
00205       fl_len = ts_length(module, 0) - mname_len;
00206       break;
00207     }
00208 
00209   if (mname_len) /* If we found a set of flags... */
00210     mname_len--; /* update the module name length */
00211   else /* otherwise, reset it */
00212     mname_len = ts_length(module, 0);
00213 
00214   /* OK, we have the module name and its flags; now, process the flags */
00215   if (fls)
00216     while (fl_len--)
00217       switch (*fls++) {
00218       case 's': /* Use socket component */
00219         init_flags |= EV_ENGINE_SOCKET;
00220         break;
00221       case 'i': /* Use signal component */
00222         init_flags |= EV_ENGINE_SIGNAL;
00223         break;
00224       case 't': /* Use timer component */
00225         init_flags |= EV_ENGINE_TIMER;
00226         break;
00227       default:
00228         break; /* Just ignore unknown flags */
00229       }
00230   else /* Use all three engine components */
00231     init_flags = EV_ENGINE_COMPMASK;
00232 
00233   init_flags &= ~*flag_p; /* mask out components we already have */
00234 
00235   if (!init_flags) /* if there's no components to try, bail out */
00236     ev_return(0);
00237 
00238   /* Now try to find the engine in the list we've developed so far */
00239   for (eng = ctx->ec_engine; eng; eng = eng->eng_list.el_next)
00240     if (!(cmp = strncmp(eng->eng_name, mname, mname_len)) &&
00241         strlen(eng->eng_name) == mname_len)
00242       break; /* we've found it! */
00243     else if (cmp >= 0) { /* have we gone too far? */
00244       eng = 0; /* got to zero the engine so we go searching for it... */
00245       break;
00246     }
00247 
00248   if (eng && (eng->eng_runfl & EV_ENGINE_RUNNING)) /* engine running? */
00249     ev_return(0); /* just skip it... */
00250   else if (!eng) { /* engine's not already registered... */
00251     ev_modinit_t modinit;
00252     lt_dlhandle handle = 0;
00253     char fname[FNAME_BUF];
00254     int i;
00255 
00256     for (i = 0; i < path_cnt; i++) { /* go through all the path elements */
00257       if (ts_length(path, i) + mname_len + 2 > FNAME_BUF)
00258         continue; /* would be too long; skip it... */
00259 
00260       sprintf(fname, "%.*s/%.*s", ts_length(path, i), ts_string(path, i),
00261               mname_len, mname); /* build the file name... */
00262 
00263       _ev_debug(EVAS_LOG, __FILE__, __LINE__, _gca_func,
00264                 "Attempting to load engine module %s...", fname);
00265 
00266       /* try to load the module */
00267       if (!(handle = lt_dlopenext(fname))) {
00268         _ev_debug(EVAS_LOG, __FILE__, __LINE__, _gca_func,
00269                   "Can't load %s: %s", fname, lt_dlerror());
00270         continue; /* not there, try somewhere else... */
00271       }
00272 
00273       /* All right, we now have a loadable module.  Does it have a
00274        * module initialization function?
00275        */
00276       if ((modinit = (ev_modinit_t)lt_dlsym(handle, MODULE_INIT))) {
00277         if ((eng = (modinit)(ctx)) && /* initialize module... */
00278             (eng->eng_runfl & EV_ENGINE_REGISTERED))
00279           break; /* excellent, we have an engine! */
00280 
00281         /* No module initialization function, try for the engine variable */
00282       } else if ((eng = (ev_engine_t *)lt_dlsym(handle, MODULE_ENGINE)) &&
00283                  !engine_register(ctx, eng)) /* register the engine... */
00284         break; /* found an engine descriptor! */
00285 
00286       /* Couldn't find an engine descriptor; close this one and try again */
00287       lt_dlclose(handle);
00288     }
00289 
00290     if (!eng) /* Guess we couldn't find a module for that engine */
00291       ev_return(0); /* Silent failure, try the next engine module */
00292 
00293     ev_assert(handle); /* handle must be set by now... */
00294 
00295     eng->eng_handle = (void *)handle; /* remember the handle */
00296   }
00297 
00298   ev_assert(eng); /* we should now have an engine... */
00299   ev_assert(eng->eng_runfl & EV_ENGINE_REGISTERED); /* must be registered */
00300 
00301   /* Modify init flags with components module handles */
00302   init_flags &= eng->eng_flags;
00303 
00304   /* Now, try to initialize the engine... */
00305   if (!init_flags || (err = eng_init(ctx, eng, &init_flags))) {
00306     /* Failed to initialize engine... */
00307 
00308     if (eng->eng_handle) { /* Was it a loaded module? */
00309       if (eng->eng_list.el_next) /* clip it out of the engine list... */
00310         eng->eng_list.el_next->eng_list.el_prev = eng->eng_list.el_prev;
00311       if (eng->eng_list.el_prev)
00312         eng->eng_list.el_prev->eng_list.el_next = eng->eng_list.el_next;
00313       else
00314         ctx->ec_engine = eng->eng_list.el_next;
00315 
00316       lt_dlclose((lt_dlhandle)eng->eng_handle); /* and unload the module */
00317     }
00318 
00319     if (init_flags) /* eng_init() was called, but failed... */
00320       _ev_debug(EVAS_LOG, __FILE__, __LINE__, _gca_func,
00321                 "eng_init() failure initializing engine %s: %u",
00322                 eng->eng_name, err);
00323 
00324     ev_return(0); /* try next engine... */
00325   }
00326 
00327   *flag_p |= init_flags; /* mark which components have been initialized */
00328 
00329   ev_return(0); /* all done! */
00330 }
00331 
00332 ev_err_t
00333 event_init(ev_ctx_t *ctx, const ev_attr_t *attr, ev_flags_t flags,
00334            const char *prog, const char *envpath)
00335 {
00336   ev_err_t err = 0;
00337   treeconf_subst_t substs[] = {
00338     TC_SUBST_INIT('n', 0, TC_SUBST_INSECURE), /* username */
00339     TC_SUBST_INIT('p', 0, 0) /* program name */
00340   };
00341   treeconf_str_t *path = 0, *modules = 0;
00342   int path_cnt, mod_cnt, i;
00343   const char *val;
00344   ev_varlist_t *vlist;
00345   ev_overvars_t *ovlist;
00346   ev_engine_t *eng, *eng_next;
00347   ev_flags_t comps = 0;
00348 
00349   ev_init(); /* make sure library is initialized... */
00350 
00351   if (!ctx || (attr && !ea_verify(attr)))
00352     ev_return(EINVAL); /* sanity check arguments */
00353 
00354   if (!attr) /* set default attributes... */
00355     attr = (const ev_attr_t *)&_ev_defattr;
00356 
00357   if (prog) /* prepare substitutions... */
00358     tu_value(&substs[1]) = prog; /* substitute program name... */
00359   else
00360     tu_flags(&substs[1]) |= TC_SUBST_IGNORE; /* must ignore substitution */
00361 
00362   tc_init(ec_conf(ctx)); /* initialize the treeconf... */
00363 
00364   /* set context flags... */
00365   ctx->ec_flags = (flags & EV_INIT_SECURE) ? EV_CTX_SECURE : 0;
00366   ctx->ec_prog = prog; /* remember program name... */
00367 
00368   ctx->ec_maxgen = 0; /* clear list of generators */
00369   ctx->ec_gens = 0;
00370 
00371   ctx->ec_timtree.tt_root = 0; /* clear the timer tree */
00372   ctx->ec_timtree.tt_insert = 0;
00373 
00374   ctx->ec_engine = 0; /* clear engine lists */
00375 
00376   ctx->ec_socket.el_first = ctx->ec_socket.el_last = 0;
00377   ctx->ec_signal.el_first = ctx->ec_signal.el_last = 0;
00378   ctx->ec_timer.el_first = ctx->ec_timer.el_last = 0;
00379 
00380   ctx->ec_evcnt = 0; /* clear event freelist */
00381   ctx->ec_evs = 0;
00382 
00383   /* Set magic number now so we can use event_destroy() on error... */
00384   ctx->ec_magic = EV_CTX_MAGIC;
00385 
00386   /* Register library configuration variables */
00387   if ((err = tc_register(ec_conf(ctx), VAR_MODULES, 0, 0, new_modvar, 0, 0)) ||
00388       (err = tc_register(ec_conf(ctx), VAR_LIBPATH, ea_libpath(attr),
00389                          0, 0, 0, 0)) ||
00390       (err = tc_register(ec_conf(ctx), VAR_MODLIST, ea_modlist(attr),
00391                          0, 0, 0, 0)))
00392     goto error;
00393 
00394   /* Walk through all the application-registered treeconf variables and
00395    * register them.
00396    */
00397   for (vlist = ea_varlist(attr); vlist; vlist = vlist->vl_next)
00398     if ((err = tc_register(ec_conf(ctx), vlist->vl_name, vlist->vl_default, 0,
00399                            vlist->vl_nodown, vlist->vl_change,
00400                            vlist->vl_assoc)))
00401       goto error;
00402 
00403   /* search for and load configuration files */
00404   if ((err = tc_path((flags & EV_INIT_SECURE) ? 0 : envpath, ea_confpath(attr),
00405                      substs, sizeof(substs) / sizeof(treeconf_subst_t),
00406                      ((flags & EV_INIT_SECURE) ? TC_PATH_SECURE : 0) |
00407                      TC_PATH_ALL, tc_load, ec_conf(ctx))))
00408     goto error;
00409 
00410   /* Now set up all the application-overridden values */
00411   for (ovlist = ea_ovars(attr); ovlist; ovlist = ovlist->ov_next)
00412     if ((err = tc_set(ec_conf(ctx), ovlist->ov_name, ovlist->ov_value, 0)))
00413       goto error;
00414 
00415   /* Register initial generators */
00416   if ((err = event_gen_register(ctx, EGT_SOCKET, EV_SOCK_MAGIC,
00417                                 sizeof(ev_sock_t), 0)) ||
00418       (err = event_gen_register(ctx, EGT_SIGNAL, EV_SIG_MAGIC,
00419                                 sizeof(ev_sig_t), 0)) ||
00420       (err = event_gen_register(ctx, EGT_TIMER, EV_TIM_MAGIC,
00421                                 sizeof(ev_tim_t), 0)))
00422     goto error;
00423 
00424   /* Let's now register application-specified engines... */
00425   for (eng = ea_engines(attr); eng; eng = eng_next) {
00426     eng_next = eng->eng_list.el_next; /* remember what's next in list... */
00427     englink_clr(&eng->eng_list); /* clear link for engine_register() */
00428     if ((err = engine_register(ctx, eng))) /* register the engine */
00429       goto error;
00430   }
00431 
00432   /* Let's split up the path list and the module list */
00433   if ((err = tc_get(ec_conf(ctx), VAR_LIBPATH, &val, 0)) ||
00434       (err = tc_break(&path, &path_cnt, val, ":")) ||
00435       (err = tc_get(ec_conf(ctx), VAR_MODLIST, &val, 0)) ||
00436       (err = tc_break(&modules, &mod_cnt, val, " \t")))
00437     goto error;
00438 
00439   /* OK, try to initialize libltdl... */
00440   if (lt_dlinit()) {
00441     err = EV_ERR_LIBLTDL;
00442     goto error;
00443   } else /* mark that we've initialized libltdl */
00444     ctx->ec_flags |= EV_CTX_LTDLINIT;
00445 
00446   /* Now walk through the module list and try to initialize... */
00447   for (i = 0; i < mod_cnt && (comps ^ EV_ENGINE_COMPMASK); i++)
00448     if ((err = engine_load(ctx, path, path_cnt, modules + i, &comps)))
00449       goto error;
00450 
00451   /* Did we get all the components? */
00452   if ((comps ^ EV_ENGINE_COMPMASK) || !ctx->ec_socket.el_first ||
00453       !ctx->ec_signal.el_first || !ctx->ec_timer.el_first)
00454     err = EV_ERR_NOENGINE;
00455 
00456   /* We are now all done.  All that remains is cleaning up temporary data
00457    * and returning!
00458    */
00459 
00460  error:
00461   if (modules) /* an error occurred, let's clean up after ourselves */
00462     free(modules);
00463   if (path)
00464     free(path);
00465   if (err)
00466     event_destroy(ctx);
00467 
00468   ev_return(err);
00469 }

Generated on Wed Dec 28 23:36:56 2005 for event by  doxygen 1.4.4