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