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