Return to unitime.cpp CVS log | Up to Nevrax / code / nel / src / net |
File: Nevrax / code / nel / src / net / unitime.cpp (download) Revision 1.31, Fri Dec 28 10:17:21 2001 UTC (7 months ago) by lecroart Branch: MAIN CVS Tags: georges_v2, HEAD Changes since 1.30: +12 -11 lines ADDED: support of precompilated header on visual |
/** \file unitime.cpp * _CUniTime class * * $Id: unitime.cpp,v 1.31 2001/12/28 10:17:21 lecroart Exp $ */ /* Copyright, 2000 Nevrax Ltd. * * This file is part of NEVRAX NEL. * NEVRAX NEL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * NEVRAX NEL is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * You should have received a copy of the GNU General Public License * along with NEVRAX NEL; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "stdnet.h" #include "nel/net/callback_client.h" #include "nel/net/callback_server.h" #include "nel/net/naming_client.h" #include "nel/net/message.h" #include "nel/net/unitime.h" using namespace NLMISC; using namespace std; namespace NLNET { TTime _CUniTime::_SyncUniTime = 0; TTime _CUniTime::_SyncLocalTime = 0; bool _CUniTime::_Simulate = false; bool _CUniTime::Sync = false; void _CUniTime::setUniTime (NLMISC::TTime uTime, NLMISC::TTime lTime) { nlstop; /* if (Sync) { TTime lt = getLocalTime (); TTime delta = uTime - lTime + _SyncLocalTime - _SyncUniTime; nlinfo ("_CUniTime::setUniTime(%"NL_I64"d, %"NL_I64"d): Resyncing delta %"NL_I64"dms",uTime,lTime,delta); } else { nlinfo ("_CUniTime::setUniTime(%"NL_I64"d, %"NL_I64"d)",uTime,lTime); Sync = true; } _SyncUniTime = uTime; _SyncLocalTime = lTime; */} void _CUniTime::setUniTime (NLMISC::TTime uTime) { nlstop; // setUniTime (uTime, getLocalTime ()); } TTime _CUniTime::getUniTime () { nlstop; return 0; /* if (!Sync) { nlerror ("called getUniTime before calling syncUniTimeFromServer"); } return getLocalTime () - (_SyncLocalTime - _SyncUniTime); */ } const char *_CUniTime::getStringUniTime () { nlstop; return getStringUniTime(_CUniTime::getUniTime()); } const char *_CUniTime::getStringUniTime (TTime ut) { nlstop; static char str[512]; uint32 ms = (uint32) (ut % 1000); // time in ms 1000ms dans 1s ut /= 1000; uint32 s = (uint32) (ut % 60); // time in seconds 60s dans 1mn ut /= 60; uint32 m = (uint32) (ut % 60); // time in minutes 60m dans 1h ut /= 60; uint32 h = (uint32) (ut % 9); // time in hours 9h dans 1j ut /= 9; uint32 day = (uint32) (ut % (8*4)); // time in days 8day dans 1month ut /= 8; uint32 week = (uint32) (ut % 4); // time in weeks 4week dans 1month ut /= 4; uint32 month = (uint32) (ut % 12); // time in months 12month dans 1year ut /= 12; uint year = (uint32) ut; // time in years smprintf (str, 512, "%02d/%02d/%04d (week %d) %02d:%02d:%02d.%03d", day+1, month+1, year+1, week+1, h, m, s, ms); return str; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// /////////////// SYNCHRONISATION BETWEEN TIME SERVICE AND OTHER SERVICES //////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// static bool GetUniversalTime; static uint32 GetUniversalTimeSecondsSince1970; static TTime GetUniversalTimeUniTime; static void cbGetUniversalTime (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) { nlstop; // get the association between a date and unitime msgin.serial (GetUniversalTimeSecondsSince1970); msgin.serial (GetUniversalTimeUniTime); GetUniversalTime = true; } static TCallbackItem UniTimeCallbackArray[] = { { "GUT", cbGetUniversalTime } }; void _CUniTime::syncUniTimeFromService (CCallbackNetBase::TRecordingState rec, const CInetAddress *addr) { nlstop; /* TTime deltaAdjust, lt; uint32 firstsecond, nextsecond; TTime before, after, delta; // create a message with type in the full text format CMessage msgout ("AUT"); CCallbackClient server( rec, "TS.nmr" ); server.addCallbackArray (UniTimeCallbackArray, sizeof (UniTimeCallbackArray) / sizeof (UniTimeCallbackArray[0])); if (addr == NULL) { CNamingClient::lookupAndConnect ("TS", server); } else { server.connect (*addr); } if (!server.connected()) goto error; server.send (msgout); // before time before = CTime::getLocalTime (); // receive the answer GetUniversalTime = false; while (!GetUniversalTime) { if (!server.connected()) goto error; server.update (); nlSleep( 0 ); } // after, before and delta is not used. It's only for information purpose. after = CTime::getLocalTime (); delta = after - before; nlinfo ("_CUniTime::syncUniTimeFromService(): ping:%"NL_I64"dms, time:%ds, unitime:%"NL_I64"dms", delta, GetUniversalTimeSecondsSince1970, GetUniversalTimeUniTime); // <-- from here to the "-->" comment, the block must be executed in less than one second or an infinite loop occurs // get the second firstsecond = CTime::getSecondsSince1970 (); nextsecond = firstsecond+1; // wait the next start of the second (take 100% of CPU to be more accurate) while (nextsecond != CTime::getSecondsSince1970 ()) nlassert (CTime::getSecondsSince1970 () <= nextsecond); // --> // get the local time of the beginning of the next second lt = CTime::getLocalTime (); if ( ! _Simulate ) { if (abs((sint32)((TTime)nextsecond - (TTime)GetUniversalTimeSecondsSince1970)) > 10) { nlerror ("the time delta (between me and the Time Service) is too big (more than 10s), servers aren't NTP synchronized"); goto error; } // compute the delta between the other side and our side number of second since 1970 deltaAdjust = ((TTime) nextsecond - (TTime) GetUniversalTimeSecondsSince1970) * 1000; // adjust the unitime to the current localtime GetUniversalTimeUniTime += deltaAdjust; nlinfo ("_CUniTime::syncUniTimeFromService(): rtime:%ds, runitime:%"NL_I64"ds, rlocaltime:%"NL_I64"d, deltaAjust:%"NL_I64"dms", nextsecond, GetUniversalTimeUniTime, lt, deltaAdjust); } else { nlinfo ("_CUniTime::syncUniTimeFromService(): runitime:%"NL_I64"ds, rlocaltime:%"NL_I64"d", GetUniversalTimeUniTime, lt); } _CUniTime::setUniTime (GetUniversalTimeUniTime, lt); server.disconnect (); return; error: nlerror ("Time Service is not found, lost or can't synchronize universal time"); */ } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// /////////////// SYNCHRONISATION BETWEEN CLIENT AND SHARD /////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // Server part static void cbServerAskUniversalTime (CMessage& msgin, TSockId from, CCallbackNetBase &netbase) { nlstop; TTime ut = _CUniTime::getUniTime (); // afficher l adresse de celui qui demande nlinfo("Send the universal time %"NL_I64"d to '%s'", ut, netbase.hostAddress(from).asString().c_str()); CMessage msgout (netbase.getSIDA(), "GUT"); msgout.serial (ut); netbase.send (msgout, from); } TCallbackItem ServerTimeServiceCallbackArray[] = { { "AUT", cbServerAskUniversalTime }, }; void _CUniTime::installServer (CCallbackServer *server) { nlstop; static bool alreadyAddedCallback = false; nlassert (server != NULL); nlassert (!alreadyAddedCallback); server->addCallbackArray (ServerTimeServiceCallbackArray, sizeof (ServerTimeServiceCallbackArray) / sizeof (ServerTimeServiceCallbackArray[0])); alreadyAddedCallback = true; } // Client part static bool GetClientUniversalTime; static TTime GetClientUniversalTimeUniTime; static void cbClientGetUniversalTime (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) { nlstop; // get the association between a date and unitime msgin.serial (GetClientUniversalTimeUniTime); GetClientUniversalTime = true; } static TCallbackItem ClientUniTimeCallbackArray[] = { { "GUT", cbClientGetUniversalTime } }; void _CUniTime::syncUniTimeFromServer (CCallbackClient *client) { nlstop; /* static bool alreadyAddedCallback = false; nlassert (client != NULL); if (!alreadyAddedCallback) { client->addCallbackArray (ClientUniTimeCallbackArray, sizeof (ClientUniTimeCallbackArray) / sizeof (ClientUniTimeCallbackArray[0])); alreadyAddedCallback = true; } sint attempt = 0; TTime bestdelta = 60000; // 1 minute if (!client->connected ()) goto error; while (attempt < 10) { CMessage msgout (client->getSIDA(), "AUT"); if (!client->connected()) goto error; // send the message client->send (msgout); // before time TTime before = CTime::getLocalTime (); // receive the answer GetClientUniversalTime = false; while (!GetClientUniversalTime) { if (!client->connected()) goto error; client->update (); } TTime after = CTime::getLocalTime (), delta = after - before; if (delta < 10 || delta < bestdelta) { bestdelta = delta; _CUniTime::setUniTime (GetClientUniversalTimeUniTime, (before+after)/2); if (delta < 10) break; } attempt++; } client->disconnect (); nlinfo ("Universal time is %"NL_I64"dms with a mean error of %"NL_I64"dms", _CUniTime::getUniTime(), bestdelta/2); return; error: nlwarning ("there's no connection or lost or can't synchronize universal time"); */ } // // Commands // /* NLMISC_COMMAND (time, "displays the universal time", "") { if(args.size() != 0) return false; if ( _CUniTime::Sync ) { log.displayNL ("CTime::getLocalTime(): %"NL_I64"dms, _CUniTime::getUniTime(): %"NL_I64"dms", CTime::getLocalTime (), _CUniTime::getUniTime ()); log.displayNL ("_CUniTime::getStringUniTime(): '%s'", _CUniTime::getStringUniTime()); } else { log.displayNL ("CTime::getLocalTime(): %"NL_I64"dms <Universal time not sync>", CTime::getLocalTime ()); } return true; } */ } // NLNET