Commit | Line | Data |
---|---|---|
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 |
19 | using namespace std; |
20 | ||
ca5d6889 BS |
21 | namespace fs = boost::filesystem; |
22 | ||
6beab33f BS |
23 | |
24 | /** | |
31af6a2e BS |
25 | * Default constructor. |
26 | */ | |
27 | Serviceholder::Serviceholder() | |
28 | :Log(new Logger) | |
29 | ,IPAddrHelp() | |
30 | { | |
31 | } | |
32 | ||
33 | ||
34 | /** | |
35 | * Constructor with Logger object. | |
6beab33f | 36 | */ |
e0080b78 | 37 | Serviceholder::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 | */ | |
47 | Serviceholder::~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 | 56 | int 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 | */ | |
111 | int 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 | 186 | void 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 | */ | |
195 | void 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 | 217 | std::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 | */ | |
227 | void 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 | */ | |
237 | IPAddrHelper::Ptr Serviceholder::get_ip_addr_helper() const | |
238 | { | |
239 | return IPAddrHelp; | |
240 | } |