|
@@ -74,8 +74,9 @@ struct _NodeImpl
|
|
|
RuntimeEnvironment renv;
|
|
|
std::string reasonForTerminationStr;
|
|
|
Node::ReasonForTermination reasonForTermination;
|
|
|
- bool started;
|
|
|
- bool running;
|
|
|
+ volatile bool started;
|
|
|
+ volatile bool running;
|
|
|
+ volatile bool updateStatusNow;
|
|
|
volatile bool terminateNow;
|
|
|
|
|
|
// Helper used to rapidly terminate from run()
|
|
@@ -104,6 +105,7 @@ Node::Node(const char *hp,const char *urlPrefix,const char *configAuthorityIdent
|
|
|
impl->reasonForTermination = Node::NODE_RUNNING;
|
|
|
impl->started = false;
|
|
|
impl->running = false;
|
|
|
+ impl->updateStatusNow = false;
|
|
|
impl->terminateNow = false;
|
|
|
}
|
|
|
|
|
@@ -236,6 +238,8 @@ Node::ReasonForTermination Node::run()
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
+ std::string statusPath(_r->homePath + ZT_PATH_SEPARATOR_S + "status");
|
|
|
+
|
|
|
uint64_t lastPingCheck = 0;
|
|
|
uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately
|
|
|
uint64_t lastNetworkFingerprintCheck = 0;
|
|
@@ -243,6 +247,7 @@ Node::ReasonForTermination Node::run()
|
|
|
uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint();
|
|
|
uint64_t lastMulticastCheck = 0;
|
|
|
uint64_t lastMulticastAnnounceAll = 0;
|
|
|
+ uint64_t lastStatusUpdate = 0;
|
|
|
long lastDelayDelta = 0;
|
|
|
|
|
|
LOG("%s starting version %s",_r->identity.address().toString().c_str(),versionString());
|
|
@@ -373,6 +378,20 @@ Node::ReasonForTermination Node::run()
|
|
|
_r->topology->clean(); // happens in background
|
|
|
}
|
|
|
|
|
|
+ if (((now - lastStatusUpdate) >= ZT_STATUS_OUTPUT_PERIOD)||(impl->updateStatusNow)) {
|
|
|
+ lastStatusUpdate = now;
|
|
|
+ impl->updateStatusNow = false;
|
|
|
+ FILE *statusf = ::fopen(statusPath.c_str(),"w");
|
|
|
+ if (statusf) {
|
|
|
+ try {
|
|
|
+ _r->topology->eachPeer(Topology::DumpPeerStatistics(statusf));
|
|
|
+ } catch ( ... ) {
|
|
|
+ TRACE("unexpected exception updating status dump");
|
|
|
+ }
|
|
|
+ ::fclose(statusf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
unsigned long delay = std::min((unsigned long)ZT_MIN_SERVICE_LOOP_INTERVAL,_r->sw->doTimerTasks());
|
|
|
uint64_t start = Utils::now();
|
|
@@ -391,11 +410,6 @@ Node::ReasonForTermination Node::run()
|
|
|
return impl->terminateBecause(Node::NODE_NORMAL_TERMINATION,"normal termination");
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Obtain a human-readable reason for node termination
|
|
|
- *
|
|
|
- * @return Reason for node termination or NULL if run() has not returned
|
|
|
- */
|
|
|
const char *Node::reasonForTermination() const
|
|
|
throw()
|
|
|
{
|
|
@@ -404,19 +418,18 @@ const char *Node::reasonForTermination() const
|
|
|
return ((_NodeImpl *)_impl)->reasonForTerminationStr.c_str();
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Cause run() to return with NODE_NORMAL_TERMINATION
|
|
|
- *
|
|
|
- * This can be called from a signal handler or another thread to signal a
|
|
|
- * running node to shut down. Shutdown may take a few seconds, so run()
|
|
|
- * may not return instantly. Multiple calls are ignored.
|
|
|
- */
|
|
|
void Node::terminate()
|
|
|
throw()
|
|
|
{
|
|
|
((_NodeImpl *)_impl)->terminateNow = true;
|
|
|
}
|
|
|
|
|
|
+void Node::updateStatusNow()
|
|
|
+ throw()
|
|
|
+{
|
|
|
+ ((_NodeImpl *)_impl)->updateStatusNow = true;
|
|
|
+}
|
|
|
+
|
|
|
class _VersionStringMaker
|
|
|
{
|
|
|
public:
|