netconf.cpp

00001 
00002 /***************************************************************************
00003  *  netconf.cpp - Fawkes remote configuration access via Fawkes net
00004  *
00005  *  Created: Sun Jan 07 15:04:41 2007
00006  *  Copyright  2006-2009  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. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <config/netconf.h>
00025 #include <config/net_messages.h>
00026 #include <config/sqlite.h>
00027 #include <config/net_list_content.h>
00028 
00029 #include <core/threading/mutex.h>
00030 #include <core/threading/interruptible_barrier.h>
00031 #include <netcomm/fawkes/client.h>
00032 #include <netcomm/fawkes/message.h>
00033 #include <netcomm/utils/exceptions.h>
00034 
00035 #include <utils/logging/liblogger.h>
00036 
00037 #ifndef _GNU_SOURCE
00038 #define _GNU_SOURCE
00039 #endif
00040 #include <cstring>
00041 #include <cstdlib>
00042 
00043 namespace fawkes {
00044 
00045 /** @class CannotEnableMirroringException <config/netconf.h>
00046  * Thrown if enabling mirror mode failed.
00047  */
00048 
00049 /** Constructor.
00050  * @param msg message describing the problem
00051  */
00052 CannotEnableMirroringException::CannotEnableMirroringException(const char *msg)
00053   : Exception("Could not enable mirroring: %s", msg)
00054 {
00055 }
00056 
00057 
00058 /** @class NetworkConfiguration <config/netconf.h>
00059  * Remote configuration via Fawkes net.
00060  * This implementation of the Configuration interface allows for remote access
00061  * to a Fawkes process implemented using the ConfigurationManager.
00062  *
00063  * The network configuration can operator in two modes. In mirror and in non-mirror
00064  * mode. The non-mirror mode is recommended if only a few operations have to be
00065  * carried out like getting only a very few values or setting a single value.
00066  * The mirror mode is for longer usage periods and on-the-fly updates. In mirror
00067  * mode the complete configuration is copied once from the Fawkes process and then
00068  * all updates are incorporated into the local database. You can register change
00069  * handlers to be notified as soon as someone modifies a value.
00070  *
00071  */
00072 
00073 /** Constructor.
00074  * @param c Fawkes network client (thread).
00075  * @param mirror_timeout_sec timeout in seconds for initiating mirroring
00076  */
00077 NetworkConfiguration::NetworkConfiguration(FawkesNetworkClient *c,
00078                                            unsigned int mirror_timeout_sec)
00079 {
00080   __mirror_timeout_sec = mirror_timeout_sec;
00081   __connected = c->connected();
00082   this->c = c;
00083   try {
00084     c->register_handler(this, FAWKES_CID_CONFIGMANAGER);
00085   } catch (Exception &e) {
00086     e.append("Failed to register for config manager component on network client");
00087     throw;
00088   }
00089   mutex = new Mutex();
00090   msg = NULL;
00091   __mirror_mode = false;
00092   __mirror_mode_before_connection_dead = false;
00093   __mirror_init_barrier = NULL;
00094 }
00095 
00096 
00097 /** Destructor. */
00098 NetworkConfiguration::~NetworkConfiguration()
00099 {
00100   set_mirror_mode(false);
00101   c->deregister_handler(FAWKES_CID_CONFIGMANAGER);
00102   if (msg != NULL) {
00103     msg->unref();
00104   }
00105   delete __mirror_init_barrier;
00106   delete mutex;
00107 }
00108 
00109 
00110 /** Load configuration.
00111  * This is a noop for the NetworkConfiguration.
00112  * @param name name of the host-based database. This should be a name of the form
00113  * hostname.db, where hostname is the unqualified part of the hostname.
00114  * @param defaults_name name of the default database. Should be defaults.db
00115  * @param tag optional tag to restore
00116  */
00117 void
00118 NetworkConfiguration::load(const char *name,
00119                            const char *defaults_name,
00120                            const char *tag)
00121 {
00122 }
00123 
00124 
00125 /** Copy all values from the given configuration.
00126  * All values from the given configuration are copied. Old values are not erased
00127  * so that the copied values will overwrite existing values, new values are
00128  * created, but values existent in current config but not in the copie config
00129  * will remain unchanged.
00130  * @param copyconf configuration to copy
00131  */
00132 void
00133 NetworkConfiguration::copy(Configuration *copyconf)
00134 {
00135   copyconf->lock();
00136   Configuration::ValueIterator *i = copyconf->iterator();
00137   while ( i->next() ) {
00138     if ( i->is_float() ) {
00139       set_float(i->path(), i->get_float());
00140     } else if ( i->is_int() ) {
00141       set_int(i->path(), i->get_int());
00142     } else if ( i->is_uint() ) {
00143       set_uint(i->path(), i->get_uint());
00144     } else if ( i->is_bool() ) {
00145       set_bool(i->path(), i->get_bool());
00146     } else if ( i->is_string() ) {
00147       std::string s = i->get_string();
00148       set_string(i->path(), s);
00149     }
00150   }
00151   delete i;
00152   copyconf->unlock();
00153 }
00154 
00155 
00156 void
00157 NetworkConfiguration::tag(const char *tag)
00158 {
00159   mutex->lock();
00160 
00161   mutex->unlock();
00162 }
00163 
00164 
00165 std::list<std::string>
00166 NetworkConfiguration::tags()
00167 {
00168   mutex->lock();
00169   std::list<std::string> l;
00170   mutex->unlock();
00171   return l;
00172 }
00173 
00174 
00175 bool
00176 NetworkConfiguration::exists(const char *path)
00177 {
00178   ValueIterator *i = get_value(path);
00179   bool rv = i->valid();
00180   delete i;
00181   return rv;
00182 }
00183 
00184 
00185 bool
00186 NetworkConfiguration::is_default(const char *path)
00187 {
00188   ValueIterator *i = get_value(path);
00189   bool rv = i->is_default();
00190   delete i;
00191   return rv;
00192 }
00193 
00194 
00195 /** Get type of field.
00196  * @param path path
00197  * @return string of type
00198  */
00199 std::string
00200 NetworkConfiguration::get_type(const char *path)
00201 {
00202   std::string s = "";
00203   mutex->lock();
00204   if ( __mirror_mode ) {
00205     s = mirror_config->get_type(path);
00206     mutex->unlock();
00207   } else {
00208     mutex->unlock();
00209     Configuration::ValueIterator *i = get_value(path);
00210     s = i->type();
00211     delete i;
00212   }
00213   return s;
00214 }
00215 
00216 
00217 bool
00218 NetworkConfiguration::is_float(const char *path)
00219 {
00220   return (get_type(path) == "float");
00221 }
00222 
00223 
00224 bool
00225 NetworkConfiguration::is_uint(const char *path)
00226 {
00227   return (get_type(path) == "unsigned int");
00228 }
00229 
00230 
00231 bool
00232 NetworkConfiguration::is_int(const char *path)
00233 {
00234   return (get_type(path) == "int");
00235 }
00236 
00237 
00238 bool
00239 NetworkConfiguration::is_bool(const char *path)
00240 {
00241   return (get_type(path) == "bool");
00242 }
00243 
00244 
00245 bool
00246 NetworkConfiguration::is_string(const char *path)
00247 {
00248   return (get_type(path) == "string");
00249 }
00250 
00251 
00252 void
00253 NetworkConfiguration::send_get(const char *path, unsigned int msgid)
00254 {
00255   if ( ! __connected ) {
00256     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00257                                   "client connection is not alive");
00258   }
00259   config_getval_msg_t *g = (config_getval_msg_t *)calloc(1, sizeof(config_getval_msg_t));
00260   strncpy(g->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00261   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00262                                                         msgid,
00263                                                         g, sizeof(config_getval_msg_t));
00264   c->enqueue_and_wait(omsg);
00265 
00266   if ( msg == NULL ) {
00267     mutex->unlock();
00268     throw NullPointerException("NetworkConfiguration::send_get: msg == NULL");
00269   }
00270 
00271   if ( msg->msgid() != msgid ) {
00272     msg->unref();
00273     msg = NULL;
00274     mutex->unlock();
00275     throw TypeMismatchException("NetworkConfiguration::send_get: msg type not float");
00276   }
00277 }
00278 
00279 
00280 float
00281 NetworkConfiguration::get_float(const char *path)
00282 {
00283   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00284     throw OutOfBoundsException("NetworkConfiguration::get_float: "
00285                                "Maximum length for path exceeded");
00286   }
00287   if ( ! __connected ) {
00288     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00289                                   "client connection is not alive");
00290   }
00291 
00292   float f;
00293   mutex->lock();
00294 
00295   if ( __mirror_mode ) {
00296     try {
00297       f = mirror_config->get_float(path);
00298     } catch (Exception &e) {
00299       e.append("NetworkConfiguration[mirroring]::get_float: exception in mirror database");
00300       mutex->unlock();
00301       throw;
00302     }
00303   } else {
00304     try {
00305       send_get(path, MSG_CONFIG_GET_FLOAT);
00306 
00307       config_float_value_msg_t *fm = msg->msg<config_float_value_msg_t>();
00308       f = fm->f;
00309 
00310       msg->unref();
00311       msg = NULL;
00312 
00313     } catch (Exception &e) {
00314       e.append("NetworkConfiguration::get_float: Fetching float failed");
00315       if ( msg != NULL ) {
00316         msg->unref();
00317         msg = NULL;
00318       }
00319       mutex->unlock();
00320       throw;
00321     }
00322   }
00323 
00324   mutex->unlock();
00325 
00326   return f;
00327 }
00328 
00329 
00330 unsigned int
00331 NetworkConfiguration::get_uint(const char *path)
00332 {
00333   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00334     throw OutOfBoundsException("NetworkConfiguration::get_uint: "
00335                                "Maximum length for path exceeded");
00336   }
00337   if ( ! __connected ) {
00338     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00339                                   "client connection is not alive");
00340   }
00341 
00342   unsigned int u;
00343   mutex->lock();
00344 
00345   if ( __mirror_mode ) {
00346     try {
00347       u = mirror_config->get_uint(path);
00348     } catch (Exception &e) {
00349       e.append("NetworkConfiguration[mirroring]::get_uint: exception in mirror database");
00350       mutex->unlock();
00351       throw;
00352     }
00353   } else {
00354     try {
00355       send_get(path, MSG_CONFIG_GET_UINT);
00356 
00357       config_uint_value_msg_t *um = msg->msg<config_uint_value_msg_t>();
00358       u = um->u;
00359 
00360       msg->unref();
00361       msg = NULL;
00362 
00363     } catch (Exception &e) {
00364       e.append("NetworkConfiguration::get_uint: Fetching unsigned int failed");
00365       if ( msg != NULL ) {
00366         msg->unref();
00367         msg = NULL;
00368       }
00369       mutex->unlock();
00370       throw;
00371     }
00372   }
00373 
00374   mutex->unlock();
00375 
00376   return u;
00377 }
00378 
00379 
00380 int
00381 NetworkConfiguration::get_int(const char *path)
00382 {
00383   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00384     throw OutOfBoundsException("NetworkConfiguration::get_int: "
00385                                "Maximum length for path exceeded");
00386   }
00387   if ( ! __connected ) {
00388     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00389                                   "client connection is not alive");
00390   }
00391 
00392   int i;
00393   mutex->lock();
00394 
00395   if ( __mirror_mode ) {
00396     try {
00397       i = mirror_config->get_int(path);
00398     } catch (Exception &e) {
00399       e.append("NetworkConfiguration[mirroring]::get_int: exception in mirror database");
00400       mutex->unlock();
00401       throw;
00402     }
00403   } else {
00404     try {
00405       send_get(path, MSG_CONFIG_GET_INT);
00406 
00407       config_int_value_msg_t *im = msg->msg<config_int_value_msg_t>();
00408       i = im->i;
00409 
00410       msg->unref();
00411       msg = NULL;
00412 
00413     } catch (Exception &e) {
00414       e.append("NetworkConfiguration::get_int: Fetching int failed");
00415       if ( msg != NULL ) {
00416         msg->unref();
00417         msg = NULL;
00418       }
00419       mutex->unlock();
00420       throw;
00421     }
00422   }
00423 
00424   mutex->unlock();
00425 
00426   return i;
00427 }
00428 
00429 
00430 bool
00431 NetworkConfiguration::get_bool(const char *path)
00432 {
00433   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00434     throw OutOfBoundsException("NetworkConfiguration::get_bool: "
00435                                "Maximum length for path exceeded");
00436   }
00437   if ( ! __connected ) {
00438     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00439                                   "client connection is not alive");
00440   }
00441 
00442   bool b;
00443   mutex->lock();
00444 
00445   if ( __mirror_mode ) {
00446     try {
00447       b = mirror_config->get_bool(path);
00448     } catch (Exception &e) {
00449       e.append("NetworkConfiguration[mirroring]::get_bool: exception in mirror database");
00450       mutex->unlock();
00451       throw;
00452     }
00453   } else {
00454     try {
00455       send_get(path, MSG_CONFIG_GET_BOOL);
00456 
00457       config_bool_value_msg_t *bm = msg->msg<config_bool_value_msg_t>();
00458       b = (bm->b != 0);
00459 
00460       msg->unref();
00461       msg = NULL;
00462 
00463     } catch (Exception &e) {
00464       e.append("NetworkConfiguration::get_bool: Fetching bool failed");
00465       if ( msg != NULL ) {
00466         msg->unref();
00467         msg = NULL;
00468       }
00469       mutex->unlock();
00470       throw;
00471     }
00472   }
00473 
00474   mutex->unlock();
00475 
00476   return b;
00477 }
00478 
00479 
00480 std::string
00481 NetworkConfiguration::get_string(const char *path)
00482 {
00483   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00484     throw OutOfBoundsException("NetworkConfiguration::get_string: "
00485                                "Maximum length for path exceeded");
00486   }
00487   if ( ! __connected ) {
00488     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00489                                   "client connection is not alive");
00490   }
00491 
00492   std::string s;
00493   mutex->lock();
00494 
00495   if ( __mirror_mode ) {
00496     try {
00497       s = mirror_config->get_string(path);
00498     } catch (Exception &e) {
00499       e.append("NetworkConfiguration[mirroring]::get_string: exception in mirror database");
00500       mutex->unlock();
00501       throw;
00502     }
00503   } else {
00504     try {
00505       send_get(path, MSG_CONFIG_GET_STRING);
00506 
00507       config_string_value_msg_t *sm = msg->msgge<config_string_value_msg_t>();
00508       s = sm->s;
00509 
00510       msg->unref();
00511       msg = NULL;
00512 
00513     } catch (Exception &e) {
00514       e.append("NetworkConfiguration::get_string: Fetching int failed");
00515       if ( msg != NULL ) {
00516         msg->unref();
00517         msg = NULL;
00518       }
00519       mutex->unlock();
00520       throw;
00521     }
00522   }
00523 
00524   mutex->unlock();
00525 
00526   return s;
00527 }
00528 
00529 
00530 std::string
00531 NetworkConfiguration::get_comment(const char *path)
00532 {
00533   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00534     throw OutOfBoundsException("NetworkConfiguration::get_comment: "
00535                                "Maximum length for path exceeded");
00536   }
00537   if ( ! __connected ) {
00538     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00539                                   "client connection is not alive");
00540   }
00541 
00542   std::string s;
00543   mutex->lock();
00544 
00545   if ( __mirror_mode ) {
00546     try {
00547       s = mirror_config->get_comment(path);
00548     } catch (Exception &e) {
00549       e.append("NetworkConfiguration[mirroring]::get_comment: exception in mirror database");
00550       mutex->unlock();
00551       throw;
00552     }
00553   } else {
00554     try {
00555       send_get(path, MSG_CONFIG_GET_COMMENT);
00556 
00557       config_comment_msg_t *sm = msg->msgge<config_comment_msg_t>();
00558       s = sm->s;
00559 
00560       msg->unref();
00561       msg = NULL;
00562 
00563     } catch (Exception &e) {
00564       e.append("NetworkConfiguration::get_comment: Fetching int failed");
00565       if ( msg != NULL ) {
00566         msg->unref();
00567         msg = NULL;
00568       }
00569       mutex->unlock();
00570       throw;
00571     }
00572   }
00573 
00574   mutex->unlock();
00575 
00576   return s;
00577 }
00578 
00579 
00580 std::string
00581 NetworkConfiguration::get_default_comment(const char *path)
00582 {
00583   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00584     throw OutOfBoundsException("NetworkConfiguration::get_default_comment: "
00585                                "Maximum length for path exceeded");
00586   }
00587   if ( ! __connected ) {
00588     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00589                                   "client connection is not alive");
00590   }
00591 
00592   std::string s;
00593   mutex->lock();
00594 
00595   if ( __mirror_mode ) {
00596     try {
00597       s = mirror_config->get_default_comment(path);
00598     } catch (Exception &e) {
00599       e.append("NetworkConfiguration[mirroring]::get_default_comment: "
00600                "exception in mirror database");
00601       mutex->unlock();
00602       throw;
00603     }
00604   } else {
00605     try {
00606       send_get(path, MSG_CONFIG_GET_DEFAULT_COMMENT);
00607 
00608       config_comment_msg_t *sm = msg->msgge<config_comment_msg_t>();
00609       s = sm->s;
00610 
00611       msg->unref();
00612       msg = NULL;
00613 
00614     } catch (Exception &e) {
00615       e.append("NetworkConfiguration::get_comment: Fetching int failed");
00616       if ( msg != NULL ) {
00617         msg->unref();
00618         msg = NULL;
00619       }
00620       mutex->unlock();
00621       throw;
00622     }
00623   }
00624 
00625   mutex->unlock();
00626 
00627   return s;
00628 }
00629 
00630 
00631 Configuration::ValueIterator *
00632 NetworkConfiguration::get_value(const char *path)
00633 {
00634   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00635     throw OutOfBoundsException("NetworkConfiguration::get_value: "
00636                                "Maximum length for path exceeded");
00637   }
00638   if ( ! __connected ) {
00639     throw ConnectionDiedException("NetworkConfiguration: Cannot send get, "
00640                                   "client connection is not alive");
00641   }
00642 
00643   Configuration::ValueIterator *i;
00644   mutex->lock();
00645 
00646   if ( __mirror_mode ) {
00647     try {
00648       i = mirror_config->get_value(path);
00649     } catch (Exception &e) {
00650       e.append("NetworkConfiguration[mirroring]::get_float: exception in mirror database");
00651       mutex->unlock();
00652       throw;
00653     }
00654   } else {
00655     config_getval_msg_t *g = (config_getval_msg_t *)calloc(1, sizeof(config_getval_msg_t));
00656     strncpy(g->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00657     FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00658                                                           MSG_CONFIG_GET_VALUE,
00659                                                           g, sizeof(config_getval_msg_t));
00660     c->enqueue_and_wait(omsg);
00661 
00662     if ( msg == NULL ) {
00663       mutex->unlock();
00664       throw NullPointerException("NetworkConfiguration::get_value: msg == NULL");
00665     }
00666 
00667     i = new NetConfValueIterator(msg);
00668 
00669     msg->unref();
00670     msg = NULL;
00671   }
00672 
00673   mutex->unlock();
00674 
00675   return i;
00676 }
00677 
00678 
00679 void
00680 NetworkConfiguration::set_float_internal(unsigned int msg_type,
00681                                          const char *path, float f)
00682 {
00683   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00684     throw OutOfBoundsException("NetworkConfiguration::set_float: "
00685                                "Maximum length for path exceeded");
00686   }
00687   if ( ! __connected ) {
00688     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00689                                   "client connection is not alive");
00690   }
00691 
00692   mutex->lock();
00693   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00694                                                         msg_type,
00695                                                         sizeof(config_float_value_msg_t));
00696   config_float_value_msg_t *fm = omsg->msg<config_float_value_msg_t>();
00697   strncpy(fm->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00698   fm->f = f;
00699   c->enqueue_and_wait(omsg);
00700   if ( ! __mirror_mode && (msg != NULL) ) {
00701     msg->unref();
00702     msg = NULL;
00703   }
00704   mutex->unlock();
00705 }
00706 
00707 
00708 void
00709 NetworkConfiguration::set_float(const char *path, float f)
00710 {
00711   set_float_internal(MSG_CONFIG_SET_FLOAT, path, f);
00712 }
00713 
00714 
00715 void
00716 NetworkConfiguration::set_default_float(const char *path, float f)
00717 {
00718   set_float_internal(MSG_CONFIG_SET_DEFAULT_FLOAT, path, f);
00719 }
00720 
00721 
00722 void
00723 NetworkConfiguration::set_uint_internal(unsigned int msg_type,
00724                                         const char *path, unsigned int uint)
00725 {
00726   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00727     throw OutOfBoundsException("NetworkConfiguration::set_uint: "
00728                                "Maximum length for path exceeded");
00729   }
00730   if ( ! __connected ) {
00731     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00732                                   "client connection is not alive");
00733   }
00734 
00735   mutex->lock();
00736   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00737                                                         msg_type,
00738                                                         sizeof(config_uint_value_msg_t));
00739   config_uint_value_msg_t *m = omsg->msg<config_uint_value_msg_t>();
00740   strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00741   m->u = uint;
00742   c->enqueue_and_wait(omsg);
00743   if ( ! __mirror_mode && (msg != NULL) ) {
00744     msg->unref();
00745     msg = NULL;
00746   }
00747   mutex->unlock();
00748 }
00749 
00750 
00751 void
00752 NetworkConfiguration::set_uint(const char *path, unsigned int uint)
00753 {
00754   set_uint_internal(MSG_CONFIG_SET_UINT, path, uint);
00755 }
00756 
00757 
00758 void
00759 NetworkConfiguration::set_default_uint(const char *path, unsigned int uint)
00760 {
00761   set_uint_internal(MSG_CONFIG_SET_DEFAULT_UINT, path, uint);
00762 }
00763 
00764 
00765 void
00766 NetworkConfiguration::set_int_internal(unsigned int msg_type,
00767                                        const char *path, int i)
00768 {
00769   if ( ! __connected ) {
00770     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00771                                   "client connection is not alive");
00772   }
00773 
00774   mutex->lock();
00775   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00776                                                         msg_type,
00777                                                         sizeof(config_int_value_msg_t));
00778   config_int_value_msg_t *m = omsg->msg<config_int_value_msg_t>();
00779   strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00780   m->i = i;
00781   c->enqueue_and_wait(omsg);
00782   if ( ! __mirror_mode && (msg != NULL) ) {
00783     msg->unref();
00784     msg = NULL;
00785   }
00786   mutex->unlock();
00787 }
00788 
00789 
00790 void
00791 NetworkConfiguration::set_int(const char *path, int i)
00792 {
00793   set_int_internal(MSG_CONFIG_SET_INT, path, i);
00794 }
00795 
00796 
00797 void
00798 NetworkConfiguration::set_default_int(const char *path, int i)
00799 {
00800   set_int_internal(MSG_CONFIG_SET_DEFAULT_INT, path, i);
00801 }
00802 
00803 
00804 void
00805 NetworkConfiguration::set_bool_internal(unsigned int msg_type,
00806                                         const char *path, bool b)
00807 {
00808   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00809     throw OutOfBoundsException("NetworkConfiguration::set_bool: "
00810                                "Maximum length for path exceeded");
00811   }
00812   if ( ! __connected ) {
00813     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00814                                   "client connection is not alive");
00815   }
00816 
00817   mutex->lock();
00818   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00819                                                         msg_type,
00820                                                         sizeof(config_bool_value_msg_t));
00821   config_bool_value_msg_t *m = omsg->msg<config_bool_value_msg_t>();
00822   strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00823   m->b = (b ? 1 : 0);
00824   c->enqueue_and_wait(omsg);
00825   if ( ! __mirror_mode && (msg != NULL) ) {
00826     msg->unref();
00827     msg = NULL;
00828   }
00829   mutex->unlock();
00830 }
00831 
00832 
00833 void
00834 NetworkConfiguration::set_bool(const char *path, bool b)
00835 {
00836   set_bool_internal(MSG_CONFIG_SET_BOOL, path, b);
00837 }
00838 
00839 
00840 void
00841 NetworkConfiguration::set_default_bool(const char *path, bool b)
00842 {
00843   set_bool_internal(MSG_CONFIG_SET_DEFAULT_BOOL, path, b);
00844 }
00845 
00846 
00847 void
00848 NetworkConfiguration::set_string_internal(unsigned int msg_type,
00849                                           const char *path,
00850                                           const char *s)
00851 {
00852   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00853     throw OutOfBoundsException("NetworkConfiguration::set_string: "
00854                                "Maximum length for path exceeded");
00855   }
00856   if ( ! __connected ) {
00857     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00858                                   "client connection is not alive");
00859   }
00860 
00861   mutex->lock();
00862   size_t s_length = strlen(s);
00863   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00864                                                         msg_type,
00865                                                         sizeof(config_string_value_msg_t) + s_length);
00866   config_string_value_msg_t *m = omsg->msgge<config_string_value_msg_t>();
00867   strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00868   strcpy(m->s, s);
00869   c->enqueue_and_wait(omsg);
00870   if ( ! __mirror_mode && (msg != NULL) ) {
00871     msg->unref();
00872     msg = NULL;
00873   }
00874   mutex->unlock();
00875 }
00876 
00877 
00878 void
00879 NetworkConfiguration::set_string(const char *path, const char *s)
00880 {
00881   set_string_internal(MSG_CONFIG_SET_STRING, path, s);
00882 }
00883 
00884 
00885 void
00886 NetworkConfiguration::set_default_string(const char *path, const char *s)
00887 {
00888   set_string_internal(MSG_CONFIG_SET_DEFAULT_STRING, path, s);
00889 }
00890 
00891 
00892 void
00893 NetworkConfiguration::set_string(const char *path, std::string &s)
00894 {
00895   set_string_internal(MSG_CONFIG_SET_STRING, path, s.c_str());
00896 }
00897 
00898 
00899 void
00900 NetworkConfiguration::set_default_string(const char *path, std::string &s)
00901 {
00902   set_string_internal(MSG_CONFIG_SET_DEFAULT_STRING, path, s.c_str());
00903 }
00904 
00905 
00906 void
00907 NetworkConfiguration::set_comment_internal(unsigned int msg_type,
00908                                           const char *path,
00909                                           const char *s)
00910 {
00911   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00912     throw OutOfBoundsException("NetworkConfiguration::set_comment: "
00913                                "Maximum length for path exceeded");
00914   }
00915   if ( ! __connected ) {
00916     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00917                                   "client connection is not alive");
00918   }
00919 
00920   mutex->lock();
00921   size_t s_length = strlen(s);
00922   size_t sl = sizeof(config_comment_msg_t) + s_length;
00923 
00924   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00925                                                         msg_type, sl);
00926   config_comment_msg_t *m = omsg->msgge<config_comment_msg_t>();
00927   strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00928   m->s_length = s_length;
00929   strcpy(m->s, s);
00930   c->enqueue_and_wait(omsg);
00931   if ( ! __mirror_mode && (msg != NULL) ) {
00932     msg->unref();
00933     msg = NULL;
00934   }
00935   mutex->unlock();
00936 }
00937 
00938 
00939 void
00940 NetworkConfiguration::set_comment(const char *path, const char *comment)
00941 {
00942   set_comment_internal(MSG_CONFIG_SET_COMMENT, path, comment);
00943 }
00944 
00945 
00946 void
00947 NetworkConfiguration::set_default_comment(const char *path, const char *comment)
00948 {
00949   set_comment_internal(MSG_CONFIG_SET_DEFAULT_COMMENT, path, comment);
00950 }
00951 
00952 
00953 void
00954 NetworkConfiguration::set_comment(const char *path, std::string &comment)
00955 {
00956   set_comment_internal(MSG_CONFIG_SET_COMMENT, path, comment.c_str());
00957 }
00958 
00959 
00960 void
00961 NetworkConfiguration::set_default_comment(const char *path, std::string &comment)
00962 {
00963   set_comment_internal(MSG_CONFIG_SET_DEFAULT_COMMENT, path, comment.c_str());
00964 }
00965 
00966 
00967 void
00968 NetworkConfiguration::erase_internal(const char *path, bool is_default)
00969 {
00970   if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
00971     throw OutOfBoundsException("NetworkConfiguration::erase: "
00972                                "Maximum length for path exceeded");
00973   }
00974   if ( ! __connected ) {
00975     throw ConnectionDiedException("NetworkConfiguration: Cannot set value, "
00976                                   "client connection is not alive");
00977   }
00978 
00979   mutex->lock();
00980   FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
00981                                                         MSG_CONFIG_ERASE_VALUE,
00982                                                         sizeof(config_erase_value_msg_t));
00983   config_erase_value_msg_t *m = omsg->msg<config_erase_value_msg_t>();
00984   m->cp.is_default = is_default ? 1 : 0;
00985   strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
00986   c->enqueue_and_wait(omsg);
00987   if ( ! __mirror_mode && (msg != NULL) ) {
00988     msg->unref();
00989     msg = NULL;
00990   }
00991   mutex->unlock();
00992 }
00993 
00994 
00995 void
00996 NetworkConfiguration::erase(const char *path)
00997 {
00998   erase_internal(path, /*default */ false);
00999 }
01000 
01001 
01002 void
01003 NetworkConfiguration::erase_default(const char *path)
01004 {
01005   erase_internal(path, /*default */ true);
01006 }
01007 
01008 
01009 /** We are no longer registered in Fawkes network client.
01010  * Ignored.
01011  * @param id the id of the calling client
01012  */
01013 void
01014 NetworkConfiguration::deregistered(unsigned int id) throw()
01015 {
01016 }
01017 
01018 
01019 void
01020 NetworkConfiguration::inbound_received(FawkesNetworkMessage *m,
01021                                        unsigned int id) throw()
01022 {
01023   if ( m->cid() == FAWKES_CID_CONFIGMANAGER ) {
01024 
01025     if ( __mirror_mode ) {
01026       switch (m->msgid()) {
01027       case MSG_CONFIG_LIST:
01028         // put all values into mirror database
01029         {
01030           mirror_config->transaction_begin();
01031           ConfigListContent *clc = m->msgc<ConfigListContent>();
01032           while ( clc->has_next() ) {
01033             size_t cle_size = 0;
01034             config_list_entity_header_t *cle = clc->next(&cle_size);
01035             switch ( cle->type ) {
01036             case MSG_CONFIG_FLOAT_VALUE:
01037               if ( cle_size == sizeof(config_list_float_entity_t) ) {
01038                 config_list_float_entity_t *clev = (config_list_float_entity_t *)cle;
01039                 if ( cle->cp.is_default ) {
01040                   mirror_config->set_default_float(cle->cp.path, clev->f);
01041                 } else {
01042                   mirror_config->set_float(cle->cp.path, clev->f);
01043                 }
01044               }
01045               break;
01046 
01047             case MSG_CONFIG_INT_VALUE:
01048               if ( cle_size == sizeof(config_list_int_entity_t) ) {
01049                 config_list_int_entity_t *clev = (config_list_int_entity_t *)cle;
01050                 if ( cle->cp.is_default ) {
01051                   mirror_config->set_default_int(cle->cp.path, clev->i);
01052                 } else {
01053                   mirror_config->set_int(cle->cp.path, clev->i);
01054                 }
01055               }
01056               break;
01057 
01058             case MSG_CONFIG_UINT_VALUE:
01059               if ( cle_size == sizeof(config_list_uint_entity_t) ) {
01060                 config_list_uint_entity_t *clev = (config_list_uint_entity_t *)cle;
01061                 if ( cle->cp.is_default ) {
01062                   mirror_config->set_default_uint(cle->cp.path, clev->u);
01063                 } else {
01064                   mirror_config->set_uint(cle->cp.path, clev->u);
01065                 }
01066               }
01067               break;
01068 
01069             case MSG_CONFIG_BOOL_VALUE:
01070               if ( cle_size == sizeof(config_list_bool_entity_t) ) {
01071                 config_list_bool_entity_t *clev = (config_list_bool_entity_t *)cle;
01072                 if ( cle->cp.is_default ) {
01073                   mirror_config->set_default_bool(cle->cp.path, clev->b != 0);
01074                 } else {
01075                   mirror_config->set_bool(cle->cp.path, clev->b != 0);
01076                 }
01077               }
01078               break;
01079 
01080             case MSG_CONFIG_STRING_VALUE:
01081               if ( cle_size >= sizeof(config_list_string_entity_t) ) {
01082                 config_list_string_entity_t *clev = (config_list_string_entity_t *)cle;
01083                 if ( cle->cp.is_default ) {
01084                   mirror_config->set_default_string(cle->cp.path, clev->s);
01085                 } else {
01086                   mirror_config->set_string(cle->cp.path, clev->s);
01087                 }
01088               }
01089               break;
01090 
01091             case MSG_CONFIG_COMMENT_VALUE:
01092               if ( cle_size >= sizeof(config_list_comment_entity_t) ) {
01093                 config_list_comment_entity_t *clev = (config_list_comment_entity_t *)cle;
01094                 if ( cle->cp.is_default ) {
01095                   mirror_config->set_default_comment(cle->cp.path, clev->s);
01096                 } else {
01097                   mirror_config->set_comment(cle->cp.path, clev->s);
01098                 }
01099               } else {
01100                 LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: ignoring bad comment");
01101               }
01102               break;
01103             }
01104           }
01105           mirror_config->transaction_commit();
01106           delete clc;
01107         }
01108 
01109         // add all change handlers
01110         for (ChangeHandlerMultimap::const_iterator j = _change_handlers.begin(); j != _change_handlers.end(); ++j) {
01111           _ch_range = _change_handlers.equal_range((*j).first);
01112           for (ChangeHandlerMultimap::const_iterator i = _ch_range.first; i != _ch_range.second; ++i) {
01113             mirror_config->add_change_handler((*i).second);
01114           }
01115         }
01116         // initial answer received -> wake up set_mirror_mode()
01117         if (__mirror_init_barrier) __mirror_init_barrier->wait();
01118         break;
01119 
01120       case MSG_CONFIG_VALUE_ERASED:
01121         try {
01122           config_value_erased_msg_t *em = m->msg<config_value_erased_msg_t>();
01123           if (em->cp.is_default == 1) {
01124             mirror_config->erase_default(em->cp.path);
01125           } else {
01126             mirror_config->erase(em->cp.path);
01127           }
01128         } catch (Exception &e) {
01129           // Just ignore silently
01130           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: erasing failed");
01131         }
01132         break;
01133 
01134       case MSG_CONFIG_FLOAT_VALUE:
01135         try {
01136           config_float_value_msg_t *fm = m->msg<config_float_value_msg_t>();
01137           if (fm->cp.is_default == 1) {
01138             mirror_config->set_default_float(fm->cp.path, fm->f);
01139           } else {
01140             mirror_config->set_float(fm->cp.path, fm->f);
01141           }
01142         } catch (TypeMismatchException &e) {
01143           // Just ignore silently
01144           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: invalid float received");
01145         }
01146         break;
01147 
01148       case MSG_CONFIG_UINT_VALUE:
01149         try {
01150           config_uint_value_msg_t *um = m->msg<config_uint_value_msg_t>();
01151           if (um->cp.is_default == 1) {
01152             mirror_config->set_default_uint(um->cp.path, um->u);
01153           } else {
01154             mirror_config->set_uint(um->cp.path, um->u);
01155           }
01156         } catch (TypeMismatchException &e) {
01157           // Just ignore silently
01158           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: invalid uint received");
01159         }
01160         break;
01161 
01162       case MSG_CONFIG_INT_VALUE:
01163         try {
01164           config_int_value_msg_t *im = m->msg<config_int_value_msg_t>();
01165           if (im->cp.is_default == 1) {
01166             mirror_config->set_default_int(im->cp.path, im->i);
01167           } else {
01168             mirror_config->set_int(im->cp.path, im->i);
01169           }
01170         } catch (TypeMismatchException &e) {
01171           // Just ignore silently
01172           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: invalid int received");
01173         }
01174         break;
01175 
01176       case MSG_CONFIG_BOOL_VALUE:
01177         try {
01178           config_bool_value_msg_t *bm = m->msg<config_bool_value_msg_t>();
01179           if (bm->cp.is_default == 1) {
01180             mirror_config->set_default_bool(bm->cp.path, (bm->b != 0));
01181           } else {
01182             mirror_config->set_bool(bm->cp.path, (bm->b != 0));
01183           }
01184         } catch (TypeMismatchException &e) {
01185           // Just ignore silently
01186           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: invalid bool received");
01187         }
01188         break;
01189 
01190       case MSG_CONFIG_STRING_VALUE:
01191         try {
01192           config_string_value_msg_t *sm = m->msgge<config_string_value_msg_t>();
01193           if (sm->cp.is_default == 1) {
01194             mirror_config->set_default_string(sm->cp.path, sm->s);
01195           } else {
01196             mirror_config->set_string(sm->cp.path, sm->s);
01197           }
01198         } catch (TypeMismatchException &e) {
01199           // Just ignore silently
01200           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: invalid string received");
01201         }
01202         break;
01203 
01204       case MSG_CONFIG_COMMENT_VALUE:
01205         try {
01206           config_comment_msg_t *cm = m->msgge<config_comment_msg_t>();
01207           if (cm->cp.is_default == 1) {
01208             mirror_config->set_default_comment(cm->cp.path, cm->s);
01209           } else {
01210             mirror_config->set_comment(cm->cp.path, cm->s);
01211           }
01212         } catch (TypeMismatchException &e) {
01213           // Just ignore silently
01214           LibLogger::log_warn("NetworkConfiguration", "[mirroring]::inboundReceived: invalid string received");
01215         }
01216         break;
01217       }
01218     } else {
01219       msg = m;
01220       msg->ref();
01221     }
01222   }
01223 }
01224 
01225 
01226 void
01227 NetworkConfiguration::connection_died(unsigned int id) throw()
01228 {
01229   __connected = false;
01230   __mirror_mode_before_connection_dead = __mirror_mode;
01231   set_mirror_mode(false);
01232   mutex->unlock(); //Just in case...
01233 }
01234 
01235 
01236 void
01237 NetworkConfiguration::connection_established(unsigned int id) throw()
01238 {
01239   __connected = true;
01240   set_mirror_mode(__mirror_mode_before_connection_dead);
01241 }
01242 
01243 
01244 void
01245 NetworkConfiguration::add_change_handler(ConfigurationChangeHandler *h)
01246 {
01247   Configuration::add_change_handler(h);
01248 
01249   if ( __mirror_mode ) {
01250     mirror_config->add_change_handler(h);
01251   }
01252 }
01253 
01254 
01255 void
01256 NetworkConfiguration::rem_change_handler(ConfigurationChangeHandler *h)
01257 {
01258   Configuration::rem_change_handler(h);
01259   if ( __mirror_mode ) {
01260     mirror_config->rem_change_handler(h);
01261   }
01262 }
01263 
01264 
01265 /** Enable or disable mirror mode.
01266  * @param mirror true to enable mirror mode, false to disable
01267  */
01268 void
01269 NetworkConfiguration::set_mirror_mode(bool mirror)
01270 {
01271   if ( mirror ) {
01272     if ( ! __mirror_mode ) {
01273 
01274       if ( ! __connected ) {
01275         throw CannotEnableMirroringException("Client connection is dead");
01276       }
01277 
01278       mirror_config = new SQLiteConfiguration();
01279       mirror_config->load(":memory:", ":memory:");
01280 
01281       __mirror_init_barrier = new InterruptibleBarrier(2);
01282       mutex->lock();
01283 
01284       __mirror_mode = true;
01285 
01286       // subscribe
01287       FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
01288                                                             MSG_CONFIG_SUBSCRIBE);
01289       c->enqueue(omsg);
01290 
01291       // wait until all data has been received (or timeout)
01292       if (! __mirror_init_barrier->wait(__mirror_timeout_sec, 0)) {
01293         // timeout
01294         delete mirror_config;
01295         __mirror_init_barrier = NULL;
01296         delete __mirror_init_barrier;
01297         mutex->unlock();
01298         throw CannotEnableMirroringException("Didn't receive data in time");
01299       }
01300       mutex->unlock();
01301       delete __mirror_init_barrier;
01302       __mirror_init_barrier = NULL;
01303     }
01304   } else {
01305     if ( __mirror_mode ) {
01306       __mirror_mode = false;
01307       // unsubscribe
01308       if ( __connected ) {
01309         FawkesNetworkMessage *omsg = new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
01310                                                               MSG_CONFIG_UNSUBSCRIBE);
01311         c->enqueue(omsg);
01312       }
01313 
01314       // delete local temporary mirror database
01315       delete mirror_config;
01316     }
01317   }
01318 }
01319 
01320 
01321 void
01322 NetworkConfiguration::lock()
01323 {
01324   mutex->lock();
01325 }
01326 
01327 
01328 bool
01329 NetworkConfiguration::try_lock()
01330 {
01331   return mutex->try_lock();
01332 }
01333 
01334 
01335 void
01336 NetworkConfiguration::unlock()
01337 {
01338   mutex->unlock();
01339 }
01340 
01341 
01342 Configuration::ValueIterator *
01343 NetworkConfiguration::iterator()
01344 {
01345   if ( __mirror_mode ) {
01346     return mirror_config->iterator();
01347   } else {
01348     throw Exception("NetworkConfiguration: Iterating only supported in mirror mode");
01349   }
01350 }
01351 
01352 
01353 Configuration::ValueIterator *
01354 NetworkConfiguration::iterator_default()
01355 {
01356   if ( __mirror_mode ) {
01357     return mirror_config->iterator_default();
01358   } else {
01359     throw Exception("NetworkConfiguration: Iterating only supported in mirror mode");
01360   }
01361 }
01362 
01363 
01364 Configuration::ValueIterator *
01365 NetworkConfiguration::iterator_hostspecific()
01366 {
01367   if ( __mirror_mode ) {
01368     return mirror_config->iterator_hostspecific();
01369   } else {
01370     throw Exception("NetworkConfiguration: Iterating only supported in mirror mode");
01371   }
01372 }
01373 
01374 
01375 Configuration::ValueIterator *
01376 NetworkConfiguration::search(const char *path)
01377 {
01378   if ( __mirror_mode ) {
01379     return mirror_config->search(path);
01380   } else {
01381     throw Exception("NetworkConfiguration: Searching only supported in mirror mode");
01382   }
01383 }
01384 
01385 
01386 /** @class NetworkConfiguration::NetConfValueIterator <config/netconf.h>
01387  * Network configuration value iterator.
01388  * @author Tim Niemueller
01389  */
01390 
01391 
01392 /** Constructor.
01393  * @param i internal other iterator, for instance form local mirrored database.
01394  */
01395 NetworkConfiguration::NetConfValueIterator::NetConfValueIterator(Configuration::ValueIterator *i)
01396 {
01397   // not interesting in this case, but anyway...
01398   iterated_once = false;
01399   this->i = i;
01400   msg = NULL;
01401   _path = NULL;
01402 }
01403 
01404 
01405 /** Constructor.
01406  * Returns invalid iterator.
01407  */
01408 NetworkConfiguration::NetConfValueIterator::NetConfValueIterator()
01409 {
01410   // not interesting in this case, but anyway...
01411   iterated_once = false;
01412   i = NULL;
01413   msg = NULL;
01414   _path = NULL;
01415 }
01416 
01417 
01418 /** Constructor.
01419  * Internally holds a message. Only this one value is accessible.
01420  * @param m message
01421  */
01422 NetworkConfiguration::NetConfValueIterator::NetConfValueIterator(FawkesNetworkMessage *m)
01423 {
01424   i = NULL;
01425   msg = NULL;
01426   iterated_once = false;
01427   _path = NULL;
01428 
01429   if ( (m->cid() == FAWKES_CID_CONFIGMANAGER) &&
01430        (m->msgid() >= MSG_CONFIG_VALUE_BEGIN) &&
01431        (m->msgid() <= MSG_CONFIG_VALUE_END) &&
01432        (m->payload_size() > sizeof(config_descriptor_t)) ) {
01433     msg = m;
01434     msg->ref();
01435     // extract path
01436     // all messages start with config_descriptor!
01437     _path      = (char *)malloc(CONFIG_MSG_PATH_LENGTH + 1);
01438     _path[CONFIG_MSG_PATH_LENGTH] = 0;
01439     config_descriptor_t *cd = (config_descriptor_t *)msg->payload();
01440     strncpy(_path, cd->path, CONFIG_MSG_PATH_LENGTH);
01441   } else {
01442     // invalid value, maybe path does not exist!
01443   }
01444 }
01445 
01446 
01447 /** Destructor. */
01448 NetworkConfiguration::NetConfValueIterator::~NetConfValueIterator()
01449 {
01450   delete i;
01451   if ( msg != NULL )         msg->unref();
01452   if ( _path != NULL)        free(_path);
01453 }
01454 
01455 
01456 bool
01457 NetworkConfiguration::NetConfValueIterator::next()
01458 {
01459   if ( i == NULL) {
01460     if ( (msg == NULL) || iterated_once ) {
01461       return false;
01462     } else {
01463       iterated_once = true;
01464       return true;
01465     }
01466   } else {
01467     return i->next();
01468   }
01469 }
01470 
01471 
01472 bool
01473 NetworkConfiguration::NetConfValueIterator::valid()
01474 {
01475   return ( (i != NULL) || (msg != NULL) );
01476 }
01477 
01478 
01479 const char *
01480 NetworkConfiguration::NetConfValueIterator::path()
01481 {
01482   if ( i == NULL ) {
01483     if ( msg == NULL ) {
01484       throw NullPointerException("You may not access path on invalid iterator");
01485     } else {
01486       return _path;
01487     }
01488   } else {
01489     return i->path();
01490   }
01491 }
01492 
01493 
01494 const char *
01495 NetworkConfiguration::NetConfValueIterator::type()
01496 {
01497   if ( i == NULL ) {
01498     if ( msg == NULL ) {
01499       throw NullPointerException("You may not access path on invalid iterator");
01500     }
01501 
01502     switch (msg->msgid()) {
01503     case MSG_CONFIG_FLOAT_VALUE:   return "float";
01504     case MSG_CONFIG_UINT_VALUE:    return "unsigned int";
01505     case MSG_CONFIG_INT_VALUE:     return "int";
01506     case MSG_CONFIG_BOOL_VALUE:    return "bool";
01507     case MSG_CONFIG_STRING_VALUE:  return "string";
01508     default:
01509       throw NullPointerException("Unknown type in NetConfValueIterator");
01510     }
01511   } else {
01512     return i->type();
01513   }
01514 }
01515 
01516 
01517 bool
01518 NetworkConfiguration::NetConfValueIterator::is_float()
01519 {
01520   if ( i == NULL ) {
01521     if ( msg == NULL ) {
01522       throw NullPointerException("You may not access value methods on invalid iterator");
01523     }
01524     return (msg->msgid() == MSG_CONFIG_FLOAT_VALUE);
01525   } else {
01526     return i->is_float();
01527   }
01528 }
01529 
01530 
01531 bool
01532 NetworkConfiguration::NetConfValueIterator::is_uint()
01533 {
01534   if ( i == NULL ) {
01535     if ( msg == NULL ) {
01536       throw NullPointerException("You may not access value methods on invalid iterator");
01537     }
01538     return (msg->msgid() == MSG_CONFIG_UINT_VALUE);
01539   } else {
01540     return i->is_float();
01541   }
01542 }
01543 
01544 
01545 bool
01546 NetworkConfiguration::NetConfValueIterator::is_int()
01547 {
01548   if ( i == NULL ) {
01549     if ( msg == NULL ) {
01550       throw NullPointerException("You may not access value methods on invalid iterator");
01551     }
01552     return (msg->msgid() == MSG_CONFIG_INT_VALUE);
01553   } else {
01554     return i->is_int();
01555   }
01556 }
01557 
01558 
01559 bool
01560 NetworkConfiguration::NetConfValueIterator::is_bool()
01561 {
01562   if ( i == NULL ) {
01563     if ( msg == NULL ) {
01564       throw NullPointerException("You may not access value methods on invalid iterator");
01565     }
01566     return (msg->msgid() == MSG_CONFIG_BOOL_VALUE);
01567   } else {
01568     return i->is_bool();
01569   }
01570 }
01571 
01572 
01573 bool
01574 NetworkConfiguration::NetConfValueIterator::is_string()
01575 {
01576   if ( i == NULL ) {
01577     if ( msg == NULL ) {
01578       throw NullPointerException("You may not access value methods on invalid iterator");
01579     }
01580     return (msg->msgid() == MSG_CONFIG_STRING_VALUE);
01581   } else {
01582     return i->is_string();
01583   }
01584 }
01585 
01586 
01587 bool
01588 NetworkConfiguration::NetConfValueIterator::is_default()
01589 {
01590   if ( i == NULL ) {
01591     if ( msg == NULL ) {
01592       throw NullPointerException("You may not access value methods on invalid iterator");
01593     } else {
01594       unsigned int msgid = msg->msgid();
01595       switch (msgid) {
01596       case MSG_CONFIG_FLOAT_VALUE:
01597         {
01598           config_float_value_msg_t *m = msg->msg<config_float_value_msg_t>();
01599           return m->cp.is_default;
01600         }
01601       case MSG_CONFIG_UINT_VALUE:
01602         {
01603           config_uint_value_msg_t *m = msg->msg<config_uint_value_msg_t>();
01604           return m->cp.is_default;
01605         }
01606       case MSG_CONFIG_INT_VALUE:
01607         {
01608           config_int_value_msg_t *m = msg->msg<config_int_value_msg_t>();
01609           return m->cp.is_default;
01610         }
01611       case MSG_CONFIG_BOOL_VALUE:
01612         {
01613           config_bool_value_msg_t *m = msg->msg<config_bool_value_msg_t>();
01614           return m->cp.is_default;
01615         }
01616       case MSG_CONFIG_STRING_VALUE:
01617         {
01618           config_string_value_msg_t *m = msg->msgge<config_string_value_msg_t>();
01619           return m->cp.is_default;
01620         }
01621       }
01622 
01623       throw TypeMismatchException("NetworkConfiguration: Neither in mirror mode nor "
01624                                   "iterator to value message");
01625     }
01626   } else {
01627     return i->is_default();
01628   }
01629 }
01630 
01631 
01632 float
01633 NetworkConfiguration::NetConfValueIterator::get_float()
01634 {
01635   if ( i == NULL ) {
01636     if ( msg == NULL ) {
01637       throw NullPointerException("You may not access value methods on invalid iterator");
01638     }
01639     if (msg->msgid() == MSG_CONFIG_FLOAT_VALUE) {
01640       config_float_value_msg_t *fm = msg->msg<config_float_value_msg_t>();
01641       return fm->f;
01642     } else {
01643       throw TypeMismatchException("NetConfValueIterator::get_float: type mismatch");
01644     }
01645   } else {
01646     return i->get_float();
01647   }
01648 }
01649 
01650 
01651 unsigned int
01652 NetworkConfiguration::NetConfValueIterator::get_uint()
01653 {
01654   if ( i == NULL ) {
01655     if ( msg == NULL ) {
01656       throw NullPointerException("You may not access value methods on invalid iterator");
01657     }
01658     if (msg->msgid() == MSG_CONFIG_UINT_VALUE) {
01659       config_uint_value_msg_t *um = msg->msg<config_uint_value_msg_t>();
01660       return um->u;
01661     } else {
01662       throw TypeMismatchException("NetConfValueIterator::get_uint: type mismatch");
01663     }
01664   } else {
01665     return i->get_int();
01666   }
01667 }
01668 
01669 
01670 int
01671 NetworkConfiguration::NetConfValueIterator::get_int()
01672 {
01673   if ( i == NULL ) {
01674     if ( msg == NULL ) {
01675       throw NullPointerException("You may not access value methods on invalid iterator");
01676     }
01677     if (msg->msgid() == MSG_CONFIG_INT_VALUE) {
01678       config_int_value_msg_t *im = msg->msg<config_int_value_msg_t>();
01679       return im->i;
01680     } else {
01681       throw TypeMismatchException("NetConfValueIterator::get_int: type mismatch");
01682     }
01683   } else {
01684     return i->get_int();
01685   }
01686 }
01687 
01688 
01689 bool
01690 NetworkConfiguration::NetConfValueIterator::get_bool()
01691 {
01692   if ( i == NULL ) {
01693     if ( msg == NULL ) {
01694       throw NullPointerException("You may not access value methods on invalid iterator");
01695     }
01696     if (msg->msgid() == MSG_CONFIG_BOOL_VALUE) {
01697       config_bool_value_msg_t *bm = msg->msg<config_bool_value_msg_t>();
01698       return (bm->b != 0);
01699     } else {
01700       throw TypeMismatchException("NetConfValueIterator::get_bool: type mismatch");
01701     }
01702   } else {
01703     return i->get_bool();
01704   }
01705 }
01706 
01707 
01708 std::string
01709 NetworkConfiguration::NetConfValueIterator::get_string()
01710 {
01711   if ( i == NULL ) {
01712     if ( msg == NULL ) {
01713       throw NullPointerException("You may not access value methods on invalid iterator");
01714     }
01715     if (msg->msgid() == MSG_CONFIG_STRING_VALUE) {
01716       config_string_value_msg_t *sm = msg->msgge<config_string_value_msg_t>();
01717       return sm->s;
01718     } else {
01719       throw TypeMismatchException("NetConfValueIterator::get_string: type mismatch, expected %u, got %u",
01720                                   MSG_CONFIG_STRING_VALUE, msg->msgid());
01721     }
01722   } else {
01723     return i->get_string();
01724   }
01725 }
01726 
01727 
01728 std::string
01729 NetworkConfiguration::NetConfValueIterator::get_comment()
01730 {
01731   if ( i == NULL ) {
01732     if ( msg == NULL ) {
01733       throw NullPointerException("You may not access value methods on invalid iterator");
01734     }
01735     if (msg->msgid() == MSG_CONFIG_COMMENT_VALUE) {
01736       config_comment_msg_t *cm = msg->msgge<config_comment_msg_t>();
01737       return cm->s;
01738     } else {
01739       throw TypeMismatchException("NetConfValueIterator::get_comment: type mismatch");
01740     }
01741   } else {
01742     return i->get_comment();
01743   }
01744 }
01745 
01746 } // end namespace fawkes

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1