Fix 'occurred' typo
[bpdyndnsd] / src / serviceholder.cpp
... / ...
CommitLineData
1/** @file
2 * @brief Serviceholder class implementation. This class holds Service and OldService lists.
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
9
10#include "serviceholder.hpp"
11
12#include <fstream>
13
14#include <boost/foreach.hpp>
15#include <boost/filesystem.hpp>
16
17#define OBJECT_FILE "/var/state/bpdyndnsd/bpdyndnsd.state"
18
19using namespace std;
20
21namespace fs = boost::filesystem;
22
23
24/**
25 * Default constructor.
26 */
27Serviceholder::Serviceholder()
28 :Log(new Logger)
29 ,IPAddrHelp()
30{
31}
32
33
34/**
35 * Constructor with Logger object.
36 */
37Serviceholder::Serviceholder(Logger::Ptr _log)
38 :Log(_log)
39 ,IPAddrHelp()
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/**
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.
55 */
56int Serviceholder::serialize_services() const
57{
58 // Put Services and OldServices into Serviceholder.
59 SerializeServiceContainer::Ptr service_container(new SerializeServiceContainer);
60
61 BOOST_FOREACH(const Service::Ptr &service, Services)
62 {
63 service_container->add_service(service);
64 }
65
66 time_t current_time = time(NULL);
67
68 BOOST_FOREACH(const Service::Ptr &service, OldServices)
69 {
70 if ( !service->get_last_updates().empty() &&
71 ( service->get_last_update_time() + ((time_t)service->get_update_interval()*60) ) >= current_time ) /*lint !e1793 */ // UpdateInterval timeout of service isn't expired.
72 service_container->add_service(service);
73 }
74
75 // Serialize SerializeServiceContainer and IPAddrHelper into file.
76 ofstream ofs(OBJECT_FILE);
77 if ( ofs.is_open() )
78 {
79 SerializeServiceContainer* _service_container = service_container.get();
80 IPAddrHelper* _ip_addr_helper = IPAddrHelp.get();
81 try
82 {
83 boost::archive::text_oarchive oa(ofs);
84 oa << _service_container << _ip_addr_helper;
85 }
86 catch( const boost::archive::archive_exception& e )
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;
104}
105
106
107/**
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;
127 IPAddrHelper* _ip_addr_helper;
128 try
129 {
130 boost::archive::text_iarchive ia(ifs);
131 ia >> _service_container >> _ip_addr_helper;
132 }
133 catch( const std::exception& e )
134 {
135 // There is a corrupted object file, continue without recovering old Services' state.
136 Log->print_exception_deserialize(e.what());
137 ifs.close();
138 return 0;
139 }
140
141 SerializeServiceContainer::Ptr service_container(_service_container);
142 IPAddrHelp = IPAddrHelper::Ptr(_ip_addr_helper);
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);
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());
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());
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());
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.
185 */
186void Serviceholder::add_service(Service::Ptr service)
187{
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();
208
209 IPAddrHelp.reset();
210}
211
212
213/**
214 * Getter for member Services
215 * @return List with shared Service pointers.
216 */
217std::list<Service::Ptr> Serviceholder::get_services() const
218{
219 return Services;
220}
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}