Files
pvAccess/pvAccessApp/remote/beaconEmitter.cpp
Matej Sekoranja ebdead0b98 beacon fixed
2011-03-05 01:29:26 +01:00

158 lines
3.6 KiB
C++

/*
* beaconEmitter.cpp
*/
#include "beaconEmitter.h"
using namespace std;
namespace epics { namespace pvAccess {
const float BeaconEmitter::EPICS_CA_MIN_BEACON_PERIOD = 1.0;
const float BeaconEmitter::EPICS_CA_MIN_BEACON_COUNT_LIMIT = 3.0;
BeaconEmitter::BeaconEmitter(Transport* transport, ServerContextImpl* context): _transport(transport)
{
if(transport == NULL || context == NULL)
{
THROW_BASE_EXCEPTION("null transport or context");
}
_timer = context->getTimer();
_beaconSequenceID = 0;
_serverAddress = context->getServerInetAddress();
_serverPort = context->getServerPort();
_serverStatusProvider = context->getBeaconServerStatusProvider();
_fastBeaconPeriod = std::max(context->getBeaconPeriod(), EPICS_CA_MIN_BEACON_PERIOD);
_slowBeaconPeriod = std::max(180.0, _fastBeaconPeriod); // TODO configurable
_beaconCountLimit = (int16)std::max(10.0f, EPICS_CA_MIN_BEACON_COUNT_LIMIT); // TODO configurable
_startupTime = new TimeStamp();
_startupTime->getCurrent();
_timerNode = new TimerNode(*this);
}
BeaconEmitter::BeaconEmitter(Transport* transport,const osiSockAddr* serverAddress): _transport(transport)
{
if(transport == NULL)
{
THROW_BASE_EXCEPTION("null transport");
}
_timer = new Timer("pvAccess-server timer", lowPriority);
_beaconSequenceID = 0;
_serverAddress = serverAddress;
_serverPort = serverAddress->ia.sin_port;
_serverStatusProvider = NULL;//new BeaconServerStatusProvider();
_fastBeaconPeriod = EPICS_CA_MIN_BEACON_PERIOD;
_slowBeaconPeriod = 180.0;
_beaconCountLimit = 10;
_startupTime = new TimeStamp();
_startupTime->getCurrent();
_timerNode = new TimerNode(*this);
}
BeaconEmitter::~BeaconEmitter()
{
if(_serverStatusProvider) delete _serverStatusProvider;
if(_timerNode) delete _timerNode;
if(_startupTime) delete _startupTime;
}
void BeaconEmitter::lock()
{
//noop
}
void BeaconEmitter::unlock()
{
//noop
}
void BeaconEmitter::acquire()
{
//noop
}
void BeaconEmitter::release()
{
//noop
}
void BeaconEmitter::send(ByteBuffer* buffer, TransportSendControl* control)
{
// get server status
PVFieldPtr serverStatus = NULL;
if(_serverStatusProvider != NULL)
{
try
{
serverStatus = _serverStatusProvider->getServerStatusData();
}
catch (...) {
// we have to proctect internal code from external implementation...
errlogSevPrintf(errlogMinor, "BeaconServerStatusProvider implementation thrown an exception.");
}
}
// send beacon
control->startMessage((int8)0, (sizeof(int16)+2*sizeof(int32)+128+sizeof(int16))/sizeof(int8));
buffer->putShort(_beaconSequenceID);
buffer->putLong((int64)_startupTime->getSecondsPastEpoch());
buffer->putInt((int32)_startupTime->getNanoSeconds());
// NOTE: is it possible (very likely) that address is any local address ::ffff:0.0.0.0
encodeAsIPv6Address(buffer, _serverAddress);
buffer->putShort((int16)_serverPort);
if (serverStatus != NULL)
{
// introspection interface + data
IntrospectionRegistry::serializeFull(serverStatus->getField(), buffer, control);
serverStatus->serialize(buffer, control);
}
else
{
IntrospectionRegistry::serializeFull(NULL, buffer, control);
}
control->flush(true);
// increment beacon sequence ID
_beaconSequenceID++;
reschedule();
}
void BeaconEmitter::timerStopped()
{
//noop
}
void BeaconEmitter::destroy()
{
_timerNode->cancel();
}
void BeaconEmitter::start()
{
_timer->scheduleAfterDelay(*_timerNode, 0.0);
}
void BeaconEmitter::reschedule()
{
const double period = (_beaconSequenceID >= _beaconCountLimit) ? _slowBeaconPeriod : _fastBeaconPeriod;
if (period > 0)
{
_timer->scheduleAfterDelay(*_timerNode, period);
}
}
void BeaconEmitter::callback()
{
_transport->enqueueSendRequest(this);
}
}}