IBR-DTNSuite  0.8
ibrdtn/ibrdtn/utils/Clock.cpp
Go to the documentation of this file.
00001 /*
00002  * Clock.cpp
00003  *
00004  *  Created on: 24.06.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrdtn/utils/Clock.h"
00009 #include "ibrdtn/data/AgeBlock.h"
00010 
00011 #include <ibrcommon/Logger.h>
00012 
00013 namespace dtn
00014 {
00015         namespace utils
00016         {
00017                 int Clock::timezone = 0;
00018                 float Clock::quality = 0;
00019                 bool Clock::badclock = false;
00020 
00021                 struct timeval Clock::_offset;
00022                 bool Clock::_offset_init = false;
00023 
00024                 bool Clock::modify_clock = false;
00025 
00029                 u_int32_t Clock::TIMEVAL_CONVERSION = 946684800;
00030 
00031                 Clock::Clock()
00032                 {
00033                 }
00034 
00035                 Clock::~Clock()
00036                 {
00037                 }
00038 
00039                 size_t Clock::getExpireTime(const dtn::data::Bundle &b)
00040                 {
00041                         if ((b._timestamp == 0) || dtn::utils::Clock::badclock)
00042                         {
00043                                 // use the AgeBlock to verify the age
00044                                 try {
00045                                         const dtn::data::AgeBlock &agebl = b.getBlock<const dtn::data::AgeBlock>();
00046                                         size_t seconds_left = b._lifetime - agebl.getSeconds();
00047                                         return getTime() + seconds_left;
00048                                 } catch (const dtn::data::Bundle::NoSuchBlockFoundException&) { };
00049                         }
00050 
00051                         return __getExpireTime(b._timestamp, b._lifetime);
00052                 }
00053 
00054                 size_t Clock::getExpireTime(size_t timestamp, size_t lifetime)
00055                 {
00056                         return __getExpireTime(timestamp, lifetime);
00057                 }
00058 
00059                 size_t Clock::getExpireTime(size_t lifetime)
00060                 {
00061                         return __getExpireTime(getTime(), lifetime);
00062                 }
00063 
00064                 size_t Clock::__getExpireTime(size_t timestamp, size_t lifetime)
00065                 {
00066                         // if the quality of time is zero, return standard expire time
00067                         if (Clock::quality == 0) return timestamp + lifetime;
00068 
00069                         // calculate sigma based on the quality of time and the original lifetime
00070                         size_t sigma = lifetime * (1 - Clock::quality);
00071 
00072                         // expiration adjusted by quality of time
00073                         return timestamp + lifetime + sigma;
00074                 }
00075 
00076                 bool Clock::isExpired(const dtn::data::Bundle &b)
00077                 {
00078                         // use the AgeBlock to verify the age
00079                         try {
00080                                 const dtn::data::AgeBlock &agebl = b.getBlock<const dtn::data::AgeBlock>();
00081                                 return (b._lifetime < agebl.getSeconds());
00082                         } catch (const dtn::data::Bundle::NoSuchBlockFoundException&) { };
00083 
00084                         return __isExpired(b._timestamp, b._lifetime);
00085                 }
00086 
00087                 bool Clock::isExpired(size_t timestamp, size_t lifetime)
00088                 {
00089                         return __isExpired(timestamp, lifetime);
00090                 }
00091 
00092                 bool Clock::__isExpired(size_t timestamp, size_t lifetime)
00093                 {
00094                         // if the quality of time is zero or the clock is bad, then never expire a bundle
00095                         if ((Clock::quality == 0) || dtn::utils::Clock::badclock) return false;
00096 
00097                         // calculate sigma based on the quality of time and the original lifetime
00098                         size_t sigma = lifetime * (1 - Clock::quality);
00099 
00100                         // expiration adjusted by quality of time
00101                         if ( Clock::getTime() > (timestamp + lifetime + sigma)) return true;
00102 
00103                         return false;
00104                 }
00105 
00106                 size_t Clock::getTime()
00107                 {
00108                         struct timeval now;
00109                         Clock::gettimeofday(&now);
00110 
00111                         // timezone
00112                         int offset = Clock::timezone * 3600;
00113 
00114                         // do we believe we are before the year 2000?
00115                         if ((u_int)now.tv_sec < TIMEVAL_CONVERSION)
00116                         {
00117                                 return 0;
00118                         }
00119 
00120                         return (now.tv_sec - TIMEVAL_CONVERSION) + offset;
00121                 }
00122 
00123                 size_t Clock::getUnixTimestamp()
00124                 {
00125                         struct timeval now;
00126                         Clock::gettimeofday(&now);
00127 
00128                         // timezone
00129                         int offset = Clock::timezone * 3600;
00130 
00131                         return now.tv_sec + offset;
00132                 }
00133 
00134                 void Clock::setOffset(struct timeval &tv)
00135                 {
00136                         if (!modify_clock)
00137                         {
00138                                 if (!Clock::_offset_init)
00139                                 {
00140                                         timerclear(&Clock::_offset);
00141                                         Clock::_offset_init = true;
00142                                 }
00143                                 timeradd(&Clock::_offset, &tv, &Clock::_offset);
00144                                 IBRCOMMON_LOGGER(info) << "[Clock] new local offset: " << _offset.tv_sec << " seconds and " << _offset.tv_usec << " microseconds" << IBRCOMMON_LOGGER_ENDL;
00145                         }
00146                         else
00147                         {
00148                                 struct timezone tz;
00149                                 struct timeval now;
00150                                 ::gettimeofday(&now, &tz);
00151 
00152                                 // adjust by the offset
00153                                 timersub(&now, &tv, &now);
00154 
00155                                 // set the local clock to the new timestamp
00156                                 ::settimeofday(&now, &tz);
00157                         }
00158                 }
00159 
00160                 void Clock::settimeofday(struct timeval *tv)
00161                 {
00162                         struct timezone tz;
00163                         struct timeval now;
00164                         ::gettimeofday(&now, &tz);
00165 
00166                         if (!modify_clock)
00167                         {
00168                                 if (!Clock::_offset_init)
00169                                 {
00170                                         timerclear(&Clock::_offset);
00171                                         Clock::_offset_init = true;
00172                                 }
00173                                 timersub(&now, tv, &Clock::_offset);
00174                                 IBRCOMMON_LOGGER(info) << "[Clock] new local offset: " << _offset.tv_sec << " seconds and " << _offset.tv_usec << " microseconds" << IBRCOMMON_LOGGER_ENDL;
00175                         }
00176                         else
00177                         {
00178                                 // set the local clock to the new timestamp
00179                                 ::settimeofday(tv, &tz);
00180                         }
00181                 }
00182 
00183                 void Clock::gettimeofday(struct timeval *tv)
00184                 {
00185                         struct timezone tz;
00186                         ::gettimeofday(tv, &tz);
00187 
00188                         // correct by the local offset
00189                         if (!modify_clock)
00190                         {
00191                                 if (!Clock::_offset_init)
00192                                 {
00193                                         timerclear(&Clock::_offset);
00194                                         Clock::_offset_init = true;
00195                                 }
00196                                 // add offset
00197                                 timersub(tv, &Clock::_offset, tv);
00198                         }
00199                 }
00200         }
00201 }