#include "config.h"
-#include "serviceholder.h"
#include "dhs.h"
#include "ods.h"
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
-#include <boost/archive/text_oarchive.hpp>
-#include <boost/archive/text_iarchive.hpp>
-#include <boost/archive/archive_exception.hpp>
-#include <boost/serialization/export.hpp>
-#include <boost/serialization/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>
-// Following boost macros are needed for serialization of derived classes through a base class pointer (Service *).
-BOOST_CLASS_EXPORT_GUID(ODS, "ODS")
-BOOST_CLASS_EXPORT_GUID(DHS, "DHS")
+
namespace po = boost::program_options;
namespace fs = boost::filesystem;
/**
* Default Constructor. Available command line and config file options with their default values are defined here.
*/
-Config::Config(Logger::Ptr _log)
- : Log(new Logger)
- , DaemonMode(false)
- , Loglevel(0)
+Config::Config(Logger::Ptr _log, Serviceholder::Ptr _serviceholder)
+ : DaemonMode(false)
, Syslog(false)
- , ConfigPath("/etc/bpdyndnsd")
, EnableIPv6(false)
- , WebcheckIpUrl("")
- , WebcheckIpUrlAlt("")
+ , Loglevel(0)
+ , ConfigPath("/etc/bpdyndnsd")
{
// initialize Logger
Log = _log;
+ // initialize Serviceholder
+ ServiceHolder = _serviceholder;
+
// Available service description config options
po::options_description opt_desc_service("Service description options");
opt_desc_service.add_options()
/**
- * This function serializes all Service objects in Services and OldServices (where the update Timeout isn't expired) into a specified file.
- * @return 0 if all is fine, -1 if output file could not be opened for reading or error while serializing.
- */
-int Config::serialize_services()
-{
- // Put Services and OldServices into Serviceholder.
- Serviceholder::Ptr service_holder(new Serviceholder());
-
- BOOST_FOREACH(Service::Ptr &service, Services)
- {
- service_holder->add_service(service);
- }
-
- int current_time = time(NULL);
-
- BOOST_FOREACH(Service::Ptr &service, OldServices)
- {
- if ( ( service->get_last_updates()->front() + (service->get_update_interval()*60) ) >= current_time ) // UpdateInterval timeout of service isn't expired.
- service_holder->add_service(service);
- }
-
- // Serialize Serviceholder into file.
- ofstream ofs(OBJECT_FILE);
- if ( ofs.is_open() )
- {
- Serviceholder* _service_holder = service_holder.get();
- try
- {
- boost::archive::text_oarchive oa(ofs);
- oa << _service_holder;
- }
- catch( boost::archive::archive_exception e )
- {
- Log->print_exception_serialize(e.what());
- ofs.close();
- return -1;
- }
-
- ofs.close();
- }
- else
- {
- Log->print_error_opening_rw(OBJECT_FILE);
- return -1;
- }
-
- Log->print_serialized_objects_success();
-
- return 0;
-}
-
-
-/**
- * This function de-serializes the Serviceholder (containing Services) from the object file.
- * @return 0 if all is fine, -1 if object file couldn't be opened for reading or error while de-serializing.
- */
-int Config::deserialize_services()
-{
- // test if OBJECT_FILE exists
- fs::path object_file = fs::system_complete(fs::path(OBJECT_FILE));
- if ( !fs::exists(object_file) )
- {
- // There is no object file, possibly first program start, continue without recovering old Services' state.
- Log->print_no_object_file(OBJECT_FILE);
- return 0;
- }
-
- ifstream ifs(OBJECT_FILE);
- if ( ifs.is_open() )
- {
- // deserialize Serviceholder
- Serviceholder* _service_holder;
- try
- {
- boost::archive::text_iarchive ia(ifs);
- ia >> _service_holder; // ends up in default constructor call for Serviceholder
- }
- catch( boost::archive::archive_exception e )
- {
- Log->print_exception_deserialize(e.what());
- ifs.close();
- return -1;
- }
- Serviceholder::Ptr service_holder(_service_holder);
- ifs.close();
-
- // Get the list of old Services from de-serialized Serviceholder object.
- list<Service::Ptr> _old_services = service_holder->get_hold_services();
-
- // Put all de-serialized Services into OldServices member and
- // compare new Services (generated from config file and cmd) with old Services (de-serialized from object file)
- // if identical Service was found, adopt the value from old Service to recover Services' state.
- BOOST_FOREACH(Service::Ptr &old_service, _old_services)
- {
- OldServices.push_back(old_service);
- Log->print_service_object("Deserialized following Service object:", old_service->get_protocol(), old_service->get_hostname(), old_service->get_login() ,old_service->get_password(), old_service->get_update_interval(), old_service->get_max_updates_within_interval(), old_service->get_actual_ip(), old_service->get_last_updates());
- BOOST_FOREACH(Service::Ptr &service, Services)
- {
- if ( *service == *old_service )
- {
- service->set_last_updates(old_service->get_last_updates());
- service->set_actual_ip(old_service->get_actual_ip());
- Log->print_service_object("New Service object with adopted values:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
- // We have adopted the values of the old_service. Just set lastupdated and timeout to 0, so this old_service wont be serialized.
- old_service->set_update_interval(0);
- }
- }
- }
- Log->print_deserialized_objects_success();
- }
- else
- {
- Log->print_error_opening_r(OBJECT_FILE);
- return -1;
- }
-
- return 0;
-}
-
-
-/**
* Parses the command line arguments and does the needed actions.
* @param argc Command line argument number given to main.
* @param argv[] Pointer to command line argument array given to main.
Service::Ptr service = create_service(protocol,host,login,password,update_interval,max_updates_within_interval);
if ( service )
- Services.push_back(service);
+ {
+ ServiceHolder->add_service(service);
+ Log->print_service_object("New Service object from command line options:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
+ }
else
return -1;
}
Service::Ptr service = create_service(protocol,host,login,password,update_interval,max_updates_within_interval);
if ( service )
{
- Services.push_back(service);
+ ServiceHolder->add_service(service);
Log->print_service_object("New Service object from config:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
}
+ else
+ return -1;
}
}
catch ( po::unknown_option e )
/**
- * Getter method for Service list member.
- * @return Pointer to a list of Service's.
- */
-list<Service::Ptr> Config::get_services() const
-{
- return this->Services;
-}
-
-
-/**
* Getter method for member OptDescCmd.
* @return options_description*.
*/
/**
- * Resets all shared Service pointers and clears the Services list.
- */
-void Config::delete_services()
-{
- BOOST_FOREACH( Service::Ptr &service, Services )
- {
- service.reset();
- }
- Services.clear();
-
- BOOST_FOREACH( Service::Ptr &service, OldServices )
- {
- service.reset();
- }
- OldServices.clear();
-}
-
-
-/**
* Deletes the map with the previously parsed options.
* This is needed in case we reload the config and don't want the old cmd options to overwrite new config file options.
*/
#include <string>
-#include "service.h"
#include "logger.h"
+#include "serviceholder.h"
#include <boost/program_options.hpp>
#include <boost/shared_ptr.hpp>
Options_descriptionPtr OptDescCmd;
Options_descriptionPtr OptDescConfMain;
Options_descriptionPtr OptDescConfService;
-
boost::program_options::variables_map VariablesMap;
- std::list<Service::Ptr> Services; // Represents all active Services.
- std::list<Service::Ptr> OldServices; // Represents all old Services where the timeout isn't expired (in case the same Service is redefined).
-
Logger::Ptr Log;
+ Serviceholder::Ptr ServiceHolder;
bool DaemonMode;
- int Loglevel;
bool Syslog;
- std::string ConfigPath;
bool EnableIPv6;
+ int Loglevel;
+ std::string ConfigPath;
std::string WebcheckIpUrl;
std::string WebcheckIpUrlAlt;
typedef boost::shared_ptr<Config> Ptr;
- Config(Logger::Ptr);
+ Config(Logger::Ptr, Serviceholder::Ptr);
~Config();
- int serialize_services();
-
- int deserialize_services();
-
int parse_cmd_line(int, char **);
int load_config_from_files();
- std::list<Service::Ptr> get_services() const;
-
Options_descriptionPtr get_opt_desc_cmd() const;
Options_descriptionPtr get_opt_desc_conf_main() const;
bool get_daemon_mode() const;
- void delete_services();
-
int get_loglevel() const;
bool get_syslog() const;
#include "serviceholder.cpp"
#include "updater.cpp"
#include "iphelper.cpp"
+#include "serializeservicecontainer.cpp"
using namespace std;
// unfortunately we can't call serialize_services in any destructor
// cause some singleton are already destroyed !?!
- if ( updater->get_config()->serialize_services() != 0 )
+ if ( updater->get_service_holder()->serialize_services() != 0 )
{
updater.reset();
exit(-1);
/**
* Initialize the signals we handle.
+ * @return 0 if all is fine, -1 on error.
*/
int init_signals()
{
// Serialize services to save their actual state.
- if ( updater->get_config()->serialize_services() != 0 )
+ if ( updater->get_service_holder()->serialize_services() != 0 )
return -1;
return 0;
--- /dev/null
+/** @file
+ * @brief SerializeServiceContainer class implementation. This class contains Service objects in a list for serialization.
+ *
+ *
+ *
+ * @copyright Intra2net AG
+ * @license GPLv2
+*/
+
+#include "serializeservicecontainer.h"
+
+#include <boost/serialization/list.hpp>
+
+SerializeServiceContainer::SerializeServiceContainer()
+{
+}
+
+
+SerializeServiceContainer::~SerializeServiceContainer()
+{
+}
+
+/**
+ * Serialize function needed by boost/serialization to define which members should be stored as the object state.
+ * In this case the STL list of Service pointers will be serialized.
+ * @param ar Archive
+ * @param version Version
+ */
+template<class Archive>
+void SerializeServiceContainer::serialize(Archive & ar, const unsigned int version)
+{
+ ar & ContainingServices;
+}
+
+
+void SerializeServiceContainer::add_service(Service::Ptr service)
+{
+ ContainingServices.push_back(service);
+}
+
+
+std::list<Service::Ptr> SerializeServiceContainer::get_containing_services() const
+{
+ return ContainingServices;
+}
--- /dev/null
+/** @file
+ * @brief SerializeServiceContainer class header. This class holds Service objects in a list for serialization.
+ *
+ *
+ *
+ * @copyright Intra2net AG
+ * @license GPLv2
+*/
+
+#ifndef SERIALIZESERVICECONTAINER_H
+#define SERIALIZESERVICECONTAINER_H
+
+#include <list>
+
+#include "service.h"
+#include "logger.h"
+
+#include <boost/serialization/array.hpp>
+#include <boost/shared_ptr.hpp>
+
+class SerializeServiceContainer
+{
+
+private:
+
+ std::list<Service::Ptr> ContainingServices;
+
+ friend class boost::serialization::access;
+ template<class Archive>
+ void serialize(Archive &, const unsigned int);
+
+public:
+
+ typedef boost::shared_ptr<SerializeServiceContainer> Ptr;
+
+ SerializeServiceContainer();
+
+ ~SerializeServiceContainer();
+
+ void add_service(Service::Ptr service);
+
+ std::list<Service::Ptr> get_containing_services() const;
+
+};
+
+#endif
/** @file
- * @brief Serviceholder class implementation. This class holds Service objects in a list for serialization.
+ * @brief Serviceholder class implementation. This class holds Service and OldService lists.
*
*
*
#include "serviceholder.h"
-#include <boost/serialization/list.hpp>
+#include "serializeservicecontainer.h"
+
+#include <boost/filesystem.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/archive_exception.hpp>
+#include <boost/serialization/export.hpp>
+#include <boost/serialization/shared_ptr.hpp>
using namespace std;
/**
- * Default constructor. Invoked on serialization and deserialization.
+ * Default constructor with Logger object.
*/
-Serviceholder::Serviceholder()
+Serviceholder::Serviceholder(Logger::Ptr _log)
{
+ Log = _log;
}
/**
- * Serialize function needed by boost/serialization to define which members should be stored as the object state.
- * In this case the STL list of Service pointers will be serialized.
- * @param ar Archive
- * @param version Version
+ * This function serializes all Service objects in Services and OldServices (where the update Timeout isn't expired) into a specified file.
+ * @return 0 if all is fine, -1 if output file could not be opened for reading or error while serializing.
*/
-template<class Archive>
-void Serviceholder::serialize(Archive & ar, const unsigned int version)
+int Serviceholder::serialize_services()
{
- ar & HoldServices;
+ // Put Services and OldServices into Serviceholder.
+ SerializeServiceContainer::Ptr service_container(new SerializeServiceContainer);
+
+ BOOST_FOREACH(Service::Ptr &service, Services)
+ {
+ service_container->add_service(service);
+ }
+
+ int current_time = time(NULL);
+
+ BOOST_FOREACH(Service::Ptr &service, OldServices)
+ {
+ if ( ( service->get_last_updates()->front() + (service->get_update_interval()*60) ) >= current_time ) // UpdateInterval timeout of service isn't expired.
+ service_container->add_service(service);
+ }
+
+ // Serialize Serviceholder into file.
+ ofstream ofs(OBJECT_FILE);
+ if ( ofs.is_open() )
+ {
+ SerializeServiceContainer* _service_container = service_container.get();
+ try
+ {
+ boost::archive::text_oarchive oa(ofs);
+ oa << _service_container;
+ }
+ catch( boost::archive::archive_exception e )
+ {
+ Log->print_exception_serialize(e.what());
+ ofs.close();
+ return -1;
+ }
+
+ ofs.close();
+ }
+ else
+ {
+ Log->print_error_opening_rw(OBJECT_FILE);
+ return -1;
+ }
+
+ Log->print_serialized_objects_success();
+
+ return 0;
}
/**
- * Add Service * to internal list.
- * @param service Pointer to Service object.
+ * This function de-serializes the SerializeServiceContainer (containing Services) from the object file.
+ * @return 0 if all is fine, -1 if object file couldn't be opened for reading or error while de-serializing.
+ */
+int Serviceholder::deserialize_services()
+{
+ // test if OBJECT_FILE exists
+ fs::path object_file = fs::system_complete(fs::path(OBJECT_FILE));
+ if ( !fs::exists(object_file) )
+ {
+ // There is no object file, possibly first program start, continue without recovering old Services' state.
+ Log->print_no_object_file(OBJECT_FILE);
+ return 0;
+ }
+
+ ifstream ifs(OBJECT_FILE);
+ if ( ifs.is_open() )
+ {
+ // deserialize SerializeServiceContainer
+ SerializeServiceContainer* _service_container;
+ try
+ {
+ boost::archive::text_iarchive ia(ifs);
+ ia >> _service_container;
+ }
+ catch( boost::archive::archive_exception e )
+ {
+ Log->print_exception_deserialize(e.what());
+ ifs.close();
+ return -1;
+ }
+ SerializeServiceContainer::Ptr service_container(_service_container);
+ ifs.close();
+
+ // Get the list of old Services from de-serialized SerializeServiceContainer object.
+ list<Service::Ptr> _old_services = service_container->get_containing_services();
+
+ // Put all de-serialized Services into OldServices member and
+ // compare new Services (generated from config file and cmd) with old Services (de-serialized from object file)
+ // if identical Service was found, adopt the value from old Service to recover Services' state.
+ BOOST_FOREACH(Service::Ptr &old_service, _old_services)
+ {
+ OldServices.push_back(old_service);
+ Log->print_service_object("Deserialized following Service object:", old_service->get_protocol(), old_service->get_hostname(), old_service->get_login() ,old_service->get_password(), old_service->get_update_interval(), old_service->get_max_updates_within_interval(), old_service->get_actual_ip(), old_service->get_last_updates());
+ BOOST_FOREACH(Service::Ptr &service, Services)
+ {
+ if ( *service == *old_service )
+ {
+ service->set_last_updates(old_service->get_last_updates());
+ service->set_actual_ip(old_service->get_actual_ip());
+ Log->print_service_object("New Service object with adopted values:", service->get_protocol(), service->get_hostname(), service->get_login() ,service->get_password(), service->get_update_interval(), service->get_max_updates_within_interval(), service->get_actual_ip(), service->get_last_updates());
+ // We have adopted the values of the old_service. Just set lastupdated and timeout to 0, so this old_service wont be serialized.
+ old_service->set_update_interval(0);
+ }
+ }
+ }
+ Log->print_deserialized_objects_success();
+ }
+ else
+ {
+ Log->print_error_opening_r(OBJECT_FILE);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Add service to internal service list.
+ * @param service Shared pointer to service object.
*/
void Serviceholder::add_service(Service::Ptr service)
{
- HoldServices.push_back(service);
+ Services.push_back(service);
+}
+
+
+/**
+ * Resets all shared Service pointers and clears the Services list.
+ */
+void Serviceholder::delete_services()
+{
+ BOOST_FOREACH( Service::Ptr &service, Services )
+ {
+ service.reset();
+ }
+ Services.clear();
+
+ BOOST_FOREACH( Service::Ptr &service, OldServices )
+ {
+ service.reset();
+ }
+ OldServices.clear();
}
/**
- * Needed after deserialization to get the valid list of Service* back.
- * @return The list of Service*.
+ * Getter for member Services
+ * @return List with shared Service pointers.
*/
-std::list<Service::Ptr> Serviceholder::get_hold_services() const
+std::list<Service::Ptr> Serviceholder::get_services() const
{
- return HoldServices;
+ return Services;
}
/** @file
- * @brief Serviceholder class header. This class holds Service objects in a list for serialization.
+ * @brief Serviceholder class header. This class holds Service and OldService lists.
*
*
*
#include "service.h"
#include "logger.h"
-#include <boost/serialization/array.hpp>
#include <boost/shared_ptr.hpp>
class Serviceholder
private:
- std::list<Service::Ptr> HoldServices;
+ Logger::Ptr Log;
- friend class boost::serialization::access;
- template<class Archive>
- void serialize(Archive &, const unsigned int);
+ std::list<Service::Ptr> OldServices; // Represents all old Services where the timeout isn't expired (in case the same Service is redefined).
+ std::list<Service::Ptr> Services; // Represents all active Services.
public:
typedef boost::shared_ptr<Serviceholder> Ptr;
- Serviceholder();
-
Serviceholder(Logger::Ptr);
~Serviceholder();
- void add_service(Service::Ptr);
+ void add_service(Service::Ptr service);
+
+ int deserialize_services();
+
+ int serialize_services();
+
+ void delete_services();
- std::list<Service::Ptr> get_hold_services() const;
+ std::list<Service::Ptr> get_services() const;
};
#endif
#include "updater.h"
+#include "serviceholder.h"
+#include "dhs.h"
+#include "ods.h"
+
#include <boost/foreach.hpp>
+
+// Following boost macros are needed for serialization of derived classes through a base class pointer (Service *).
+BOOST_CLASS_EXPORT_GUID(ODS, "ODS")
+BOOST_CLASS_EXPORT_GUID(DHS, "DHS")
+
+namespace fs = boost::filesystem;
+
using namespace std;
/**
Log = _log;
_log.reset();
+ // initialize Serviceholder
+ Serviceholder::Ptr _serviceholder(new Serviceholder(Log));
+ ServiceHolder = _serviceholder;
+ _serviceholder.reset();
+
// initialize Config
- Config::Ptr _config(new Config(Log));
+ Config::Ptr _config(new Config(Log,ServiceHolder));
Conf = _config;
_config.reset();
}
int Updater::init_config_from_cmd(int argc, char *argv[])
{
// Load the command line parameters
- if( Conf->parse_cmd_line( argc, argv ) != 0)
+ if( Conf->parse_cmd_line( argc, argv) != 0)
return -1;
// If we have loaded the cmd options we need to init the log facility immediately in case debugging is enabled from cmd.
init_log_facility();
// Here we are. All Service Objects should be initialized, so it is time to deserialize the old service objects and compare them.
- if ( Conf->deserialize_services() != 0 )
+ if ( ServiceHolder->deserialize_services() != 0 )
return -1;
// successful loaded
int Updater::reload_config()
{
// serialize all service objects
- if ( Conf->serialize_services() != 0 )
+ if ( ServiceHolder->serialize_services() != 0 )
return -1;
// delete all service objects
- Conf->delete_services();
+ ServiceHolder->delete_services();
// delete the actual Variables_map, perhaps with old cmd options which would overwrite new config file options.
Conf->delete_variables_map();
*/
void Updater::update_services()
{
- list<Service::Ptr> services = this->Conf->get_services();
+ list<Service::Ptr> services = ServiceHolder->get_services();
string ip = IPHelp->get_actual_ip();
}
}
}
+
+
+/**
+ * Getter for member ServiceHolder.
+ * @return ServiceHolder
+ */
+Serviceholder::Ptr Updater::get_service_holder() const
+{
+ return ServiceHolder;
+}
#define UPDATER_H
#include "config.h"
-#include "logger.h"
#include "iphelper.h"
+#include "logger.h"
+#include "serviceholder.h"
#include <boost/shared_ptr.hpp>
private:
Config::Ptr Conf;
- Logger::Ptr Log;
IPHelper::Ptr IPHelp;
+ Logger::Ptr Log;
+ Serviceholder::Ptr ServiceHolder;
public:
Logger::Ptr get_logger() const;
+ Serviceholder::Ptr get_service_holder() const;
+
int reload_config();
void init_log_facility();