Fix 'occurred' typo
[bpdyndnsd] / src / serviceholder.cpp
CommitLineData
6beab33f 1/** @file
e0080b78 2 * @brief Serviceholder class implementation. This class holds Service and OldService lists.
6beab33f
BS
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
9
4de6a9b8 10#include "serviceholder.hpp"
6beab33f 11
ca5d6889 12#include <fstream>
e0080b78 13
ca5d6889 14#include <boost/foreach.hpp>
e0080b78 15#include <boost/filesystem.hpp>
ca5d6889 16
04e3d681 17#define OBJECT_FILE "/var/state/bpdyndnsd/bpdyndnsd.state"
88a594e8 18
6beab33f
BS
19using namespace std;
20
ca5d6889
BS
21namespace fs = boost::filesystem;
22
6beab33f
BS
23
24/**
31af6a2e
BS
25 * Default constructor.
26 */
27Serviceholder::Serviceholder()
28 :Log(new Logger)
29 ,IPAddrHelp()
30{
31}
32
33
34/**
35 * Constructor with Logger object.
6beab33f 36 */
e0080b78 37Serviceholder::Serviceholder(Logger::Ptr _log)
9a0aff44 38 :Log(_log)
20399847 39 ,IPAddrHelp()
6beab33f
BS
40{
41}
42
43
44/**
45 * Default destructor. While serializing and deserializing we use boost/shared_ptr, the resources are managed correctly.
46 */
47Serviceholder::~Serviceholder()
48{
49}
50
51
52/**
e0080b78
BS
53 * This function serializes all Service objects in Services and OldServices (where the update Timeout isn't expired) into a specified file.
54 * @return 0 if all is fine, -1 if output file could not be opened for reading or error while serializing.
6beab33f 55 */
c730deea 56int Serviceholder::serialize_services() const
6beab33f 57{
e0080b78
BS
58 // Put Services and OldServices into Serviceholder.
59 SerializeServiceContainer::Ptr service_container(new SerializeServiceContainer);
60
c730deea 61 BOOST_FOREACH(const Service::Ptr &service, Services)
e0080b78
BS
62 {
63 service_container->add_service(service);
64 }
65
62df5f33 66 time_t current_time = time(NULL);
e0080b78 67
c730deea 68 BOOST_FOREACH(const Service::Ptr &service, OldServices)
e0080b78 69 {
623751fb 70 if ( !service->get_last_updates().empty() &&
4553e833 71 ( service->get_last_update_time() + ((time_t)service->get_update_interval()*60) ) >= current_time ) /*lint !e1793 */ // UpdateInterval timeout of service isn't expired.
e0080b78
BS
72 service_container->add_service(service);
73 }
74
20399847 75 // Serialize SerializeServiceContainer and IPAddrHelper into file.
e0080b78
BS
76 ofstream ofs(OBJECT_FILE);
77 if ( ofs.is_open() )
78 {
79 SerializeServiceContainer* _service_container = service_container.get();
20399847 80 IPAddrHelper* _ip_addr_helper = IPAddrHelp.get();
e0080b78
BS
81 try
82 {
83 boost::archive::text_oarchive oa(ofs);
20399847 84 oa << _service_container << _ip_addr_helper;
e0080b78 85 }
08a5a621 86 catch( const boost::archive::archive_exception& e )
e0080b78
BS
87 {
88 Log->print_exception_serialize(e.what());
89 ofs.close();
90 return -1;
91 }
92
93 ofs.close();
94 }
95 else
96 {
97 Log->print_error_opening_rw(OBJECT_FILE);
98 return -1;
99 }
100
101 Log->print_serialized_objects_success();
102
103 return 0;
6beab33f
BS
104}
105
106
107/**
e0080b78
BS
108 * This function de-serializes the SerializeServiceContainer (containing Services) from the object file.
109 * @return 0 if all is fine, -1 if object file couldn't be opened for reading or error while de-serializing.
110 */
111int Serviceholder::deserialize_services()
112{
113 // test if OBJECT_FILE exists
114 fs::path object_file = fs::system_complete(fs::path(OBJECT_FILE));
115 if ( !fs::exists(object_file) )
116 {
117 // There is no object file, possibly first program start, continue without recovering old Services' state.
118 Log->print_no_object_file(OBJECT_FILE);
119 return 0;
120 }
121
122 ifstream ifs(OBJECT_FILE);
123 if ( ifs.is_open() )
124 {
125 // deserialize SerializeServiceContainer
126 SerializeServiceContainer* _service_container;
20399847 127 IPAddrHelper* _ip_addr_helper;
e0080b78
BS
128 try
129 {
130 boost::archive::text_iarchive ia(ifs);
20399847 131 ia >> _service_container >> _ip_addr_helper;
e0080b78 132 }
b6171a3f 133 catch( const std::exception& e )
e0080b78 134 {
6741febc 135 // There is a corrupted object file, continue without recovering old Services' state.
e0080b78
BS
136 Log->print_exception_deserialize(e.what());
137 ifs.close();
6741febc 138 return 0;
e0080b78 139 }
6741febc 140
e0080b78 141 SerializeServiceContainer::Ptr service_container(_service_container);
c3c84086 142 IPAddrHelp = IPAddrHelper::Ptr(_ip_addr_helper);
e0080b78
BS
143 ifs.close();
144
145 // Get the list of old Services from de-serialized SerializeServiceContainer object.
146 list<Service::Ptr> _old_services = service_container->get_containing_services();
147
148 // Put all de-serialized Services into OldServices member and
149 // compare new Services (generated from config file and cmd) with old Services (de-serialized from object file)
150 // if identical Service was found, adopt the value from old Service to recover Services' state.
151 BOOST_FOREACH(Service::Ptr &old_service, _old_services)
152 {
153 OldServices.push_back(old_service);
7335d7a7 154 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());
e0080b78
BS
155 BOOST_FOREACH(Service::Ptr &service, Services)
156 {
157 if ( *service == *old_service )
158 {
159 service->set_last_updates(old_service->get_last_updates());
160 service->set_actual_ip(old_service->get_actual_ip());
7335d7a7
BS
161 if ( old_service->get_activated() )
162 service->set_activated();
163
164 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());
e0080b78
BS
165 // We have adopted the values of the old_service. Just set lastupdated and timeout to 0, so this old_service wont be serialized.
166 old_service->set_update_interval(0);
167 }
168 }
169 }
170 Log->print_deserialized_objects_success();
171 }
172 else
173 {
174 Log->print_error_opening_r(OBJECT_FILE);
175 return -1;
176 }
177
178 return 0;
179}
180
181
182/**
183 * Add service to internal service list.
184 * @param service Shared pointer to service object.
6beab33f 185 */
88a594e8 186void Serviceholder::add_service(Service::Ptr service)
6beab33f 187{
e0080b78
BS
188 Services.push_back(service);
189}
190
191
192/**
193 * Resets all shared Service pointers and clears the Services list.
194 */
195void Serviceholder::delete_services()
196{
197 BOOST_FOREACH( Service::Ptr &service, Services )
198 {
199 service.reset();
200 }
201 Services.clear();
202
203 BOOST_FOREACH( Service::Ptr &service, OldServices )
204 {
205 service.reset();
206 }
207 OldServices.clear();
20399847
BS
208
209 IPAddrHelp.reset();
6beab33f
BS
210}
211
212
213/**
e0080b78
BS
214 * Getter for member Services
215 * @return List with shared Service pointers.
6beab33f 216 */
e0080b78 217std::list<Service::Ptr> Serviceholder::get_services() const
6beab33f 218{
e0080b78 219 return Services;
6beab33f 220}
20399847
BS
221
222
223/**
224 * Set member IPAddrHelp
225 * @param _ip_addr_helper The IPAddrHelper.
226 */
227void Serviceholder::set_ip_addr_helper(IPAddrHelper::Ptr _ip_addr_helper)
228{
229 IPAddrHelp = _ip_addr_helper;
230}
231
232
233/**
234 * Get member IPAddrHelp
235 * @return IPAddrHelp
236 */
237IPAddrHelper::Ptr Serviceholder::get_ip_addr_helper() const
238{
239 return IPAddrHelp;
240}