24 #include <config/netconf.h>
25 #include <config/net_messages.h>
26 #include <config/sqlite.h>
27 #include <config/net_list_content.h>
29 #include <core/threading/mutex.h>
30 #include <core/threading/interruptible_barrier.h>
31 #include <netcomm/fawkes/client.h>
32 #include <netcomm/fawkes/message.h>
33 #include <netcomm/utils/exceptions.h>
35 #include <logging/liblogger.h>
36 #include <utils/misc/string_conversions.h>
54 :
Exception(
"Could not enable mirroring: %s", msg)
79 unsigned int mirror_timeout_sec)
81 __mirror_timeout_sec = mirror_timeout_sec;
87 e.
append(
"Failed to register for config manager component on network client");
92 __mirror_mode =
false;
93 __mirror_mode_before_connection_dead =
false;
94 __mirror_init_barrier = NULL;
106 delete __mirror_init_barrier;
120 const char *defaults_name,
138 while ( i->
next() ) {
141 }
else if ( i->
is_int() ) {
166 std::list<std::string>
170 std::list<std::string> l;
180 bool rv = i->
valid();
205 if ( __mirror_mode ) {
228 return (
get_type(path) ==
"unsigned int");
249 return (
get_type(path) ==
"string");
254 NetworkConfiguration::send_get(
const char *path,
unsigned int msgid)
256 if ( ! __connected ) {
258 "client connection is not alive");
260 config_getval_msg_t *g = (config_getval_msg_t *)calloc(1,
sizeof(config_getval_msg_t));
261 strncpy(g->cp.path, path, CONFIG_MSG_PATH_LENGTH);
262 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
264 g,
sizeof(config_getval_msg_t));
269 throw NullPointerException(
"NetworkConfiguration::send_get: msg == NULL");
272 if ( msg->
msgid() != msgid ) {
276 throw TypeMismatchException(
"NetworkConfiguration::send_get: msg type not float");
284 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
286 "Maximum length for path exceeded");
288 if ( ! __connected ) {
290 "client connection is not alive");
296 if ( __mirror_mode ) {
300 e.
append(
"NetworkConfiguration[mirroring]::get_float: exception in mirror database");
306 send_get(path, MSG_CONFIG_GET_FLOAT);
315 e.
append(
"NetworkConfiguration::get_float: Fetching float failed");
334 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
336 "Maximum length for path exceeded");
338 if ( ! __connected ) {
340 "client connection is not alive");
346 if ( __mirror_mode ) {
350 e.
append(
"NetworkConfiguration[mirroring]::get_uint: exception in mirror database");
356 send_get(path, MSG_CONFIG_GET_UINT);
365 e.
append(
"NetworkConfiguration::get_uint: Fetching unsigned int failed");
384 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
386 "Maximum length for path exceeded");
388 if ( ! __connected ) {
390 "client connection is not alive");
396 if ( __mirror_mode ) {
398 i = mirror_config->
get_int(path);
400 e.
append(
"NetworkConfiguration[mirroring]::get_int: exception in mirror database");
406 send_get(path, MSG_CONFIG_GET_INT);
415 e.
append(
"NetworkConfiguration::get_int: Fetching int failed");
434 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
436 "Maximum length for path exceeded");
438 if ( ! __connected ) {
440 "client connection is not alive");
446 if ( __mirror_mode ) {
450 e.
append(
"NetworkConfiguration[mirroring]::get_bool: exception in mirror database");
456 send_get(path, MSG_CONFIG_GET_BOOL);
465 e.
append(
"NetworkConfiguration::get_bool: Fetching bool failed");
484 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
486 "Maximum length for path exceeded");
488 if ( ! __connected ) {
490 "client connection is not alive");
496 if ( __mirror_mode ) {
500 e.
append(
"NetworkConfiguration[mirroring]::get_string: exception in mirror database");
506 send_get(path, MSG_CONFIG_GET_STRING);
515 e.
append(
"NetworkConfiguration::get_string: Fetching int failed");
534 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
536 "Maximum length for path exceeded");
538 if ( ! __connected ) {
540 "client connection is not alive");
546 if ( __mirror_mode ) {
550 e.
append(
"NetworkConfiguration[mirroring]::get_comment: exception in mirror database");
556 send_get(path, MSG_CONFIG_GET_COMMENT);
565 e.
append(
"NetworkConfiguration::get_comment: Fetching int failed");
584 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
586 "Maximum length for path exceeded");
588 if ( ! __connected ) {
590 "client connection is not alive");
596 if ( __mirror_mode ) {
600 e.
append(
"NetworkConfiguration[mirroring]::get_default_comment: "
601 "exception in mirror database");
607 send_get(path, MSG_CONFIG_GET_DEFAULT_COMMENT);
616 e.
append(
"NetworkConfiguration::get_comment: Fetching int failed");
635 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
637 "Maximum length for path exceeded");
639 if ( ! __connected ) {
641 "client connection is not alive");
647 if ( __mirror_mode ) {
651 e.
append(
"NetworkConfiguration[mirroring]::get_float: exception in mirror database");
657 strncpy(g->
cp.
path, path, CONFIG_MSG_PATH_LENGTH);
659 MSG_CONFIG_GET_VALUE,
681 NetworkConfiguration::set_float_internal(
unsigned int msg_type,
682 const char *path,
float f)
684 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
686 "Maximum length for path exceeded");
688 if ( ! __connected ) {
689 throw ConnectionDiedException(
"NetworkConfiguration: Cannot set value, "
690 "client connection is not alive");
694 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
696 sizeof(config_float_value_msg_t));
697 config_float_value_msg_t *fm = omsg->msg<config_float_value_msg_t>();
698 strncpy(fm->cp.path, path, CONFIG_MSG_PATH_LENGTH);
701 if ( ! __mirror_mode && (msg != NULL) ) {
712 set_float_internal(MSG_CONFIG_SET_FLOAT, path, f);
719 set_float_internal(MSG_CONFIG_SET_DEFAULT_FLOAT, path, f);
724 NetworkConfiguration::set_uint_internal(
unsigned int msg_type,
725 const char *path,
unsigned int uint)
727 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
729 "Maximum length for path exceeded");
731 if ( ! __connected ) {
732 throw ConnectionDiedException(
"NetworkConfiguration: Cannot set value, "
733 "client connection is not alive");
737 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
739 sizeof(config_uint_value_msg_t));
740 config_uint_value_msg_t *m = omsg->msg<config_uint_value_msg_t>();
741 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
744 if ( ! __mirror_mode && (msg != NULL) ) {
755 set_uint_internal(MSG_CONFIG_SET_UINT, path, uint);
762 set_uint_internal(MSG_CONFIG_SET_DEFAULT_UINT, path, uint);
767 NetworkConfiguration::set_int_internal(
unsigned int msg_type,
768 const char *path,
int i)
770 if ( ! __connected ) {
772 "client connection is not alive");
776 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
778 sizeof(config_int_value_msg_t));
779 config_int_value_msg_t *m = omsg->msg<config_int_value_msg_t>();
780 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
783 if ( ! __mirror_mode && (msg != NULL) ) {
794 set_int_internal(MSG_CONFIG_SET_INT, path, i);
801 set_int_internal(MSG_CONFIG_SET_DEFAULT_INT, path, i);
806 NetworkConfiguration::set_bool_internal(
unsigned int msg_type,
807 const char *path,
bool b)
809 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
811 "Maximum length for path exceeded");
813 if ( ! __connected ) {
814 throw ConnectionDiedException(
"NetworkConfiguration: Cannot set value, "
815 "client connection is not alive");
819 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
821 sizeof(config_bool_value_msg_t));
822 config_bool_value_msg_t *m = omsg->msg<config_bool_value_msg_t>();
823 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
826 if ( ! __mirror_mode && (msg != NULL) ) {
837 set_bool_internal(MSG_CONFIG_SET_BOOL, path, b);
844 set_bool_internal(MSG_CONFIG_SET_DEFAULT_BOOL, path, b);
849 NetworkConfiguration::set_string_internal(
unsigned int msg_type,
853 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
855 "Maximum length for path exceeded");
857 if ( ! __connected ) {
858 throw ConnectionDiedException(
"NetworkConfiguration: Cannot set value, "
859 "client connection is not alive");
863 size_t s_length = strlen(s);
864 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
866 sizeof(config_string_value_msg_t) + s_length);
867 config_string_value_msg_t *m = omsg->msgge<config_string_value_msg_t>();
868 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
871 if ( ! __mirror_mode && (msg != NULL) ) {
882 set_string_internal(MSG_CONFIG_SET_STRING, path, s);
889 set_string_internal(MSG_CONFIG_SET_DEFAULT_STRING, path, s);
896 set_string_internal(MSG_CONFIG_SET_STRING, path, s.c_str());
903 set_string_internal(MSG_CONFIG_SET_DEFAULT_STRING, path, s.c_str());
908 NetworkConfiguration::set_comment_internal(
unsigned int msg_type,
912 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
914 "Maximum length for path exceeded");
916 if ( ! __connected ) {
917 throw ConnectionDiedException(
"NetworkConfiguration: Cannot set value, "
918 "client connection is not alive");
922 size_t s_length = strlen(s);
923 size_t sl =
sizeof(config_comment_msg_t) + s_length;
925 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
927 config_comment_msg_t *m = omsg->msgge<config_comment_msg_t>();
928 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
929 m->s_length = s_length;
932 if ( ! __mirror_mode && (msg != NULL) ) {
943 set_comment_internal(MSG_CONFIG_SET_COMMENT, path, comment);
950 set_comment_internal(MSG_CONFIG_SET_DEFAULT_COMMENT, path, comment);
957 set_comment_internal(MSG_CONFIG_SET_COMMENT, path, comment.c_str());
964 set_comment_internal(MSG_CONFIG_SET_DEFAULT_COMMENT, path, comment.c_str());
969 NetworkConfiguration::erase_internal(
const char *path,
bool is_default)
971 if ( strlen(path) > CONFIG_MSG_PATH_LENGTH ) {
973 "Maximum length for path exceeded");
975 if ( ! __connected ) {
976 throw ConnectionDiedException(
"NetworkConfiguration: Cannot set value, "
977 "client connection is not alive");
981 FawkesNetworkMessage *omsg =
new FawkesNetworkMessage(FAWKES_CID_CONFIGMANAGER,
982 MSG_CONFIG_ERASE_VALUE,
983 sizeof(config_erase_value_msg_t));
984 config_erase_value_msg_t *m = omsg->msg<config_erase_value_msg_t>();
985 m->cp.is_default = is_default ? 1 : 0;
986 strncpy(m->cp.path, path, CONFIG_MSG_PATH_LENGTH);
988 if ( ! __mirror_mode && (msg != NULL) ) {
999 erase_internal(path,
false);
1006 erase_internal(path,
true);
1022 unsigned int id)
throw()
1024 if ( m->cid() == FAWKES_CID_CONFIGMANAGER ) {
1026 if ( __mirror_mode ) {
1027 switch (m->msgid()) {
1028 case MSG_CONFIG_LIST:
1031 mirror_config->transaction_begin();
1034 size_t cle_size = 0;
1036 switch ( cle->
type ) {
1037 case MSG_CONFIG_FLOAT_VALUE:
1041 mirror_config->set_default_float(cle->
cp.
path, clev->
f);
1043 mirror_config->set_float(cle->
cp.
path, clev->
f);
1048 case MSG_CONFIG_INT_VALUE:
1052 mirror_config->set_default_int(cle->
cp.
path, clev->
i);
1054 mirror_config->set_int(cle->
cp.
path, clev->
i);
1059 case MSG_CONFIG_UINT_VALUE:
1063 mirror_config->set_default_uint(cle->
cp.
path, clev->
u);
1065 mirror_config->set_uint(cle->
cp.
path, clev->
u);
1070 case MSG_CONFIG_BOOL_VALUE:
1074 mirror_config->set_default_bool(cle->
cp.
path, clev->
b != 0);
1076 mirror_config->set_bool(cle->
cp.
path, clev->
b != 0);
1081 case MSG_CONFIG_STRING_VALUE:
1085 mirror_config->set_default_string(cle->
cp.
path, clev->
s);
1087 mirror_config->set_string(cle->
cp.
path, clev->
s);
1092 case MSG_CONFIG_COMMENT_VALUE:
1096 mirror_config->set_default_comment(cle->
cp.
path, clev->
s);
1098 mirror_config->set_comment(cle->
cp.
path, clev->
s);
1101 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: ignoring bad comment");
1106 mirror_config->transaction_commit();
1111 for (ChangeHandlerMultimap::const_iterator j = _change_handlers.begin(); j != _change_handlers.end(); ++j) {
1112 _ch_range = _change_handlers.equal_range((*j).first);
1113 for (ChangeHandlerMultimap::const_iterator i = _ch_range.first; i != _ch_range.second; ++i) {
1114 mirror_config->add_change_handler((*i).second);
1118 if (__mirror_init_barrier) __mirror_init_barrier->wait();
1121 case MSG_CONFIG_VALUE_ERASED:
1125 mirror_config->erase_default(em->
cp.
path);
1127 mirror_config->erase(em->
cp.
path);
1131 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: erasing failed");
1135 case MSG_CONFIG_FLOAT_VALUE:
1139 mirror_config->set_default_float(fm->
cp.
path, fm->
f);
1141 mirror_config->set_float(fm->
cp.
path, fm->
f);
1145 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: invalid float received");
1149 case MSG_CONFIG_UINT_VALUE:
1153 mirror_config->set_default_uint(um->
cp.
path, um->
u);
1155 mirror_config->set_uint(um->
cp.
path, um->
u);
1159 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: invalid uint received");
1163 case MSG_CONFIG_INT_VALUE:
1167 mirror_config->set_default_int(im->
cp.
path, im->
i);
1169 mirror_config->set_int(im->
cp.
path, im->
i);
1173 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: invalid int received");
1177 case MSG_CONFIG_BOOL_VALUE:
1181 mirror_config->set_default_bool(bm->
cp.
path, (bm->
b != 0));
1183 mirror_config->set_bool(bm->
cp.
path, (bm->
b != 0));
1187 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: invalid bool received");
1191 case MSG_CONFIG_STRING_VALUE:
1195 mirror_config->set_default_string(sm->
cp.
path, sm->
s);
1197 mirror_config->set_string(sm->
cp.
path, sm->
s);
1201 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: invalid string received");
1205 case MSG_CONFIG_COMMENT_VALUE:
1209 mirror_config->set_default_comment(cm->
cp.
path, cm->
s);
1211 mirror_config->set_comment(cm->
cp.
path, cm->
s);
1215 LibLogger::log_warn(
"NetworkConfiguration",
"[mirroring]::inboundReceived: invalid string received");
1230 __connected =
false;
1231 __mirror_mode_before_connection_dead = __mirror_mode;
1232 set_mirror_mode(
false);
1241 set_mirror_mode(__mirror_mode_before_connection_dead);
1250 if ( __mirror_mode ) {
1260 if ( __mirror_mode ) {
1273 if ( ! __mirror_mode ) {
1275 if ( ! __connected ) {
1280 mirror_config->
load(
":memory:",
":memory:");
1285 __mirror_mode =
true;
1289 MSG_CONFIG_SUBSCRIBE);
1293 if (! __mirror_init_barrier->
wait(__mirror_timeout_sec, 0)) {
1295 delete mirror_config;
1296 __mirror_init_barrier = NULL;
1297 delete __mirror_init_barrier;
1302 delete __mirror_init_barrier;
1303 __mirror_init_barrier = NULL;
1306 if ( __mirror_mode ) {
1307 __mirror_mode =
false;
1309 if ( __connected ) {
1311 MSG_CONFIG_UNSUBSCRIBE);
1316 delete mirror_config;
1346 if ( __mirror_mode ) {
1349 throw Exception(
"NetworkConfiguration: Iterating only supported in mirror mode");
1357 if ( __mirror_mode ) {
1360 throw Exception(
"NetworkConfiguration: Iterating only supported in mirror mode");
1368 if ( __mirror_mode ) {
1371 throw Exception(
"NetworkConfiguration: Iterating only supported in mirror mode");
1379 if ( __mirror_mode ) {
1380 return mirror_config->
search(path);
1382 throw Exception(
"NetworkConfiguration: Searching only supported in mirror mode");
1399 iterated_once =
false;
1412 iterated_once =
false;
1427 iterated_once =
false;
1430 if ( (m->
cid() == FAWKES_CID_CONFIGMANAGER) &&
1431 (m->
msgid() >= MSG_CONFIG_VALUE_BEGIN) &&
1432 (m->
msgid() <= MSG_CONFIG_VALUE_END) &&
1438 _path = (
char *)malloc(CONFIG_MSG_PATH_LENGTH + 1);
1439 _path[CONFIG_MSG_PATH_LENGTH] = 0;
1441 strncpy(_path, cd->
path, CONFIG_MSG_PATH_LENGTH);
1452 if ( msg != NULL ) msg->
unref();
1453 if ( _path != NULL) free(_path);
1461 if ( (msg == NULL) || iterated_once ) {
1464 iterated_once =
true;
1476 return ( (i != NULL) || (msg != NULL) );
1484 if ( msg == NULL ) {
1499 if ( msg == NULL ) {
1503 switch (msg->
msgid()) {
1504 case MSG_CONFIG_FLOAT_VALUE:
return "float";
1505 case MSG_CONFIG_UINT_VALUE:
return "unsigned int";
1506 case MSG_CONFIG_INT_VALUE:
return "int";
1507 case MSG_CONFIG_BOOL_VALUE:
return "bool";
1508 case MSG_CONFIG_STRING_VALUE:
return "string";
1522 if ( msg == NULL ) {
1525 return (msg->
msgid() == MSG_CONFIG_FLOAT_VALUE);
1527 return i->is_float();
1536 if ( msg == NULL ) {
1539 return (msg->
msgid() == MSG_CONFIG_UINT_VALUE);
1541 return i->is_float();
1550 if ( msg == NULL ) {
1553 return (msg->
msgid() == MSG_CONFIG_INT_VALUE);
1564 if ( msg == NULL ) {
1567 return (msg->
msgid() == MSG_CONFIG_BOOL_VALUE);
1569 return i->is_bool();
1578 if ( msg == NULL ) {
1581 return (msg->
msgid() == MSG_CONFIG_STRING_VALUE);
1583 return i->is_string();
1592 if ( msg == NULL ) {
1595 unsigned int msgid = msg->
msgid();
1597 case MSG_CONFIG_FLOAT_VALUE:
1602 case MSG_CONFIG_UINT_VALUE:
1607 case MSG_CONFIG_INT_VALUE:
1612 case MSG_CONFIG_BOOL_VALUE:
1617 case MSG_CONFIG_STRING_VALUE:
1625 "iterator to value message");
1628 return i->is_default();
1637 if ( msg == NULL ) {
1640 if (msg->
msgid() == MSG_CONFIG_FLOAT_VALUE) {
1647 return i->get_float();
1656 if ( msg == NULL ) {
1659 if (msg->
msgid() == MSG_CONFIG_UINT_VALUE) {
1666 return i->get_int();
1675 if ( msg == NULL ) {
1678 if (msg->
msgid() == MSG_CONFIG_INT_VALUE) {
1685 return i->get_int();
1694 if ( msg == NULL ) {
1697 if (msg->
msgid() == MSG_CONFIG_BOOL_VALUE) {
1699 return (bm->
b != 0);
1704 return i->get_bool();
1713 if ( msg == NULL ) {
1716 if (msg->
msgid() == MSG_CONFIG_STRING_VALUE) {
1721 MSG_CONFIG_STRING_VALUE, msg->
msgid());
1724 return i->get_string();
1733 if ( msg == NULL ) {
1735 "invalid iterator");
1737 if (msg->
msgid() == MSG_CONFIG_STRING_VALUE) {
1740 }
else if (msg->
msgid() == MSG_CONFIG_BOOL_VALUE) {
1742 return (bm->
b != 0) ?
"true" :
"false";
1743 }
else if (msg->
msgid() == MSG_CONFIG_INT_VALUE) {
1746 }
else if (msg->
msgid() == MSG_CONFIG_UINT_VALUE) {
1749 }
else if (msg->
msgid() == MSG_CONFIG_FLOAT_VALUE) {
1753 throw Exception(
"NetConfValueIterator::get_as_string: unknown type");
1756 return i->get_as_string();
1765 if ( msg == NULL ) {
1768 if (msg->
msgid() == MSG_CONFIG_COMMENT_VALUE) {
1775 return i->get_comment();