Make sure get_last_updates() contains atleast one entry before calling .front()
[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
TJ
70 if ( !service->get_last_updates().empty() &&
71 ( service->get_last_updates().front() + ((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 }
08a5a621 133 catch( const boost::archive::archive_exception& e )
e0080b78
BS
134 {
135 Log->print_exception_deserialize(e.what());
136 ifs.close();
137 return -1;
138 }
139 SerializeServiceContainer::Ptr service_container(_service_container);
c3c84086 140 IPAddrHelp = IPAddrHelper::Ptr(_ip_addr_helper);
e0080b78
BS
141 ifs.close();
142
143 // Get the list of old Services from de-serialized SerializeServiceContainer object.
144 list<Service::Ptr> _old_services = service_container->get_containing_services();
145
146 // Put all de-serialized Services into OldServices member and
147 // compare new Services (generated from config file and cmd) with old Services (de-serialized from object file)
148 // if identical Service was found, adopt the value from old Service to recover Services' state.
149 BOOST_FOREACH(Service::Ptr &old_service, _old_services)
150 {
151 OldServices.push_back(old_service);
d5a516ba 152 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_dns_cache_ttl() , old_service->get_actual_ip(), old_service->get_last_updates());
e0080b78
BS
153 BOOST_FOREACH(Service::Ptr &service, Services)
154 {
155 if ( *service == *old_service )
156 {
157 service->set_last_updates(old_service->get_last_updates());
158 service->set_actual_ip(old_service->get_actual_ip());
d5a516ba 159 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_dns_cache_ttl() , service->get_actual_ip(), service->get_last_updates());
e0080b78
BS
160 // We have adopted the values of the old_service. Just set lastupdated and timeout to 0, so this old_service wont be serialized.
161 old_service->set_update_interval(0);
162 }
163 }
164 }
165 Log->print_deserialized_objects_success();
166 }
167 else
168 {
169 Log->print_error_opening_r(OBJECT_FILE);
170 return -1;
171 }
172
173 return 0;
174}
175
176
177/**
178 * Add service to internal service list.
179 * @param service Shared pointer to service object.
6beab33f 180 */
88a594e8 181void Serviceholder::add_service(Service::Ptr service)
6beab33f 182{
e0080b78
BS
183 Services.push_back(service);
184}
185
186
187/**
188 * Resets all shared Service pointers and clears the Services list.
189 */
190void Serviceholder::delete_services()
191{
192 BOOST_FOREACH( Service::Ptr &service, Services )
193 {
194 service.reset();
195 }
196 Services.clear();
197
198 BOOST_FOREACH( Service::Ptr &service, OldServices )
199 {
200 service.reset();
201 }
202 OldServices.clear();
20399847
BS
203
204 IPAddrHelp.reset();
6beab33f
BS
205}
206
207
208/**
e0080b78
BS
209 * Getter for member Services
210 * @return List with shared Service pointers.
6beab33f 211 */
e0080b78 212std::list<Service::Ptr> Serviceholder::get_services() const
6beab33f 213{
e0080b78 214 return Services;
6beab33f 215}
20399847
BS
216
217
218/**
219 * Set member IPAddrHelp
220 * @param _ip_addr_helper The IPAddrHelper.
221 */
222void Serviceholder::set_ip_addr_helper(IPAddrHelper::Ptr _ip_addr_helper)
223{
224 IPAddrHelp = _ip_addr_helper;
225}
226
227
228/**
229 * Get member IPAddrHelp
230 * @return IPAddrHelp
231 */
232IPAddrHelper::Ptr Serviceholder::get_ip_addr_helper() const
233{
234 return IPAddrHelp;
235}