2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
20 Christian Herdtweck, Intra2net AG 2015
23 #include "dns/dnscache.h"
26 #include <logfunc.hpp>
27 #include <filefunc.hxx> // I2n::file_exists
28 #include <boost/bind.hpp>
29 #include <boost/date_time/posix_time/posix_time.hpp>
30 #include <boost/asio/placeholders.hpp>
31 #include <boost/serialization/serialization.hpp>
32 #include <boost/serialization/map.hpp>
33 #include <boost/serialization/string.hpp>
34 #include <boost/serialization/vector.hpp>
35 #include <boost/archive/xml_oarchive.hpp>
36 #include <boost/archive/xml_iarchive.hpp>
39 using boost::posix_time::seconds;
40 using I2n::Logger::GlobalLogger;
44 int SaveTimerSeconds = 60;
49 DnsCache::DnsCache(const IoServiceItem &io_serv,
50 const std::string &cache_file)
52 , SaveTimer( *io_serv )
53 , CacheFile( cache_file )
56 // load cache from file
57 load_from_cachefile();
60 (void) SaveTimer.expires_from_now( seconds( Config::SaveTimerSeconds ) );
61 SaveTimer.async_wait( bind( &DnsCache::schedule_save, this,
62 boost::asio::placeholders::error ) );
68 GlobalLogger.info() << "Dns Cache is being destructed";
70 // save one last time without re-scheduling the next save
78 void DnsCache::schedule_save(const boost::system::error_code &error)
80 // just in case: ensure SaveTimer is cancelled
81 SaveTimer.cancel(); // (will do nothing if already expired/cancelled)
83 if ( error == boost::asio::error::operation_aborted ) // cancelled
85 GlobalLogger.error() << "DNS Cache: SaveTimer was cancelled "
86 << "--> no save and no re-schedule of saving!";
91 GlobalLogger.error() << "DNS Cache: Received error " << error
92 << " in schedule_save "
93 << "--> no save now but re-schedule saving";
99 (void) SaveTimer.expires_from_now( seconds( Config::SaveTimerSeconds ) );
100 SaveTimer.async_wait( bind( &DnsCache::schedule_save, this,
101 boost::asio::placeholders::error ) );
104 void DnsCache::save_to_cachefile()
108 GlobalLogger.info() << "DNS Cache: skip saving because has not changed";
111 else if (CacheFile.empty())
113 GlobalLogger.warning()
114 << "DNS Cache: skip saving because file name empty!";
120 std::ofstream ofs( CacheFile.c_str() );
121 boost::archive::xml_oarchive oa(ofs);
122 oa << boost::serialization::make_nvp("DataCache", DataCache);
123 GlobalLogger.info() << "DNS Cache: saved to cache file " << CacheFile;
127 catch (std::exception &exc)
129 GlobalLogger.warning() << "Saving failed: " << exc.what();
134 void DnsCache::load_from_cachefile()
136 if (CacheFile.empty())
138 GlobalLogger.warning()
139 << "DNS Cache: cannot load because cache file name is empty!";
142 else if ( !I2n::file_exists(CacheFile) )
144 GlobalLogger.warning() << "DNS Cache: cannot load because cache file "
145 << CacheFile << " does not exist!";
150 HostAddressVec cache;
152 std::ifstream ifs( CacheFile.c_str() );
153 boost::archive::xml_iarchive ia(ifs);
155 ia >> boost::serialization::make_nvp("DataCache", cache);
156 GlobalLogger.info() << "DNS Cache: loaded from file " << CacheFile;
158 catch (boost::archive::archive_exception &exc)
160 GlobalLogger.warning() << "DNS Cache: archive exception loading from "
161 << CacheFile << ": " << exc.what();
163 catch (std::exception &exc)
165 GlobalLogger.warning() << "DNS Cache: exception while loading from "
166 << CacheFile << ": " << exc.what();
172 * in case the cached set is equal to the given new one, the old one is kept
174 * @returns true if changed cache; returns false if new_data is same as cache
176 void DnsCache::update(const std::string &hostname,
177 const HostAddressVec &new_data)
179 GlobalLogger.info() << "DNS Cache: update IPs for " << hostname
180 << " to " << new_data.size() << "-list";
181 DataCache[hostname] = new_data;
186 HostAddressVec& DnsCache::get_data(const std::string &hostname)
188 GlobalLogger.info() << "DNS Cache: request IPs for " << hostname
189 << " --> " << DataCache[hostname].size() << "-list";
190 return DataCache[hostname];
193 // (created using vim -- the world's best text editor)