/** @file * @brief Serviceholder class implementation. This class holds Service and OldService lists. * * * * @copyright Intra2net AG * @license GPLv2 */ #include "serviceholder.hpp" #include #include #include #define OBJECT_FILE "/var/state/bpdyndnsd/bpdyndnsd.state" using namespace std; namespace fs = boost::filesystem; /** * Default constructor. */ Serviceholder::Serviceholder() :Log(new Logger) ,IPAddrHelp() { } /** * Constructor with Logger object. */ Serviceholder::Serviceholder(Logger::Ptr _log) :Log(_log) ,IPAddrHelp() { } /** * Default destructor. While serializing and deserializing we use boost/shared_ptr, the resources are managed correctly. */ Serviceholder::~Serviceholder() { } /** * 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 Serviceholder::serialize_services() const { // Put Services and OldServices into Serviceholder. SerializeServiceContainer::Ptr service_container(new SerializeServiceContainer); BOOST_FOREACH(const Service::Ptr &service, Services) { service_container->add_service(service); } time_t current_time = time(NULL); BOOST_FOREACH(const Service::Ptr &service, OldServices) { if ( !service->get_last_updates().empty() && ( service->get_last_update_time() + ((time_t)service->get_update_interval()*60) ) >= current_time ) /*lint !e1793 */ // UpdateInterval timeout of service isn't expired. service_container->add_service(service); } // Serialize SerializeServiceContainer and IPAddrHelper into file. ofstream ofs(OBJECT_FILE); if ( ofs.is_open() ) { SerializeServiceContainer* _service_container = service_container.get(); IPAddrHelper* _ip_addr_helper = IPAddrHelp.get(); try { boost::archive::text_oarchive oa(ofs); oa << _service_container << _ip_addr_helper; } catch( const 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 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; IPAddrHelper* _ip_addr_helper; try { boost::archive::text_iarchive ia(ifs); ia >> _service_container >> _ip_addr_helper; } catch( const std::exception& e ) { // There is a corrupted object file, continue without recovering old Services' state. Log->print_exception_deserialize(e.what()); ifs.close(); return 0; } SerializeServiceContainer::Ptr service_container(_service_container); IPAddrHelp = IPAddrHelper::Ptr(_ip_addr_helper); ifs.close(); // Get the list of old Services from de-serialized SerializeServiceContainer object. list _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_max_equal_updates_in_succession(), old_service->get_dns_cache_ttl() , old_service->get_actual_ip(), old_service->get_last_updates(), old_service->get_activated()); 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()); if ( old_service->get_activated() ) service->set_activated(); 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_max_equal_updates_in_succession(), service->get_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates(), service->get_activated()); // 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) { 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(); IPAddrHelp.reset(); } /** * Getter for member Services * @return List with shared Service pointers. */ std::list Serviceholder::get_services() const { return Services; } /** * Set member IPAddrHelp * @param _ip_addr_helper The IPAddrHelper. */ void Serviceholder::set_ip_addr_helper(IPAddrHelper::Ptr _ip_addr_helper) { IPAddrHelp = _ip_addr_helper; } /** * Get member IPAddrHelp * @return IPAddrHelp */ IPAddrHelper::Ptr Serviceholder::get_ip_addr_helper() const { return IPAddrHelp; }