plugin_tool.cpp

00001 
00002 /***************************************************************************
00003  *  plugin_tool.cpp - Fawkes plugin tool
00004  *
00005  *  Created: Mon Dec 04 14:43:23 2006
00006  *  Copyright  2006  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include <tools/plugin/plugin_tool.h>
00024 
00025 #include <netcomm/fawkes/client.h>
00026 #include <plugin/net/messages.h>
00027 #include <plugin/net/list_message.h>
00028 #include <utils/system/argparser.h>
00029 
00030 #include <cstdio>
00031 #include <cstdlib>
00032 #include <cstring>
00033 
00034 using namespace fawkes;
00035 
00036 /** @class PluginTool tools/plugin/plugin_tool.h
00037  * Program to communicate with plugin manager via Fawkes network.
00038  */
00039 
00040 /** Constructor.
00041  * @param argp argument parser, three arguments are handled:
00042  * - -l plugin_name load plugin named plugin_name
00043  * - -u plugin_name unload plugin named plugin_name
00044  * - -w watch for changes
00045  * @param c FawkesNetworkClient with established connection
00046  */
00047 PluginTool::PluginTool(ArgumentParser *argp, FawkesNetworkClient *c)
00048 {
00049   this->c     = c;
00050   plugin_name = NULL;
00051   quit        = false;
00052   
00053   if ( argp->has_arg("l") ) {
00054     opmode = M_LOAD;
00055     plugin_name = argp->arg("l");
00056   } else if ( argp->has_arg("u") ) {
00057     opmode = M_UNLOAD;
00058     plugin_name = argp->arg("u");
00059   } else if ( argp->has_arg("R") ) {
00060     opmode = M_RELOAD;
00061     plugin_name = argp->arg("R");
00062   } else if ( argp->has_arg("w") ) {
00063     opmode = M_WATCH;
00064   } else if ( argp->has_arg("a") ) {
00065     opmode = M_LIST_AVAIL;
00066   } else {
00067     opmode = M_LIST_LOADED;
00068   }
00069 
00070   __program_name = argp->program_name();
00071 
00072   list_found = false;
00073 }
00074 
00075 
00076 /** Constructor.
00077  * This constructor just set the Fawkes network client. A run() call will
00078  * fail if not one of set_load_plugin(), set_unload_plugin(), set_watch_mode()
00079  * or set_list_mode() has been called before.
00080  * @param c Fawkes network client with established connection
00081  */
00082 PluginTool::PluginTool(FawkesNetworkClient *c)
00083 {
00084   this->c     = c;
00085   plugin_name = NULL;
00086   quit        = false;
00087   opmode      = M_UNKNOWN;
00088   list_found  = false;
00089 }
00090 
00091 /** Destructor */
00092 PluginTool::~PluginTool()
00093 {
00094 }
00095 
00096 
00097 /** Print usage.
00098  * @param program_name program name
00099  */
00100 void
00101 PluginTool::print_usage(const char *program_name)
00102 {
00103     printf("Usage: %s [-l plugin|-u plugin|-R plugin|-w|-a|-L] [-r host[:port]]\n"
00104            "  -l plugin      Load plugin with given name\n"
00105            "  -u plugin      Unload plugin with given name\n"
00106            "  -R plugin      Reload plugin with given name\n"
00107            "  -w             Watch all load/unload operations\n"
00108            "  -a             List available plugins\n"
00109            "  -L             List loaded plugins (default)\n\n"
00110            "  -r host[:port] Remote host (and optionally port) to connect to\n\n"
00111             "  If called without any option list currently loaded plugins\n\n",
00112            program_name);
00113 }
00114 
00115 /** Load plugin on next run.
00116  * The next time run is called a LOAD_PLUGIN message is sent for the
00117  * given plugin name.
00118  * @param plugin_name name of the plugin to load
00119  */
00120 void
00121 PluginTool::set_load_plugin(const char *plugin_name)
00122 {
00123   this->plugin_name = plugin_name;
00124   opmode = M_LOAD;
00125 }
00126 
00127 
00128 /** Unload plugin on next run.
00129  * The next time run is called a UNLOAD_PLUGIN message is sent for the
00130  * given plugin name.
00131  * @param plugin_name name of the plugin to unload
00132  */
00133 void
00134 PluginTool::set_unload_plugin(const char *plugin_name)
00135 {
00136   this->plugin_name = plugin_name;
00137   opmode = M_UNLOAD;
00138 }
00139 
00140 
00141 /** Set watch mode.
00142  * On next run() call the client will watch for new events.
00143  */
00144 void
00145 PluginTool::set_watch_mode()
00146 {
00147   opmode = M_WATCH;
00148 }
00149 
00150 
00151 /** Set list mode.
00152  * On next run() call the client will list all loaded plugins once.
00153  */
00154 void
00155 PluginTool::set_list_mode()
00156 {
00157   opmode = M_LIST_LOADED;
00158 }
00159 
00160 
00161 /** Handle signals.
00162  * @param signum signal number of received signal
00163  */
00164 void
00165 PluginTool::handle_signal(int signum)
00166 { 
00167   c->wake(FAWKES_CID_PLUGINMANAGER);
00168   quit = true;
00169 }
00170 
00171 
00172 /** Execute load operation. */
00173 void
00174 PluginTool::load()
00175 {
00176   printf("Requesting loading of plugin %s\n", plugin_name);
00177   plugin_load_msg_t *l = (plugin_load_msg_t *)calloc(1, sizeof(plugin_load_msg_t));
00178   strncpy(l->name, plugin_name, PLUGIN_MSG_NAME_LENGTH);
00179 
00180   FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER,
00181                                                        MSG_PLUGIN_LOAD,
00182                                                        l, sizeof(plugin_load_msg_t));
00183   c->enqueue(msg);
00184 
00185   while ( ! quit ) {
00186     c->wait(FAWKES_CID_PLUGINMANAGER);
00187   }
00188 }
00189 
00190 
00191 /** Execute unload operation. */
00192 void
00193 PluginTool::unload()
00194 {
00195   printf("Requesting unloading of plugin %s\n", plugin_name);
00196   plugin_unload_msg_t *m = (plugin_unload_msg_t *)calloc(1, sizeof(plugin_unload_msg_t));
00197   strncpy(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH);
00198 
00199   FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER,
00200                                                        MSG_PLUGIN_UNLOAD,
00201                                                        m, sizeof(plugin_unload_msg_t));
00202   c->enqueue(msg);
00203 
00204   while ( ! quit ) {
00205     c->wait(FAWKES_CID_PLUGINMANAGER);
00206   }
00207 }
00208 
00209 
00210 /** Execute list available operation. */
00211 void
00212 PluginTool::list_avail()
00213 {
00214   printf("Request the list of all available plugins\n");
00215   FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER,
00216                                                        MSG_PLUGIN_LIST_AVAIL);
00217   c->enqueue(msg);
00218 
00219   while ( ! quit ) {
00220     c->wait(FAWKES_CID_PLUGINMANAGER);
00221   }
00222 }
00223 
00224 
00225 /** Execute list operation. */
00226 void
00227 PluginTool::list_loaded()
00228 {
00229   // we got a list of loaded messages during startup, show them
00230   printf("Request the list of all loaded plugins\n");
00231   FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER,
00232                                                        MSG_PLUGIN_LIST_LOADED);
00233   c->enqueue(msg);
00234 
00235   while ( ! quit ) {
00236     c->wait(FAWKES_CID_PLUGINMANAGER);
00237   }
00238 }
00239 
00240 
00241 /** Watch for plugin manager events. */
00242 void
00243 PluginTool::watch()
00244 {
00245   FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER,
00246                                                        MSG_PLUGIN_SUBSCRIBE_WATCH);
00247   c->enqueue(msg);
00248   printf("Watching for plugin events\n");
00249   printf("%-10s   %-40s\n", "Event", "Plugin Name/ID");
00250   while ( ! quit ) {
00251     c->wait(FAWKES_CID_PLUGINMANAGER);
00252   }
00253 
00254   // unsubscribe
00255   msg = new FawkesNetworkMessage(FAWKES_CID_PLUGINMANAGER, MSG_PLUGIN_UNSUBSCRIBE_WATCH);
00256   c->enqueue(msg);
00257 }
00258 
00259 
00260 /** Handler has been deregistered.
00261  */
00262 void
00263 PluginTool::deregistered(unsigned int id) throw()
00264 {
00265   quit = true;
00266 }
00267 
00268 
00269 /** Inbound message received.
00270  * @param msg message.
00271  */
00272 void
00273 PluginTool::inbound_received(FawkesNetworkMessage *msg,
00274                              unsigned int id) throw()
00275 {
00276   if (msg->cid() != FAWKES_CID_PLUGINMANAGER)  return;
00277 
00278   if ( msg->msgid() == MSG_PLUGIN_LOADED ) {
00279     if ( msg->payload_size() != sizeof(plugin_loaded_msg_t) ) {
00280       printf("Invalid message size (load succeeded)\n");
00281     } else {
00282       plugin_loaded_msg_t *m = (plugin_loaded_msg_t *)msg->payload();
00283       if ( opmode == M_WATCH ) {
00284         printf("%-10s   %s\n", "loaded", m->name);
00285       } else {
00286         if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) {
00287           printf("Loading of %s succeeded\n", plugin_name);
00288           quit = true;
00289         }
00290       }
00291     }
00292   } else if ( msg->msgid() == MSG_PLUGIN_LOAD_FAILED) {
00293     if ( msg->payload_size() != sizeof(plugin_load_failed_msg_t) ) {
00294       printf("Invalid message size (load failed)\n");
00295     } else {
00296       plugin_load_failed_msg_t *m = (plugin_load_failed_msg_t *)msg->payload();
00297       if ( opmode == M_WATCH ) {
00298         printf("%-10s   %s\n", "loadfail", m->name);
00299       } else {
00300         if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) {
00301           printf("Loading of %s failed, see log for reason\n", plugin_name);
00302           quit = true;
00303         }
00304       }
00305     }
00306   } else if ( msg->msgid() == MSG_PLUGIN_UNLOADED ) {
00307     if ( msg->payload_size() != sizeof(plugin_unloaded_msg_t) ) {
00308       printf("Invalid message size (unload succeeded)\n");
00309     } else {
00310       plugin_unloaded_msg_t *m = (plugin_unloaded_msg_t *)msg->payload();
00311       if ( opmode == M_WATCH ) {
00312         printf("%-10s   %s\n", "unloaded", m->name);
00313       } else {
00314         if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) {
00315           printf("Unloading of %s succeeded\n", plugin_name);
00316           quit = true;
00317         }
00318       }
00319     }
00320   } else if ( msg->msgid() == MSG_PLUGIN_UNLOAD_FAILED) {
00321     if ( msg->payload_size() != sizeof(plugin_unload_failed_msg_t) ) {
00322       printf("Invalid message size (unload failed)\n");
00323     } else {
00324       plugin_unload_failed_msg_t *m = (plugin_unload_failed_msg_t *)msg->payload();
00325       if ( opmode == M_WATCH ) {
00326         printf("%-10s   %s\n", "unloadfail", m->name);
00327       } else {
00328         if ( strncmp(m->name, plugin_name, PLUGIN_MSG_NAME_LENGTH) == 0 ) {
00329           printf("Unloading of %s failed, see log for reason\n", plugin_name);
00330           quit = true;
00331         }
00332       }
00333     }
00334   } else if (msg->msgid() == MSG_PLUGIN_AVAIL_LIST ) {
00335     PluginListMessage *plm = msg->msgc<PluginListMessage>();
00336     if ( plm->has_next() ) {
00337       printf("Available plugins:\n");
00338       while ( plm->has_next() ) {
00339         char *plugin_name = plm->next();
00340         char *plugin_desc = NULL;
00341         if ( plm->has_next() ) {
00342           plugin_desc = plm->next();
00343         } else {
00344           throw Exception("Invalid plugin list received");
00345         }
00346         printf(" %-16s (%s)\n", plugin_name, plugin_desc);
00347         free(plugin_name);
00348         free(plugin_desc);
00349       }
00350     } else {
00351       printf("No plugins available\n");
00352     }
00353     quit = true;
00354     delete plm;
00355   } else if (msg->msgid() == MSG_PLUGIN_LOADED_LIST ) {
00356     PluginListMessage *plm = msg->msgc<PluginListMessage>();
00357     if ( plm->has_next() ) {
00358       printf("Loaded plugins:\n");
00359       while ( plm->has_next() ) {
00360         char *p = plm->next();
00361         printf("  %s\n", p);
00362         free(p);
00363       }
00364     } else {
00365       printf("No plugins loaded\n");
00366     }
00367     quit = true;
00368     delete plm;
00369   } else if ( msg->msgid() == MSG_PLUGIN_AVAIL_LIST_FAILED) {
00370     printf("Obtaining list of available plugins failed\n");
00371   } else if ( msg->msgid() == MSG_PLUGIN_LOADED_LIST_FAILED) {
00372     printf("Obtaining list of loaded plugins failed\n");
00373   }
00374 }
00375 
00376 
00377 void
00378 PluginTool::connection_established(unsigned int id) throw()
00379 {
00380   // ignored, client has to be connected already
00381 }
00382 
00383 
00384 void
00385 PluginTool::connection_died(unsigned int id) throw()
00386 {
00387   printf("Connection died, exiting\n");
00388   quit = true;
00389 }
00390 
00391 /** Run opmode as requested determined by the arguments. */
00392 void
00393 PluginTool:: run()
00394 {
00395   c->register_handler(this, FAWKES_CID_PLUGINMANAGER);
00396 
00397   switch (opmode) {
00398   case M_LOAD:
00399     load();
00400     break;
00401 
00402   case M_UNLOAD:
00403     unload();
00404     break;
00405 
00406   case M_RELOAD:
00407     unload();
00408     quit = false;
00409     load();
00410     break;
00411 
00412   case M_LIST_AVAIL:
00413     list_avail();
00414     break;
00415 
00416   case M_LIST_LOADED:
00417     list_loaded();
00418     break;
00419 
00420   case M_WATCH:
00421     watch();
00422     break;
00423 
00424   default:
00425     print_usage(__program_name);
00426   }
00427 
00428   c->deregister_handler(FAWKES_CID_PLUGINMANAGER);
00429 }

Generated on Tue Feb 22 13:32:32 2011 for Fawkes API by  doxygen 1.4.7