Rename pvAccessApp to src, adjust Makefiles
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
SRC_DIRS += $(PVACCESS_SRC)/server
|
||||
|
||||
INC += serverContext.h
|
||||
INC += responseHandlers.h
|
||||
INC += serverChannelImpl.h
|
||||
INC += baseChannelRequester.h
|
||||
INC += beaconEmitter.h
|
||||
INC += beaconServerStatusProvider.h
|
||||
|
||||
LIBSRCS += responseHandlers.cpp
|
||||
LIBSRCS += serverContext.cpp
|
||||
LIBSRCS += serverChannelImpl.cpp
|
||||
LIBSRCS += baseChannelRequester.cpp
|
||||
LIBSRCS += beaconEmitter.cpp
|
||||
LIBSRCS += beaconServerStatusProvider.cpp
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <pv/baseChannelRequester.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
const Status BaseChannelRequester::okStatus = Status();
|
||||
const Status BaseChannelRequester::badCIDStatus = Status(Status::STATUSTYPE_ERROR, "bad channel id");
|
||||
const Status BaseChannelRequester::badIOIDStatus = Status(Status::STATUSTYPE_ERROR, "bad request id");
|
||||
const Status BaseChannelRequester::noReadACLStatus = Status(Status::STATUSTYPE_ERROR, "no read access");
|
||||
const Status BaseChannelRequester::noWriteACLStatus = Status(Status::STATUSTYPE_ERROR, "no write access");
|
||||
const Status BaseChannelRequester::noProcessACLStatus = Status(Status::STATUSTYPE_ERROR, "no process access");
|
||||
const Status BaseChannelRequester::otherRequestPendingStatus = Status(Status::STATUSTYPE_ERROR, "other request pending");
|
||||
|
||||
const int32 BaseChannelRequester::NULL_REQUEST = -1;
|
||||
|
||||
BaseChannelRequester::BaseChannelRequester(
|
||||
ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel,
|
||||
const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport) :
|
||||
_ioid(ioid),
|
||||
_transport(transport),
|
||||
_channel(channel),
|
||||
_context(context),
|
||||
_pendingRequest(BaseChannelRequester::NULL_REQUEST)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool BaseChannelRequester::startRequest(int32 qos)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (_pendingRequest != NULL_REQUEST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_pendingRequest = qos;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseChannelRequester::stopRequest()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
_pendingRequest = NULL_REQUEST;
|
||||
}
|
||||
|
||||
int32 BaseChannelRequester::getPendingRequest()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
return _pendingRequest;
|
||||
}
|
||||
|
||||
String BaseChannelRequester::getRequesterName()
|
||||
{
|
||||
std::stringstream name;
|
||||
name << typeid(*_transport).name() << "/" << _ioid;
|
||||
return name.str();
|
||||
}
|
||||
|
||||
void BaseChannelRequester::message(String const & message, epics::pvData::MessageType messageType)
|
||||
{
|
||||
BaseChannelRequester::message(_transport, _ioid, message, messageType);
|
||||
}
|
||||
|
||||
void BaseChannelRequester::message(Transport::shared_pointer const & transport, const pvAccessID ioid, const String message, const MessageType messageType)
|
||||
{
|
||||
TransportSender::shared_pointer sender(new BaseChannelRequesterMessageTransportSender(ioid, message, messageType));
|
||||
transport->enqueueSendRequest(sender);
|
||||
}
|
||||
|
||||
void BaseChannelRequester::sendFailureMessage(const int8 command, Transport::shared_pointer const & transport, const pvAccessID ioid, const int8 qos, const Status status)
|
||||
{
|
||||
TransportSender::shared_pointer sender(new BaseChannelRequesterFailureMessageTransportSender(command, transport, ioid, qos, status));
|
||||
transport->enqueueSendRequest(sender);
|
||||
}
|
||||
|
||||
BaseChannelRequesterMessageTransportSender::BaseChannelRequesterMessageTransportSender(const pvAccessID ioid, const String message,const epics::pvData::MessageType messageType):
|
||||
_ioid(ioid),
|
||||
_message(message),
|
||||
_messageType(messageType)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseChannelRequesterMessageTransportSender::send(ByteBuffer* buffer, TransportSendControl* control)
|
||||
{
|
||||
control->startMessage((int8)18, sizeof(int32)/sizeof(int8) + 1);
|
||||
buffer->putInt(_ioid);
|
||||
buffer->putByte((int8)_messageType);
|
||||
epics::pvData::SerializeHelper::serializeString(_message, buffer, control);
|
||||
}
|
||||
|
||||
void BaseChannelRequesterMessageTransportSender::lock()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void BaseChannelRequesterMessageTransportSender::unlock()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
BaseChannelRequesterFailureMessageTransportSender::BaseChannelRequesterFailureMessageTransportSender(const int8 command,
|
||||
Transport::shared_pointer const & transport, const pvAccessID ioid, const int8 qos, const Status& status) :
|
||||
_command(command),
|
||||
_ioid(ioid),
|
||||
_qos(qos),
|
||||
_status(status),
|
||||
_transport(transport)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseChannelRequesterFailureMessageTransportSender::send(ByteBuffer* buffer, TransportSendControl* control)
|
||||
{
|
||||
control->startMessage(_command, sizeof(int32)/sizeof(int8) + 1);
|
||||
buffer->putInt(_ioid);
|
||||
buffer->put(_qos);
|
||||
_status.serialize(buffer, control);
|
||||
}
|
||||
|
||||
void BaseChannelRequesterFailureMessageTransportSender::lock()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void BaseChannelRequesterFailureMessageTransportSender::unlock()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef BASECHANNELREQUESTER_H_
|
||||
#define BASECHANNELREQUESTER_H_
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define baseChannelRequesterEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/requester.h>
|
||||
#include <pv/destroyable.h>
|
||||
|
||||
#ifdef baseChannelRequesterEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef baseChannelRequesterEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/serverChannelImpl.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class BaseChannelRequester : virtual public epics::pvData::Requester, public epics::pvData::Destroyable
|
||||
{
|
||||
public:
|
||||
BaseChannelRequester(ServerContextImpl::shared_pointer const & context, ServerChannelImpl::shared_pointer const & channel,
|
||||
const pvAccessID ioid, Transport::shared_pointer const & transport);
|
||||
virtual ~BaseChannelRequester() {};
|
||||
|
||||
bool startRequest(epics::pvData::int32 qos);
|
||||
void stopRequest();
|
||||
epics::pvData::int32 getPendingRequest();
|
||||
epics::pvData::String getRequesterName();
|
||||
void message(epics::pvData::String const & message, epics::pvData::MessageType messageType);
|
||||
static void message(Transport::shared_pointer const & transport, const pvAccessID ioid, const epics::pvData::String message, const epics::pvData::MessageType messageType);
|
||||
static void sendFailureMessage(const epics::pvData::int8 command, Transport::shared_pointer const & transport, const pvAccessID ioid, const epics::pvData::int8 qos, const epics::pvData::Status status);
|
||||
|
||||
static const epics::pvData::Status okStatus;
|
||||
static const epics::pvData::Status badCIDStatus;
|
||||
static const epics::pvData::Status badIOIDStatus;
|
||||
static const epics::pvData::Status noReadACLStatus;
|
||||
static const epics::pvData::Status noWriteACLStatus;
|
||||
static const epics::pvData::Status noProcessACLStatus;
|
||||
static const epics::pvData::Status otherRequestPendingStatus;
|
||||
protected:
|
||||
const pvAccessID _ioid;
|
||||
Transport::shared_pointer _transport;
|
||||
ServerChannelImpl::shared_pointer _channel;
|
||||
epics::pvData::Mutex _mutex;
|
||||
private:
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
static const epics::pvData::int32 NULL_REQUEST;
|
||||
epics::pvData::int32 _pendingRequest;
|
||||
};
|
||||
|
||||
class BaseChannelRequesterMessageTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
BaseChannelRequesterMessageTransportSender(const pvAccessID _ioid, const epics::pvData::String message,const epics::pvData::MessageType messageType);
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
const pvAccessID _ioid;
|
||||
const epics::pvData::String _message;
|
||||
const epics::pvData::MessageType _messageType;
|
||||
};
|
||||
|
||||
class BaseChannelRequesterFailureMessageTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
BaseChannelRequesterFailureMessageTransportSender(const epics::pvData::int8 command, Transport::shared_pointer const & transport, const pvAccessID ioid, const epics::pvData::int8 qos, const epics::pvData::Status& status);
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
const epics::pvData::int8 _command;
|
||||
const pvAccessID _ioid;
|
||||
const epics::pvData::int8 _qos;
|
||||
const epics::pvData::Status _status;
|
||||
Transport::shared_pointer _transport;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* BASECHANNELREQUESTER_H_ */
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <pv/beaconEmitter.h>
|
||||
#include <pv/serializationHelper.h>
|
||||
|
||||
#include <pv/logger.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <pv/serverContext.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
const float BeaconEmitter::EPICS_PVA_MIN_BEACON_PERIOD = 1.0;
|
||||
const float BeaconEmitter::EPICS_PVA_MIN_BEACON_COUNT_LIMIT = 3.0;
|
||||
|
||||
//BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, ServerContextImpl::shared_pointer const & context) :
|
||||
BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, std::tr1::shared_ptr<ServerContextImpl>& context) :
|
||||
_transport(transport),
|
||||
_beaconSequenceID(0),
|
||||
_startupTime(),
|
||||
_fastBeaconPeriod(std::max(context->getBeaconPeriod(), EPICS_PVA_MIN_BEACON_PERIOD)),
|
||||
_slowBeaconPeriod(std::max(180.0, _fastBeaconPeriod)), // TODO configurable
|
||||
_beaconCountLimit((int16)std::max(10.0f, EPICS_PVA_MIN_BEACON_COUNT_LIMIT)), // TODO configurable
|
||||
_serverAddress(*(context->getServerInetAddress())),
|
||||
_serverPort(context->getServerPort()),
|
||||
_serverStatusProvider(context->getBeaconServerStatusProvider()),
|
||||
_timer(context->getTimer())
|
||||
{
|
||||
_startupTime.getCurrent();
|
||||
}
|
||||
|
||||
BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, const osiSockAddr& serverAddress) :
|
||||
_transport(transport),
|
||||
_beaconSequenceID(0),
|
||||
_startupTime(),
|
||||
_fastBeaconPeriod(EPICS_PVA_MIN_BEACON_PERIOD),
|
||||
_slowBeaconPeriod(180.0),
|
||||
_beaconCountLimit(10),
|
||||
_serverAddress(serverAddress),
|
||||
_serverPort(serverAddress.ia.sin_port),
|
||||
_serverStatusProvider(),
|
||||
_timer(new Timer("pvAccess-server timer", lowPriority))
|
||||
{
|
||||
_startupTime.getCurrent();
|
||||
}
|
||||
|
||||
BeaconEmitter::~BeaconEmitter()
|
||||
{
|
||||
// shared_from_this is not yet allows in destructor
|
||||
// be sure to call destroy() first !!!
|
||||
// destroy();
|
||||
}
|
||||
|
||||
void BeaconEmitter::lock()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::unlock()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::send(ByteBuffer* buffer, TransportSendControl* control)
|
||||
{
|
||||
// get server status
|
||||
PVField::shared_pointer serverStatus;
|
||||
if(_serverStatusProvider.get())
|
||||
{
|
||||
try
|
||||
{
|
||||
serverStatus = _serverStatusProvider->getServerStatusData();
|
||||
}
|
||||
catch (...) {
|
||||
// we have to proctect internal code from external implementation...
|
||||
LOG(logLevelDebug, "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)
|
||||
{
|
||||
// introspection interface + data
|
||||
serverStatus->getField()->serialize(buffer, control);
|
||||
serverStatus->serialize(buffer, control);
|
||||
}
|
||||
else
|
||||
{
|
||||
SerializationHelper::serializeNullField(buffer, control);
|
||||
}
|
||||
control->flush(true);
|
||||
|
||||
// increment beacon sequence ID
|
||||
_beaconSequenceID++;
|
||||
|
||||
reschedule();
|
||||
}
|
||||
|
||||
void BeaconEmitter::timerStopped()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::destroy()
|
||||
{
|
||||
_timer->cancel(shared_from_this());
|
||||
}
|
||||
|
||||
void BeaconEmitter::start()
|
||||
{
|
||||
_timer->scheduleAfterDelay(shared_from_this(), 0.0);
|
||||
}
|
||||
|
||||
void BeaconEmitter::reschedule()
|
||||
{
|
||||
const double period = (_beaconSequenceID >= _beaconCountLimit) ? _slowBeaconPeriod : _fastBeaconPeriod;
|
||||
if (period > 0)
|
||||
{
|
||||
_timer->scheduleAfterDelay(shared_from_this(), period);
|
||||
}
|
||||
}
|
||||
|
||||
void BeaconEmitter::callback()
|
||||
{
|
||||
_transport->enqueueSendRequest(shared_from_this());
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef BEACONEMITTER_H
|
||||
#define BEACONEMITTER_H
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define beaconEmitterEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <osiSock.h>
|
||||
|
||||
#include <pv/timer.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#ifdef beaconEmitterEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef beaconEmitterEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/remote.h>
|
||||
#include <pv/beaconServerStatusProvider.h>
|
||||
//#include <pv/serverContext.h>
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class ServerContextImpl;
|
||||
|
||||
/**
|
||||
* BeaconEmitter
|
||||
*
|
||||
* @author gjansa
|
||||
*/
|
||||
class BeaconEmitter:
|
||||
public TransportSender,
|
||||
public epics::pvData::TimerCallback,
|
||||
public std::tr1::enable_shared_from_this<BeaconEmitter>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<BeaconEmitter> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BeaconEmitter> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param transport transport to be used to send beacons.
|
||||
* @param context PVA context.
|
||||
*/
|
||||
// BeaconEmitter(Transport::shared_pointer const & transport, ServerContextImpl::shared_pointer const & context);
|
||||
BeaconEmitter(Transport::shared_pointer const & transport, std::tr1::shared_ptr<ServerContextImpl>& context);
|
||||
|
||||
/**
|
||||
* Test Constructor (ohne context)
|
||||
* @param transport transport to be used to send beacons.
|
||||
*/
|
||||
BeaconEmitter(Transport::shared_pointer const & transport, const osiSockAddr& serverAddress);
|
||||
|
||||
virtual ~BeaconEmitter();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
|
||||
void timerStopped();
|
||||
|
||||
/**
|
||||
* Start emitting.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Reschedule timer.
|
||||
*/
|
||||
void reschedule();
|
||||
|
||||
/**
|
||||
* Timer callback.
|
||||
*/
|
||||
void callback();
|
||||
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Minimal (initial) PVA beacon period (in seconds).
|
||||
*/
|
||||
static const float EPICS_PVA_MIN_BEACON_PERIOD;
|
||||
|
||||
/**
|
||||
* Minimal PVA beacon count limit.
|
||||
*/
|
||||
static const float EPICS_PVA_MIN_BEACON_COUNT_LIMIT;
|
||||
|
||||
/**
|
||||
* Transport.
|
||||
*/
|
||||
Transport::shared_pointer _transport;
|
||||
|
||||
/**
|
||||
* Beacon sequence ID.
|
||||
*/
|
||||
epics::pvData::int16 _beaconSequenceID;
|
||||
|
||||
/**
|
||||
* Startup timestamp (when clients detect a change, they will consider server restarted).
|
||||
*/
|
||||
epics::pvData::TimeStamp _startupTime;
|
||||
|
||||
/**
|
||||
* Fast (at startup) beacon period (in sec).
|
||||
*/
|
||||
double _fastBeaconPeriod;
|
||||
|
||||
/**
|
||||
* Slow (after beaconCountLimit is reached) beacon period (in sec).
|
||||
*/
|
||||
double _slowBeaconPeriod;
|
||||
|
||||
/**
|
||||
* Limit on number of beacons issued.
|
||||
*/
|
||||
epics::pvData::int16 _beaconCountLimit;
|
||||
|
||||
/**
|
||||
* Server address.
|
||||
*/
|
||||
const osiSockAddr _serverAddress;
|
||||
|
||||
/**
|
||||
* Server port.
|
||||
*/
|
||||
epics::pvData::int32 _serverPort;
|
||||
|
||||
/**
|
||||
* Server status provider implementation (optional).
|
||||
*/
|
||||
BeaconServerStatusProvider::shared_pointer _serverStatusProvider;
|
||||
|
||||
/**
|
||||
* Timer.
|
||||
*/
|
||||
epics::pvData::Timer::shared_pointer _timer;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* BEACONEMITTER_H */
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/beaconServerStatusProvider.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
DefaultBeaconServerStatusProvider::DefaultBeaconServerStatusProvider(ServerContext::shared_pointer const & context): _context(context)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
DefaultBeaconServerStatusProvider::~DefaultBeaconServerStatusProvider()
|
||||
{
|
||||
}
|
||||
|
||||
void DefaultBeaconServerStatusProvider::initialize()
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
StringArray fieldNames;
|
||||
fieldNames.resize(6);
|
||||
fieldNames[0] = "connections";
|
||||
fieldNames[1] = "allocatedMemory";
|
||||
fieldNames[2] = "freeMemory";
|
||||
fieldNames[3] = "threads";
|
||||
fieldNames[4] = "deadlocks";
|
||||
fieldNames[5] = "averageSystemLoad";
|
||||
|
||||
FieldConstPtrArray fields;
|
||||
fields.resize(6);
|
||||
// TODO hierarchy can be used...
|
||||
fields[0] = fieldCreate->createScalar(pvInt);
|
||||
fields[1] = fieldCreate->createScalar(pvLong);
|
||||
fields[2] = fieldCreate->createScalar(pvLong);
|
||||
fields[3] = fieldCreate->createScalar(pvInt);
|
||||
fields[4] = fieldCreate->createScalar(pvInt);
|
||||
fields[5] = fieldCreate->createScalar(pvDouble);
|
||||
|
||||
_status = getPVDataCreate()->createPVStructure(fieldCreate->createStructure(fieldNames, fields));
|
||||
}
|
||||
|
||||
PVField::shared_pointer DefaultBeaconServerStatusProvider::getServerStatusData()
|
||||
{
|
||||
//TODO implement (fill data)
|
||||
return _status;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef BEACONSERVERSTATUSPROVIDER_H
|
||||
#define BEACONSERVERSTATUSPROVIDER_H
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define beaconServerStatusProviderEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/sharedPtr.h>
|
||||
|
||||
#ifdef beaconServerStatusProviderEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef beaconServerStatusProviderEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class ServerContext;
|
||||
|
||||
/**
|
||||
* BeaconServerStatusProvider
|
||||
*/
|
||||
class epicsShareClass BeaconServerStatusProvider
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<BeaconServerStatusProvider> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BeaconServerStatusProvider> const_shared_pointer;
|
||||
|
||||
virtual ~BeaconServerStatusProvider() {};
|
||||
|
||||
/**
|
||||
* Gets server status data.
|
||||
*/
|
||||
virtual epics::pvData::PVField::shared_pointer getServerStatusData() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* DefaultBeaconServerStatusProvider
|
||||
*/
|
||||
class epicsShareClass DefaultBeaconServerStatusProvider : public BeaconServerStatusProvider
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param context PVA context.
|
||||
*/
|
||||
// DefaultBeaconServerStatusProvider(ServerContext::shared_pointer const & context);
|
||||
DefaultBeaconServerStatusProvider(std::tr1::shared_ptr<ServerContext> const & context);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~DefaultBeaconServerStatusProvider();
|
||||
|
||||
virtual epics::pvData::PVField::shared_pointer getServerStatusData();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
|
||||
private:
|
||||
epics::pvData::PVStructure::shared_pointer _status;
|
||||
std::tr1::shared_ptr<ServerContext> _context;
|
||||
//ServerContext::shared_pointer _context;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* BEACONSERVERSTATUSPROVIDER_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,777 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef RESPONSEHANDLERS_H_
|
||||
#define RESPONSEHANDLERS_H_
|
||||
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/remote.h>
|
||||
#include <pv/serverChannelImpl.h>
|
||||
#include <pv/baseChannelRequester.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
/**
|
||||
*/
|
||||
class AbstractServerResponseHandler : public AbstractResponseHandler {
|
||||
protected:
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
public:
|
||||
AbstractServerResponseHandler(ServerContextImpl::shared_pointer const & context, epics::pvData::String description) :
|
||||
AbstractResponseHandler(context.get(), description), _context(context) {
|
||||
}
|
||||
|
||||
virtual ~AbstractServerResponseHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Bad request handler.
|
||||
*/
|
||||
class ServerBadResponse : public AbstractServerResponseHandler {
|
||||
public:
|
||||
ServerBadResponse(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Bad request") {
|
||||
}
|
||||
|
||||
virtual ~ServerBadResponse() {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
/**
|
||||
* PVAS request handler - main handler which dispatches requests to appropriate handlers.
|
||||
*/
|
||||
class ServerResponseHandler : public ResponseHandler {
|
||||
public:
|
||||
ServerResponseHandler(ServerContextImpl::shared_pointer const & context);
|
||||
|
||||
virtual ~ServerResponseHandler() {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
/**
|
||||
* Table of response handlers for each command ID.
|
||||
*/
|
||||
std::vector<ResponseHandler::shared_pointer> m_handlerTable;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection validation message handler.
|
||||
*/
|
||||
class ServerConnectionValidationHandler : public AbstractServerResponseHandler {
|
||||
public:
|
||||
ServerConnectionValidationHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Connection validation") {
|
||||
}
|
||||
virtual ~ServerConnectionValidationHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
/**
|
||||
* NOOP response.
|
||||
*/
|
||||
class ServerNoopResponse : public AbstractServerResponseHandler {
|
||||
public:
|
||||
ServerNoopResponse(ServerContextImpl::shared_pointer const & context, epics::pvData::String description) :
|
||||
AbstractServerResponseHandler(context, description) {
|
||||
}
|
||||
virtual ~ServerNoopResponse(){}
|
||||
};
|
||||
|
||||
/**
|
||||
* Echo request handler.
|
||||
*/
|
||||
class ServerEchoHandler : public AbstractServerResponseHandler {
|
||||
public:
|
||||
ServerEchoHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Echo request") {
|
||||
}
|
||||
virtual ~ServerEchoHandler(){}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class EchoTransportSender : public TransportSender {
|
||||
public:
|
||||
EchoTransportSender(osiSockAddr* echoFrom) {
|
||||
memcpy(&_echoFrom, echoFrom, sizeof(osiSockAddr));
|
||||
}
|
||||
|
||||
virtual ~EchoTransportSender() {
|
||||
}
|
||||
|
||||
virtual void send(epics::pvData::ByteBuffer* /*buffer*/, TransportSendControl* control) {
|
||||
control->startMessage(CMD_ECHO, 0);
|
||||
control->setRecipient(_echoFrom);
|
||||
// TODO content
|
||||
}
|
||||
|
||||
virtual void lock() {
|
||||
}
|
||||
|
||||
virtual void unlock() {
|
||||
}
|
||||
|
||||
private:
|
||||
osiSockAddr _echoFrom;
|
||||
};
|
||||
|
||||
/**
|
||||
* Introspection search request handler.
|
||||
*/
|
||||
class ServerIntrospectionSearchHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerIntrospectionSearchHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Search request") {
|
||||
}
|
||||
virtual ~ServerIntrospectionSearchHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Search channel request handler.
|
||||
*/
|
||||
// TODO object pool!!!
|
||||
class ServerSearchHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
// TODO
|
||||
static std::map<epics::pvData::String, std::tr1::weak_ptr<ChannelProvider> > s_channelNameToProvider;
|
||||
|
||||
ServerSearchHandler(ServerContextImpl::shared_pointer const & context);
|
||||
virtual ~ServerSearchHandler(){}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
private:
|
||||
std::vector<ChannelProvider::shared_pointer> _providers;
|
||||
};
|
||||
|
||||
|
||||
class ServerChannelFindRequesterImpl:
|
||||
public ChannelFindRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelFindRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelFindRequesterImpl(ServerContextImpl::shared_pointer const & context, epics::pvData::int32 expectedResponseCount);
|
||||
virtual ~ServerChannelFindRequesterImpl(){}
|
||||
void clear();
|
||||
ServerChannelFindRequesterImpl* set(epics::pvData::String _name, epics::pvData::int32 searchSequenceId, epics::pvData::int32 cid, osiSockAddr* sendTo, bool responseRequired);
|
||||
void channelFindResult(const epics::pvData::Status& status, ChannelFind::shared_pointer const & channelFind, bool wasFound);
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
epics::pvData::String _name;
|
||||
epics::pvData::int32 _searchSequenceId;
|
||||
epics::pvData::int32 _cid;
|
||||
osiSockAddr* _sendTo;
|
||||
bool _responseRequired;
|
||||
bool _wasFound;
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
epics::pvData::Mutex _mutex;
|
||||
epics::pvData::int32 _expectedResponseCount;
|
||||
epics::pvData::int32 _responseCount;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Create channel request handler.
|
||||
*/
|
||||
class ServerCreateChannelHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerCreateChannelHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Create channel request") {
|
||||
_providers = context->getChannelProviders();
|
||||
}
|
||||
virtual ~ServerCreateChannelHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
private:
|
||||
void disconnect(Transport::shared_pointer const & transport);
|
||||
std::vector<ChannelProvider::shared_pointer> _providers;
|
||||
};
|
||||
|
||||
class ServerChannelRequesterImpl :
|
||||
public ChannelRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelRequesterImpl(Transport::shared_pointer const & transport, const epics::pvData::String channelName, const pvAccessID cid);
|
||||
public:
|
||||
virtual ~ServerChannelRequesterImpl() {}
|
||||
static ChannelRequester::shared_pointer create(ChannelProvider::shared_pointer const & provider, Transport::shared_pointer const & transport, const epics::pvData::String channelName, const pvAccessID cid);
|
||||
void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel);
|
||||
void channelStateChange(Channel::shared_pointer const & c, const Channel::ConnectionState isConnected);
|
||||
epics::pvData::String getRequesterName();
|
||||
void message(epics::pvData::String const & message, epics::pvData::MessageType messageType);
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ServerChannel::weak_pointer _serverChannel;
|
||||
Transport::weak_pointer _transport;
|
||||
const epics::pvData::String _channelName;
|
||||
const pvAccessID _cid;
|
||||
epics::pvData::Status _status;
|
||||
epics::pvData::Mutex _mutex;
|
||||
void createChannelFailedResponse(epics::pvData::ByteBuffer* buffer, TransportSendControl* control, const epics::pvData::Status& status);
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Destroy channel request handler.
|
||||
*/
|
||||
class ServerDestroyChannelHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerDestroyChannelHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Destroy channel request") {
|
||||
}
|
||||
virtual ~ServerDestroyChannelHandler(){}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
|
||||
class ServerDestroyChannelHandlerTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
ServerDestroyChannelHandlerTransportSender(pvAccessID cid, pvAccessID sid): _cid(cid), _sid(sid) {
|
||||
}
|
||||
|
||||
virtual ~ServerDestroyChannelHandlerTransportSender() {}
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) {
|
||||
control->startMessage((epics::pvData::int8)CMD_DESTROY_CHANNEL, 2*sizeof(epics::pvData::int32)/sizeof(epics::pvData::int8));
|
||||
buffer->putInt(_sid);
|
||||
buffer->putInt(_cid);
|
||||
}
|
||||
|
||||
void lock() {
|
||||
// noop
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
// noop
|
||||
}
|
||||
|
||||
private:
|
||||
pvAccessID _cid;
|
||||
pvAccessID _sid;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Get request handler.
|
||||
*/
|
||||
class ServerGetHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerGetHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Get request") {
|
||||
}
|
||||
virtual ~ServerGetHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelGetRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelGetRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelGetRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelGetRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelGetRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelGetRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static ChannelGetRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelGetRequesterImpl() {}
|
||||
void channelGetConnect(const epics::pvData::Status& status, ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void getDone(const epics::pvData::Status& status);
|
||||
void destroy();
|
||||
|
||||
ChannelGet::shared_pointer getChannelGet();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelGet::shared_pointer _channelGet;
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvStructure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Put request handler.
|
||||
*/
|
||||
class ServerPutHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerPutHandler(ServerContextImpl::shared_pointer context) :
|
||||
AbstractServerResponseHandler(context, "Put request") {
|
||||
}
|
||||
virtual ~ServerPutHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelPutRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelPutRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelPutRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelPutRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelPutRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelPutRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static ChannelPutRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ~ServerChannelPutRequesterImpl() {}
|
||||
void channelPutConnect(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut, epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void putDone(const epics::pvData::Status& status);
|
||||
void getDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
ChannelPut::shared_pointer getChannelPut();
|
||||
epics::pvData::BitSet::shared_pointer getBitSet();
|
||||
epics::pvData::PVStructure::shared_pointer getPVStructure();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelPut::shared_pointer _channelPut;
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvStructure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Put request handler.
|
||||
*/
|
||||
class ServerPutGetHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerPutGetHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Put-get request") {
|
||||
}
|
||||
|
||||
virtual ~ServerPutGetHandler() {}
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelPutGetRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelPutGetRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelPutGetRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelPutGetRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelPutGetRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelPutGetRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static ChannelPutGetRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelPutGetRequesterImpl() {}
|
||||
|
||||
void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & channelPutGet, epics::pvData::PVStructure::shared_pointer const & pvPutStructure, epics::pvData::PVStructure::shared_pointer const & pvGetStructure);
|
||||
void getGetDone(const epics::pvData::Status& status);
|
||||
void getPutDone(const epics::pvData::Status& status);
|
||||
void putGetDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
ChannelPutGet::shared_pointer getChannelPutGet();
|
||||
epics::pvData::PVStructure::shared_pointer getPVPutStructure();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelPutGet::shared_pointer _channelPutGet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvPutStructure;
|
||||
epics::pvData::PVStructure::shared_pointer _pvGetStructure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Monitor request handler.
|
||||
*/
|
||||
class ServerMonitorHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerMonitorHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Monitor request") {
|
||||
}
|
||||
virtual ~ServerMonitorHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
|
||||
class ServerMonitorRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public epics::pvData::MonitorRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerMonitorRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerMonitorRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerMonitorRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerMonitorRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static epics::pvData::MonitorRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerMonitorRequesterImpl(){}
|
||||
|
||||
void monitorConnect(const epics::pvData::Status& status, epics::pvData::Monitor::shared_pointer const & monitor, epics::pvData::StructureConstPtr const & structure);
|
||||
void unlisten(epics::pvData::Monitor::shared_pointer const & monitor);
|
||||
void monitorEvent(epics::pvData::Monitor::shared_pointer const & monitor);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
epics::pvData::Monitor::shared_pointer getChannelMonitor();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
epics::pvData::Monitor::shared_pointer _channelMonitor;
|
||||
epics::pvData::StructureConstPtr _structure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Array request handler.
|
||||
*/
|
||||
class ServerArrayHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerArrayHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Array request") {
|
||||
}
|
||||
virtual ~ServerArrayHandler(){}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelArrayRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelArrayRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelArrayRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelArrayRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelArrayRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelArrayRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static ChannelArrayRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelArrayRequesterImpl() {}
|
||||
|
||||
void channelArrayConnect(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray, epics::pvData::PVArray::shared_pointer const & pvArray);
|
||||
void getArrayDone(const epics::pvData::Status& status);
|
||||
void putArrayDone(const epics::pvData::Status& status);
|
||||
void setLengthDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
ChannelArray::shared_pointer getChannelArray();
|
||||
|
||||
epics::pvData::PVArray::shared_pointer getPVArray();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
|
||||
private:
|
||||
ChannelArray::shared_pointer _channelArray;
|
||||
epics::pvData::PVArray::shared_pointer _pvArray;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Cancel request handler.
|
||||
*/
|
||||
class ServerCancelRequestHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerCancelRequestHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Cancel request") {
|
||||
}
|
||||
virtual ~ServerCancelRequestHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
|
||||
void failureResponse(Transport::shared_pointer const & transport, pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Process request handler.
|
||||
*/
|
||||
class ServerProcessHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerProcessHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Process request") {
|
||||
}
|
||||
virtual ~ServerProcessHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelProcessRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelProcessRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelProcessRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelProcessRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelProcessRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelProcessRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static ChannelProcessRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport, epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelProcessRequesterImpl() {}
|
||||
|
||||
void channelProcessConnect(const epics::pvData::Status& status, ChannelProcess::shared_pointer const & channelProcess);
|
||||
void processDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
ChannelProcess::shared_pointer getChannelProcess();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
|
||||
private:
|
||||
ChannelProcess::shared_pointer _channelProcess;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Get field request handler.
|
||||
*/
|
||||
class ServerGetFieldHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerGetFieldHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Get field request") {
|
||||
}
|
||||
virtual ~ServerGetFieldHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
void getFieldFailureResponse(Transport::shared_pointer const & transport, const pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
};
|
||||
|
||||
class ServerGetFieldRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public GetFieldRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerGetFieldRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerGetFieldRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerGetFieldRequesterImpl> const_shared_pointer;
|
||||
|
||||
ServerGetFieldRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
|
||||
virtual ~ServerGetFieldRequesterImpl() {}
|
||||
void getDone(const epics::pvData::Status& status, epics::pvData::FieldConstPtr const & field);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
epics::pvData::Status _status;
|
||||
epics::pvData::FieldConstPtr _field;
|
||||
};
|
||||
|
||||
class ServerGetFieldHandlerTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
ServerGetFieldHandlerTransportSender(const pvAccessID ioid,const epics::pvData::Status& status, Transport::shared_pointer const & transport):
|
||||
_ioid(ioid), _status(status), _transport(transport) {
|
||||
|
||||
}
|
||||
virtual ~ServerGetFieldHandlerTransportSender() {}
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) {
|
||||
control->startMessage((epics::pvData::int8)CMD_GET_FIELD, sizeof(epics::pvData::int32)/sizeof(epics::pvData::int8));
|
||||
buffer->putInt(_ioid);
|
||||
_status.serialize(buffer, control);
|
||||
}
|
||||
|
||||
void lock() {
|
||||
// noop
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
// noop
|
||||
}
|
||||
|
||||
private:
|
||||
const pvAccessID _ioid;
|
||||
const epics::pvData::Status _status;
|
||||
Transport::shared_pointer const & _transport;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* RPC handler.
|
||||
*/
|
||||
class ServerRPCHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerRPCHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "RPC request") {
|
||||
}
|
||||
virtual ~ServerRPCHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelRPCRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelRPCRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelRPCRequesterImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelRPCRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelRPCRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelRPCRequesterImpl(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
public:
|
||||
static ChannelRPCRequester::shared_pointer create(ServerContextImpl::shared_pointer const & context,
|
||||
ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelRPCRequesterImpl() {}
|
||||
|
||||
void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC::shared_pointer const & channelRPC);
|
||||
void requestDone(const epics::pvData::Status& status, epics::pvData::PVStructure::shared_pointer const & pvResponse);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelRPC
|
||||
*/
|
||||
ChannelRPC::shared_pointer getChannelRPC();
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelRPC::shared_pointer _channelRPC;
|
||||
epics::pvData::PVStructure::shared_pointer _pvResponse;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* RESPONSEHANDLERS_H_ */
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <pv/serverChannelImpl.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
ServerChannelImpl::ServerChannelImpl(Channel::shared_pointer const & channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField::shared_pointer const & /*securityToken*/):
|
||||
_channel(channel),
|
||||
_cid(cid),
|
||||
_sid(sid),
|
||||
_destroyed(false)
|
||||
{
|
||||
if (!channel.get())
|
||||
{
|
||||
THROW_BASE_EXCEPTION("non-null channel required");
|
||||
}
|
||||
}
|
||||
|
||||
Channel::shared_pointer ServerChannelImpl::getChannel()
|
||||
{
|
||||
return _channel;
|
||||
}
|
||||
|
||||
pvAccessID ServerChannelImpl::getCID() const
|
||||
{
|
||||
return _cid;
|
||||
}
|
||||
|
||||
pvAccessID ServerChannelImpl::getSID() const
|
||||
{
|
||||
return _sid;
|
||||
}
|
||||
|
||||
int16 ServerChannelImpl::getAccessRights()
|
||||
{
|
||||
//TODO implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerChannelImpl::registerRequest(const pvAccessID id, Destroyable::shared_pointer const & request)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
_requests[id] = request;
|
||||
}
|
||||
|
||||
void ServerChannelImpl::unregisterRequest(const pvAccessID id)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
std::map<pvAccessID, epics::pvData::Destroyable::shared_pointer>::iterator iter = _requests.find(id);
|
||||
if(iter != _requests.end())
|
||||
{
|
||||
_requests.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
Destroyable::shared_pointer ServerChannelImpl::getRequest(const pvAccessID id)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
std::map<pvAccessID, epics::pvData::Destroyable::shared_pointer>::iterator iter = _requests.find(id);
|
||||
if(iter != _requests.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return Destroyable::shared_pointer();
|
||||
}
|
||||
|
||||
void ServerChannelImpl::destroy()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (_destroyed) return;
|
||||
_destroyed = true;
|
||||
|
||||
// destroy all requests
|
||||
destroyAllRequests();
|
||||
|
||||
// ... and the channel
|
||||
// TODO try catch
|
||||
_channel->destroy();
|
||||
}
|
||||
|
||||
ServerChannelImpl::~ServerChannelImpl()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ServerChannelImpl::printInfo()
|
||||
{
|
||||
printInfo(stdout);
|
||||
}
|
||||
|
||||
void ServerChannelImpl::printInfo(FILE *fd)
|
||||
{
|
||||
fprintf(fd,"CLASS : %s\n", typeid(*this).name());
|
||||
fprintf(fd,"CHANNEL : %s\n", typeid(*_channel).name());
|
||||
}
|
||||
|
||||
void ServerChannelImpl::destroyAllRequests()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
|
||||
// resource allocation optimization
|
||||
if (_requests.size() == 0)
|
||||
return;
|
||||
|
||||
while(_requests.size() != 0)
|
||||
{
|
||||
_requests.begin()->second->destroy();
|
||||
}
|
||||
|
||||
_requests.clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef SERVERCHANNEL_H_
|
||||
#define SERVERCHANNEL_H_
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define serverChannelImplEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/destroyable.h>
|
||||
|
||||
#ifdef serverChannelImplEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef serverChannelImplEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/remote.h>
|
||||
#include <pv/clientContextImpl.h>
|
||||
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class ServerChannelImpl : public ServerChannel
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ServerChannelImpl);
|
||||
|
||||
/**
|
||||
* Create server channel for given process variable.
|
||||
* @param channel local channel.
|
||||
* @param cid channel CID.
|
||||
* @param sid channel SID.
|
||||
* @param securityToken security token.
|
||||
*/
|
||||
ServerChannelImpl(Channel::shared_pointer const & channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField::shared_pointer const & securityToken);
|
||||
/*
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~ServerChannelImpl();
|
||||
|
||||
/**
|
||||
* Get local channel.
|
||||
* @return local channel.
|
||||
*/
|
||||
Channel::shared_pointer getChannel();
|
||||
|
||||
/**
|
||||
* Get channel CID.
|
||||
* @return channel CID.
|
||||
*/
|
||||
pvAccessID getCID() const;
|
||||
|
||||
/**
|
||||
* Get channel SID.
|
||||
* @return channel SID.
|
||||
*/
|
||||
pvAccessID getSID() const;
|
||||
|
||||
/**
|
||||
* Get access rights (bit-mask encoded).
|
||||
* @see AccessRights
|
||||
* @return bit-mask encoded access rights.
|
||||
*/
|
||||
epics::pvData::int16 getAccessRights();
|
||||
|
||||
/**
|
||||
* Register request
|
||||
* @param id request ID.
|
||||
* @param request request to be registered.
|
||||
*/
|
||||
void registerRequest(pvAccessID id, epics::pvData::Destroyable::shared_pointer const & request);
|
||||
|
||||
/**
|
||||
* Unregister request.
|
||||
* @param id request ID.
|
||||
*/
|
||||
void unregisterRequest(pvAccessID id);
|
||||
|
||||
/**
|
||||
* Get request by its ID.
|
||||
* @param id request ID.
|
||||
* @return request with given ID, <code>null</code> if there is no request with such ID.
|
||||
*/
|
||||
epics::pvData::Destroyable::shared_pointer getRequest(pvAccessID id);
|
||||
|
||||
/**
|
||||
* Destroy server channel.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Prints detailed information about the process variable to the standard output stream.
|
||||
*/
|
||||
void printInfo();
|
||||
|
||||
/**
|
||||
* Prints detailed information about the process variable to the specified output
|
||||
* stream.
|
||||
* @param fd the output stream.
|
||||
*/
|
||||
void printInfo(FILE *fd);
|
||||
private:
|
||||
/**
|
||||
* Local channel.
|
||||
*/
|
||||
Channel::shared_pointer _channel;
|
||||
|
||||
/**
|
||||
* Channel CID.
|
||||
*/
|
||||
pvAccessID _cid;
|
||||
|
||||
/**
|
||||
* Channel SID.
|
||||
*/
|
||||
pvAccessID _sid;
|
||||
|
||||
/**
|
||||
* Requests.
|
||||
*/
|
||||
std::map<pvAccessID, epics::pvData::Destroyable::shared_pointer> _requests;
|
||||
|
||||
/**
|
||||
* Destroy state.
|
||||
*/
|
||||
bool _destroyed;
|
||||
|
||||
/**
|
||||
* Mutex
|
||||
*/
|
||||
epics::pvData::Mutex _mutex;
|
||||
|
||||
/**
|
||||
* Destroy all registered requests.
|
||||
*/
|
||||
void destroyAllRequests();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SERVERCHANNEL_H_ */
|
||||
@@ -0,0 +1,655 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <epicsSignal.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/responseHandlers.h>
|
||||
#include <pv/logger.h>
|
||||
#include <pv/serverContext.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
const char* ServerContextImpl::StateNames[] = { "NOT_INITIALIZED", "INITIALIZED", "RUNNING", "SHUTDOWN", "DESTROYED"};
|
||||
const Version ServerContextImpl::VERSION("pvAccess Server", "cpp",
|
||||
EPICS_PVA_MAJOR_VERSION, EPICS_PVA_MINOR_VERSION, EPICS_PVA_MAINTENANCE_VERSION, EPICS_PVA_DEVELOPMENT_FLAG);
|
||||
|
||||
ServerContextImpl::ServerContextImpl():
|
||||
_state(NOT_INITIALIZED),
|
||||
_beaconAddressList(),
|
||||
_ignoreAddressList(),
|
||||
_autoBeaconAddressList(true),
|
||||
_beaconPeriod(15.0),
|
||||
_broadcastPort(PVA_BROADCAST_PORT),
|
||||
_serverPort(PVA_SERVER_PORT),
|
||||
_receiveBufferSize(MAX_TCP_RECV),
|
||||
_timer(),
|
||||
_broadcastTransport(),
|
||||
_beaconEmitter(),
|
||||
_acceptor(),
|
||||
_transportRegistry(),
|
||||
_channelAccess(),
|
||||
_channelProviderNames(PVACCESS_DEFAULT_PROVIDER),
|
||||
_channelProviders(),
|
||||
_beaconServerStatusProvider()
|
||||
|
||||
{
|
||||
// TODO maybe there is a better place for this (when there will be some factory)
|
||||
epicsSignalInstallSigAlarmIgnore ();
|
||||
epicsSignalInstallSigPipeIgnore ();
|
||||
|
||||
initializeLogger();
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
ServerContextImpl::shared_pointer ServerContextImpl::create()
|
||||
{
|
||||
ServerContextImpl::shared_pointer thisPointer(new ServerContextImpl());
|
||||
return thisPointer;
|
||||
}
|
||||
|
||||
ServerContextImpl::~ServerContextImpl()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
const Version& ServerContextImpl::getVersion()
|
||||
{
|
||||
return ServerContextImpl::VERSION;
|
||||
}
|
||||
|
||||
void ServerContextImpl::initializeLogger()
|
||||
{
|
||||
//createFileLogger("serverContextImpl.log");
|
||||
}
|
||||
|
||||
struct noop_deleter
|
||||
{
|
||||
template<class T> void operator()(T * p) {}
|
||||
};
|
||||
|
||||
Configuration::shared_pointer ServerContextImpl::getConfiguration()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (configuration.get() == 0)
|
||||
{
|
||||
ConfigurationProvider::shared_pointer configurationProvider = ConfigurationFactory::getProvider();
|
||||
configuration = configurationProvider->getConfiguration("pvAccess-server");
|
||||
if (configuration.get() == 0)
|
||||
{
|
||||
configuration = configurationProvider->getConfiguration("system");
|
||||
}
|
||||
}
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configuration.
|
||||
*/
|
||||
void ServerContextImpl::loadConfiguration()
|
||||
{
|
||||
Configuration::shared_pointer config = getConfiguration();
|
||||
|
||||
_beaconAddressList = config->getPropertyAsString("EPICS_PVA_ADDR_LIST", _beaconAddressList);
|
||||
_beaconAddressList = config->getPropertyAsString("EPICS_PVAS_BEACON_ADDR_LIST", _beaconAddressList);
|
||||
|
||||
_autoBeaconAddressList = config->getPropertyAsBoolean("EPICS_PVA_AUTO_ADDR_LIST", _autoBeaconAddressList);
|
||||
_autoBeaconAddressList = config->getPropertyAsBoolean("EPICS_PVAS_AUTO_BEACON_ADDR_LIST", _autoBeaconAddressList);
|
||||
|
||||
_beaconPeriod = config->getPropertyAsFloat("EPICS_PVA_BEACON_PERIOD", _beaconPeriod);
|
||||
_beaconPeriod = config->getPropertyAsFloat("EPICS_PVAS_BEACON_PERIOD", _beaconPeriod);
|
||||
|
||||
_serverPort = config->getPropertyAsInteger("EPICS_PVA_SERVER_PORT", _serverPort);
|
||||
_serverPort = config->getPropertyAsInteger("EPICS_PVAS_SERVER_PORT", _serverPort);
|
||||
|
||||
_broadcastPort = config->getPropertyAsInteger("EPICS_PVA_BROADCAST_PORT", _broadcastPort);
|
||||
_broadcastPort = config->getPropertyAsInteger("EPICS_PVAS_BROADCAST_PORT", _broadcastPort);
|
||||
|
||||
_receiveBufferSize = config->getPropertyAsInteger("EPICS_PVA_MAX_ARRAY_BYTES", _receiveBufferSize);
|
||||
_receiveBufferSize = config->getPropertyAsInteger("EPICS_PVAS_MAX_ARRAY_BYTES", _receiveBufferSize);
|
||||
|
||||
_channelProviderNames = config->getPropertyAsString("EPICS_PVA_PROVIDER_NAMES", _channelProviderNames);
|
||||
_channelProviderNames = config->getPropertyAsString("EPICS_PVAS_PROVIDER_NAMES", _channelProviderNames);
|
||||
}
|
||||
|
||||
bool ServerContextImpl::isChannelProviderNamePreconfigured()
|
||||
{
|
||||
Configuration::shared_pointer config = getConfiguration();
|
||||
return config->hasProperty("EPICS_PVA_PROVIDER_NAMES") || config->hasProperty("EPICS_PVAS_PROVIDER_NAMES");
|
||||
}
|
||||
|
||||
void ServerContextImpl::initialize(ChannelAccess::shared_pointer const & channelAccess)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (channelAccess == NULL)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("non null channelAccess expected");
|
||||
}
|
||||
|
||||
if (_state == DESTROYED)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context destroyed.");
|
||||
}
|
||||
else if (_state != NOT_INITIALIZED)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context already initialized.");
|
||||
}
|
||||
|
||||
_channelAccess = channelAccess;
|
||||
|
||||
|
||||
// user all providers
|
||||
if (_channelProviderNames == PVACCESS_ALL_PROVIDERS)
|
||||
{
|
||||
_channelProviderNames.resize(0); // VxWorks 5.5 omits clear()
|
||||
|
||||
std::auto_ptr<ChannelAccess::stringVector_t> names = _channelAccess->getProviderNames();
|
||||
for (ChannelAccess::stringVector_t::iterator iter = names->begin(); iter != names->end(); iter++)
|
||||
{
|
||||
ChannelProvider::shared_pointer channelProvider = _channelAccess->getProvider(*iter);
|
||||
if (channelProvider)
|
||||
{
|
||||
_channelProviders.push_back(channelProvider);
|
||||
|
||||
// compile a list
|
||||
if (!_channelProviderNames.empty())
|
||||
_channelProviderNames += ' ';
|
||||
_channelProviderNames += *iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// split space separated names
|
||||
std::stringstream ss(_channelProviderNames);
|
||||
std::string providerName;
|
||||
while (std::getline(ss, providerName, ' '))
|
||||
{
|
||||
ChannelProvider::shared_pointer channelProvider = _channelAccess->getProvider(providerName);
|
||||
if (channelProvider)
|
||||
_channelProviders.push_back(channelProvider);
|
||||
}
|
||||
}
|
||||
|
||||
//_channelProvider = _channelAccess->getProvider(_channelProviderNames);
|
||||
if (_channelProviders.size() == 0)
|
||||
{
|
||||
std::string msg = "None of the specified channel providers are available: " + _channelProviderNames + ".";
|
||||
THROW_BASE_EXCEPTION(msg.c_str());
|
||||
}
|
||||
|
||||
internalInitialize();
|
||||
|
||||
_state = INITIALIZED;
|
||||
}
|
||||
|
||||
std::auto_ptr<ResponseHandler> ServerContextImpl::createResponseHandler()
|
||||
{
|
||||
ServerContextImpl::shared_pointer thisContext = shared_from_this();
|
||||
return std::auto_ptr<ResponseHandler>(new ServerResponseHandler(thisContext));
|
||||
}
|
||||
|
||||
void ServerContextImpl::internalInitialize()
|
||||
{
|
||||
osiSockAttach();
|
||||
|
||||
_timer.reset(new Timer("pvAccess-server timer", lowerPriority));
|
||||
_transportRegistry.reset(new TransportRegistry());
|
||||
|
||||
ServerContextImpl::shared_pointer thisServerContext = shared_from_this();
|
||||
|
||||
_acceptor.reset(new BlockingTCPAcceptor(thisServerContext, thisServerContext, _serverPort, _receiveBufferSize));
|
||||
_serverPort = ntohs(_acceptor->getBindAddress()->ia.sin_port);
|
||||
|
||||
// setup broadcast UDP transport
|
||||
initializeBroadcastTransport();
|
||||
|
||||
_beaconEmitter.reset(new BeaconEmitter(_broadcastTransport, thisServerContext));
|
||||
}
|
||||
|
||||
void ServerContextImpl::initializeBroadcastTransport()
|
||||
{
|
||||
// setup UDP transport
|
||||
try
|
||||
{
|
||||
// where to bind (listen) address
|
||||
osiSockAddr listenLocalAddress;
|
||||
listenLocalAddress.ia.sin_family = AF_INET;
|
||||
listenLocalAddress.ia.sin_port = htons(_broadcastPort);
|
||||
listenLocalAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
// where to send addresses
|
||||
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (socket == INVALID_SOCKET)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Failed to initialize broadcast UDP transport");
|
||||
}
|
||||
auto_ptr<InetAddrVector> broadcastAddresses(getBroadcastAddresses(socket,_broadcastPort));
|
||||
epicsSocketDestroy(socket);
|
||||
|
||||
TransportClient::shared_pointer nullTransportClient;
|
||||
|
||||
auto_ptr<BlockingUDPConnector> broadcastConnector(new BlockingUDPConnector(true, true));
|
||||
auto_ptr<epics::pvAccess::ResponseHandler> responseHandler = createResponseHandler();
|
||||
_broadcastTransport = static_pointer_cast<BlockingUDPTransport>(broadcastConnector->connect(
|
||||
nullTransportClient, responseHandler,
|
||||
listenLocalAddress, PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
_broadcastTransport->setBroadcastAddresses(broadcastAddresses.get());
|
||||
|
||||
// set ignore address list
|
||||
if (!_ignoreAddressList.empty())
|
||||
{
|
||||
// we do not care about the port
|
||||
auto_ptr<InetAddrVector> list(getSocketAddressList(_ignoreAddressList, 0, NULL));
|
||||
if (list.get() != NULL && list->size() > 0)
|
||||
{
|
||||
_broadcastTransport->setIgnoredAddresses(list.get());
|
||||
}
|
||||
}
|
||||
// set broadcast address list
|
||||
if (!_beaconAddressList.empty())
|
||||
{
|
||||
// if auto is true, add it to specified list
|
||||
InetAddrVector* appendList = NULL;
|
||||
if (_autoBeaconAddressList == true)
|
||||
{
|
||||
appendList = _broadcastTransport->getSendAddresses();
|
||||
}
|
||||
|
||||
auto_ptr<InetAddrVector> list(getSocketAddressList(_beaconAddressList, _broadcastPort, appendList));
|
||||
if (list.get() != NULL && list->size() > 0)
|
||||
{
|
||||
_broadcastTransport->setBroadcastAddresses(list.get());
|
||||
}
|
||||
}
|
||||
|
||||
_broadcastTransport->start();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
THROW_BASE_EXCEPTION_CAUSE("Failed to initialize broadcast UDP transport", e);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Failed to initialize broadcast UDP transport");
|
||||
}
|
||||
}
|
||||
|
||||
void ServerContextImpl::run(int32 seconds)
|
||||
{
|
||||
if (seconds < 0)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("seconds cannot be negative.");
|
||||
}
|
||||
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
|
||||
if (_state == NOT_INITIALIZED)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context not initialized.");
|
||||
}
|
||||
else if (_state == DESTROYED)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context destroyed.");
|
||||
}
|
||||
else if (_state == RUNNING)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context is already running.");
|
||||
}
|
||||
else if (_state == SHUTDOWN)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context was shutdown.");
|
||||
}
|
||||
|
||||
_state = RUNNING;
|
||||
}
|
||||
|
||||
// run...
|
||||
_beaconEmitter->start();
|
||||
|
||||
//TODO review this
|
||||
if(seconds == 0)
|
||||
{
|
||||
_runEvent.wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
_runEvent.wait(seconds);
|
||||
}
|
||||
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
_state = SHUTDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void ServerContextImpl::shutdown()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if(_state == DESTROYED)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("Context already destroyed.");
|
||||
}
|
||||
|
||||
// notify to stop running...
|
||||
_runEvent.signal();
|
||||
}
|
||||
|
||||
void ServerContextImpl::destroy()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (_state == DESTROYED)
|
||||
{
|
||||
// silent return
|
||||
return;
|
||||
// exception is not OK, since we use
|
||||
// shared_pointer-s auto-cleanup/destruction
|
||||
// THROW_BASE_EXCEPTION("Context already destroyed.");
|
||||
}
|
||||
|
||||
// shutdown if not already
|
||||
shutdown();
|
||||
|
||||
// go into destroyed state ASAP
|
||||
_state = DESTROYED;
|
||||
|
||||
internalDestroy();
|
||||
}
|
||||
|
||||
|
||||
void ServerContextImpl::internalDestroy()
|
||||
{
|
||||
// stop responding to search requests
|
||||
if (_broadcastTransport != NULL)
|
||||
{
|
||||
_broadcastTransport->close();
|
||||
_broadcastTransport.reset();
|
||||
}
|
||||
|
||||
// stop accepting connections
|
||||
if (_acceptor != NULL)
|
||||
{
|
||||
_acceptor->destroy();
|
||||
_acceptor.reset();
|
||||
}
|
||||
|
||||
// stop emitting beacons
|
||||
if (_beaconEmitter != NULL)
|
||||
{
|
||||
_beaconEmitter->destroy();
|
||||
_beaconEmitter.reset();
|
||||
}
|
||||
|
||||
// this will also destroy all channels
|
||||
destroyAllTransports();
|
||||
}
|
||||
|
||||
void ServerContextImpl::destroyAllTransports()
|
||||
{
|
||||
|
||||
// not initialized yet
|
||||
if (_transportRegistry == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::auto_ptr<TransportRegistry::transportVector_t> transports = _transportRegistry->toArray();
|
||||
if (transports.get() == 0)
|
||||
return;
|
||||
|
||||
int size = (int)transports->size();
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
LOG(logLevelInfo, "Server context still has %d transport(s) active and closing...", size);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
Transport::shared_pointer transport = (*transports)[i];
|
||||
try
|
||||
{
|
||||
transport->close();
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
// do all exception safe, log in case of an error
|
||||
LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// do all exception safe, log in case of an error
|
||||
LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
// now clear all (release)
|
||||
_transportRegistry->clear();
|
||||
|
||||
}
|
||||
|
||||
void ServerContextImpl::printInfo()
|
||||
{
|
||||
printInfo(cout);
|
||||
}
|
||||
|
||||
void ServerContextImpl::printInfo(ostream& str)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
str << "VERSION : " << getVersion().getVersionString() << endl \
|
||||
<< "PROVIDER_NAMES : " << _channelProviderNames << endl \
|
||||
<< "BEACON_ADDR_LIST : " << _beaconAddressList << endl \
|
||||
<< "AUTO_BEACON_ADDR_LIST : " << _autoBeaconAddressList << endl \
|
||||
<< "BEACON_PERIOD : " << _beaconPeriod << endl \
|
||||
<< "BROADCAST_PORT : " << _broadcastPort << endl \
|
||||
<< "SERVER_PORT : " << _serverPort << endl \
|
||||
<< "RCV_BUFFER_SIZE : " << _receiveBufferSize << endl \
|
||||
<< "IGNORE_ADDR_LIST: " << _ignoreAddressList << endl \
|
||||
<< "STATE : " << ServerContextImpl::StateNames[_state] << endl;
|
||||
}
|
||||
|
||||
void ServerContextImpl::dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
void ServerContextImpl::setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer const & beaconServerStatusProvider)
|
||||
{
|
||||
_beaconServerStatusProvider = beaconServerStatusProvider;
|
||||
}
|
||||
|
||||
bool ServerContextImpl::isInitialized()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
return _state == INITIALIZED || _state == RUNNING || _state == SHUTDOWN;
|
||||
}
|
||||
|
||||
bool ServerContextImpl::isDestroyed()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
return _state == DESTROYED;
|
||||
}
|
||||
|
||||
std::string ServerContextImpl::getBeaconAddressList()
|
||||
{
|
||||
return _beaconAddressList;
|
||||
}
|
||||
|
||||
bool ServerContextImpl::isAutoBeaconAddressList()
|
||||
{
|
||||
return _autoBeaconAddressList;
|
||||
}
|
||||
|
||||
float ServerContextImpl::getBeaconPeriod()
|
||||
{
|
||||
return _beaconPeriod;
|
||||
}
|
||||
|
||||
int32 ServerContextImpl::getReceiveBufferSize()
|
||||
{
|
||||
return _receiveBufferSize;
|
||||
}
|
||||
|
||||
int32 ServerContextImpl::getServerPort()
|
||||
{
|
||||
return _serverPort;
|
||||
}
|
||||
|
||||
void ServerContextImpl::setServerPort(int32 port)
|
||||
{
|
||||
_serverPort = port;
|
||||
}
|
||||
|
||||
int32 ServerContextImpl::getBroadcastPort()
|
||||
{
|
||||
return _broadcastPort;
|
||||
}
|
||||
|
||||
std::string ServerContextImpl::getIgnoreAddressList()
|
||||
{
|
||||
return _ignoreAddressList;
|
||||
}
|
||||
|
||||
BeaconServerStatusProvider::shared_pointer ServerContextImpl::getBeaconServerStatusProvider()
|
||||
{
|
||||
return _beaconServerStatusProvider;
|
||||
}
|
||||
|
||||
osiSockAddr* ServerContextImpl::getServerInetAddress()
|
||||
{
|
||||
if(_acceptor != NULL)
|
||||
{
|
||||
return const_cast<osiSockAddr*>(_acceptor->getBindAddress());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BlockingUDPTransport::shared_pointer ServerContextImpl::getBroadcastTransport()
|
||||
{
|
||||
return _broadcastTransport;
|
||||
}
|
||||
|
||||
ChannelAccess::shared_pointer ServerContextImpl::getChannelAccess()
|
||||
{
|
||||
return _channelAccess;
|
||||
}
|
||||
|
||||
std::string ServerContextImpl::getChannelProviderName()
|
||||
{
|
||||
return _channelProviderNames;
|
||||
}
|
||||
|
||||
// NOTE: not synced
|
||||
void ServerContextImpl::setChannelProviderName(std::string channelProviderName)
|
||||
{
|
||||
if (_state != NOT_INITIALIZED)
|
||||
throw std::logic_error("must be called before initialize");
|
||||
_channelProviderNames = channelProviderName;
|
||||
}
|
||||
|
||||
std::vector<ChannelProvider::shared_pointer> ServerContextImpl::getChannelProviders()
|
||||
{
|
||||
return _channelProviders;
|
||||
}
|
||||
|
||||
Timer::shared_pointer ServerContextImpl::getTimer()
|
||||
{
|
||||
return _timer;
|
||||
}
|
||||
|
||||
TransportRegistry::shared_pointer ServerContextImpl::getTransportRegistry()
|
||||
{
|
||||
return _transportRegistry;
|
||||
}
|
||||
|
||||
Channel::shared_pointer ServerContextImpl::getChannel(pvAccessID /*id*/)
|
||||
{
|
||||
// not used
|
||||
return Channel::shared_pointer();
|
||||
}
|
||||
|
||||
Transport::shared_pointer ServerContextImpl::getSearchTransport()
|
||||
{
|
||||
// not used
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
|
||||
void ServerContextImpl::newServerDetected()
|
||||
{
|
||||
// not used
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct ThreadRunnerParam {
|
||||
ServerContextImpl::shared_pointer ctx;
|
||||
int timeToRun;
|
||||
};
|
||||
|
||||
static void threadRunner(void* usr)
|
||||
{
|
||||
ThreadRunnerParam* pusr = static_cast<ThreadRunnerParam*>(usr);
|
||||
ThreadRunnerParam param = *pusr;
|
||||
delete pusr;
|
||||
|
||||
param.ctx->run(param.timeToRun);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ServerContext::shared_pointer startPVAServer(String const & providerNames, int timeToRun, bool runInSeparateThread, bool printInfo)
|
||||
{
|
||||
ServerContextImpl::shared_pointer ctx = ServerContextImpl::create();
|
||||
|
||||
// do not override configuration
|
||||
if (!ctx->isChannelProviderNamePreconfigured())
|
||||
ctx->setChannelProviderName(providerNames);
|
||||
|
||||
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
|
||||
ctx->initialize(channelAccess);
|
||||
|
||||
if (printInfo)
|
||||
ctx->printInfo();
|
||||
|
||||
|
||||
if (runInSeparateThread)
|
||||
{
|
||||
// delete left to the thread
|
||||
auto_ptr<ThreadRunnerParam> param(new ThreadRunnerParam());
|
||||
param->ctx = ctx;
|
||||
param->timeToRun = timeToRun;
|
||||
|
||||
// TODO can this fail?
|
||||
epicsThreadCreate("startPVAServer",
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
threadRunner, param.get());
|
||||
|
||||
param.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->run(timeToRun);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef SERVERCONTEXT_H_
|
||||
#define SERVERCONTEXT_H_
|
||||
|
||||
#include <pv/remote.h>
|
||||
#include <pv/beaconServerStatusProvider.h>
|
||||
#include <pv/pvaConstants.h>
|
||||
#include <pv/pvaVersion.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/blockingUDP.h>
|
||||
#include <pv/blockingTCP.h>
|
||||
#include <pv/beaconEmitter.h>
|
||||
#include <pv/logger.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
/**
|
||||
* The class representing a PVA Server context.
|
||||
*/
|
||||
class epicsShareClass ServerContext
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerContext> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerContext> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ServerContext() {};
|
||||
/**
|
||||
* Get context implementation version.
|
||||
* @return version of the context implementation.
|
||||
*/
|
||||
virtual const Version& getVersion() = 0;
|
||||
|
||||
/**
|
||||
* Set <code>ChannelAccess</code> implementation and initialize server.
|
||||
* @param channelAccess implementation of channel access to be served.
|
||||
*/
|
||||
virtual void initialize(ChannelAccess::shared_pointer const & channelAccess) = 0;
|
||||
|
||||
/**
|
||||
* Run server (process events).
|
||||
* @param seconds time in seconds the server will process events (method will block), if <code>0</code>
|
||||
* the method would block until <code>destroy()</code> is called.
|
||||
* @throws BaseException if server is already destroyed.
|
||||
*/
|
||||
virtual void run(epics::pvData::int32 seconds) = 0;
|
||||
|
||||
/**
|
||||
* Shutdown (stop executing run() method) of this context.
|
||||
* After shutdown Context cannot be rerun again, destroy() has to be called to clear all used resources.
|
||||
* @throws BaseException if the context has been destroyed.
|
||||
*/
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
/**
|
||||
* Clear all resources attached to this context.
|
||||
* @throws BaseException if the context has been destroyed.
|
||||
*/
|
||||
virtual void destroy() = 0;
|
||||
|
||||
/**
|
||||
* Prints detailed information about the context to the standard output stream.
|
||||
*/
|
||||
virtual void printInfo() = 0;
|
||||
|
||||
/**
|
||||
* Prints detailed information about the context to the specified output stream.
|
||||
* @param str stream to which to print the info
|
||||
*/
|
||||
virtual void printInfo(std::ostream& str) = 0;
|
||||
|
||||
/**
|
||||
* Dispose (destroy) server context.
|
||||
* This calls <code>destroy()</code> and silently handles all exceptions.
|
||||
*/
|
||||
virtual void dispose() = 0;
|
||||
|
||||
// ************************************************************************** //
|
||||
// **************************** [ Plugins ] ********************************* //
|
||||
// ************************************************************************** //
|
||||
|
||||
/**
|
||||
* Set beacon server status provider.
|
||||
* @param beaconServerStatusProvider <code>BeaconServerStatusProvider</code> implementation to set.
|
||||
*/
|
||||
virtual void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer const & beaconServerStatusProvider) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class epicsShareClass ServerContextImpl :
|
||||
public ServerContext,
|
||||
public Context,
|
||||
public ResponseHandlerFactory,
|
||||
public std::tr1::enable_shared_from_this<ServerContextImpl>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerContextImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerContextImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerContextImpl();
|
||||
public:
|
||||
static shared_pointer create();
|
||||
|
||||
virtual ~ServerContextImpl();
|
||||
|
||||
//**************** derived from ServerContext ****************//
|
||||
const Version& getVersion();
|
||||
void initialize(ChannelAccess::shared_pointer const & channelAccess);
|
||||
void run(epics::pvData::int32 seconds);
|
||||
void shutdown();
|
||||
void destroy();
|
||||
void printInfo();
|
||||
void printInfo(std::ostream& str);
|
||||
void dispose();
|
||||
void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer const & beaconServerStatusProvider);
|
||||
//**************** derived from Context ****************//
|
||||
epics::pvData::Timer::shared_pointer getTimer();
|
||||
Channel::shared_pointer getChannel(pvAccessID id);
|
||||
Transport::shared_pointer getSearchTransport();
|
||||
Configuration::shared_pointer getConfiguration();
|
||||
TransportRegistry::shared_pointer getTransportRegistry();
|
||||
|
||||
std::auto_ptr<ResponseHandler> createResponseHandler();
|
||||
virtual void newServerDetected();
|
||||
|
||||
/**
|
||||
* Version.
|
||||
*/
|
||||
static const Version VERSION;
|
||||
|
||||
|
||||
/**
|
||||
* Server state enum.
|
||||
*/
|
||||
enum State {
|
||||
/**
|
||||
* State value of non-initialized context.
|
||||
*/
|
||||
NOT_INITIALIZED,
|
||||
|
||||
/**
|
||||
* State value of initialized context.
|
||||
*/
|
||||
INITIALIZED,
|
||||
|
||||
/**
|
||||
* State value of running context.
|
||||
*/
|
||||
RUNNING,
|
||||
|
||||
/**
|
||||
* State value of shutdown (once running) context.
|
||||
*/
|
||||
SHUTDOWN,
|
||||
|
||||
/**
|
||||
* State value of destroyed context.
|
||||
*/
|
||||
DESTROYED
|
||||
};
|
||||
/**
|
||||
* Names of the enum <code>State</code>
|
||||
*/
|
||||
static const char* StateNames[];
|
||||
|
||||
/**
|
||||
* Get initialization status.
|
||||
* @return initialization status.
|
||||
*/
|
||||
bool isInitialized();
|
||||
|
||||
/**
|
||||
* Get destruction status.
|
||||
* @return destruction status.
|
||||
*/
|
||||
bool isDestroyed();
|
||||
|
||||
/**
|
||||
* Get beacon address list.
|
||||
* @return beacon address list.
|
||||
*/
|
||||
std::string getBeaconAddressList();
|
||||
|
||||
/**
|
||||
* Get beacon address list auto flag.
|
||||
* @return beacon address list auto flag.
|
||||
*/
|
||||
bool isAutoBeaconAddressList();
|
||||
|
||||
/**
|
||||
* Get beacon period (in seconds).
|
||||
* @return beacon period (in seconds).
|
||||
*/
|
||||
float getBeaconPeriod();
|
||||
|
||||
/**
|
||||
* Get receiver buffer (payload) size.
|
||||
* @return max payload size.
|
||||
*/
|
||||
epics::pvData::int32 getReceiveBufferSize();
|
||||
|
||||
/**
|
||||
* Get server port.
|
||||
* @return server port.
|
||||
*/
|
||||
epics::pvData::int32 getServerPort();
|
||||
|
||||
/**
|
||||
* Set server port number.
|
||||
* @param port new server port number.
|
||||
*/
|
||||
void setServerPort(epics::pvData::int32 port);
|
||||
|
||||
/**
|
||||
* Get broadcast port.
|
||||
* @return broadcast port.
|
||||
*/
|
||||
epics::pvData::int32 getBroadcastPort();
|
||||
|
||||
/**
|
||||
* Get ignore search address list.
|
||||
* @return ignore search address list.
|
||||
*/
|
||||
std::string getIgnoreAddressList();
|
||||
|
||||
/**
|
||||
* Get registered beacon server status provider.
|
||||
* @return registered beacon server status provider.
|
||||
*/
|
||||
BeaconServerStatusProvider::shared_pointer getBeaconServerStatusProvider();
|
||||
|
||||
/**
|
||||
* Get server newtwork (IP) address.
|
||||
* @return server network (IP) address, <code>NULL</code> if not bounded.
|
||||
*/
|
||||
osiSockAddr* getServerInetAddress();
|
||||
|
||||
/**
|
||||
* Broadcast transport.
|
||||
* @return broadcast transport.
|
||||
*/
|
||||
BlockingUDPTransport::shared_pointer getBroadcastTransport();
|
||||
|
||||
/**
|
||||
* Get channel access implementation.
|
||||
* @return channel access implementation.
|
||||
*/
|
||||
ChannelAccess::shared_pointer getChannelAccess();
|
||||
|
||||
/**
|
||||
* Get channel provider name.
|
||||
* @return channel provider name.
|
||||
*/
|
||||
std::string getChannelProviderName();
|
||||
|
||||
/**
|
||||
* Set channel provider name.
|
||||
* This method can only be called before initialize.
|
||||
*/
|
||||
void setChannelProviderName(std::string providerName);
|
||||
|
||||
/**
|
||||
* Get channel providers.
|
||||
* @return channel providers.
|
||||
*/
|
||||
std::vector<ChannelProvider::shared_pointer> getChannelProviders();
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if channel provider name is provided by configuration (e.g. system env. var.).
|
||||
* @return <code>true</code> if channel provider name is provided by configuration (e.g. system env. var.)
|
||||
*/
|
||||
bool isChannelProviderNamePreconfigured();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialization status.
|
||||
*/
|
||||
State _state;
|
||||
|
||||
/**
|
||||
* A space-separated list of broadcast address which to send beacons.
|
||||
* Each address must be of the form: ip.number:port or host.name:port
|
||||
*/
|
||||
std::string _beaconAddressList;
|
||||
|
||||
/**
|
||||
* A space-separated list of address from which to ignore name resolution requests.
|
||||
* Each address must be of the form: ip.number:port or host.name:port
|
||||
*/
|
||||
std::string _ignoreAddressList;
|
||||
|
||||
/**
|
||||
* Define whether or not the network interfaces should be discovered at runtime.
|
||||
*/
|
||||
bool _autoBeaconAddressList;
|
||||
|
||||
/**
|
||||
* Period in second between two beacon signals.
|
||||
*/
|
||||
float _beaconPeriod;
|
||||
|
||||
/**
|
||||
* Broadcast port number to listen to.
|
||||
*/
|
||||
epics::pvData::int32 _broadcastPort;
|
||||
|
||||
/**
|
||||
* Port number for the server to listen to.
|
||||
*/
|
||||
epics::pvData::int32 _serverPort;
|
||||
|
||||
/**
|
||||
* Length in bytes of the maximum buffer (payload) size that may pass through PVA.
|
||||
*/
|
||||
epics::pvData::int32 _receiveBufferSize;
|
||||
|
||||
/**
|
||||
* Timer.
|
||||
*/
|
||||
epics::pvData::Timer::shared_pointer _timer;
|
||||
|
||||
/**
|
||||
* Broadcast transport needed for channel searches.
|
||||
*/
|
||||
BlockingUDPTransport::shared_pointer _broadcastTransport;
|
||||
|
||||
/**
|
||||
* Beacon emitter.
|
||||
*/
|
||||
BeaconEmitter::shared_pointer _beaconEmitter;
|
||||
|
||||
/**
|
||||
* PVAS acceptor (accepts PVA virtual circuit).
|
||||
*/
|
||||
BlockingTCPAcceptor::shared_pointer _acceptor;
|
||||
|
||||
/**
|
||||
* PVA transport (virtual circuit) registry.
|
||||
* This registry contains all active transports - connections to PVA servers.
|
||||
*/
|
||||
TransportRegistry::shared_pointer _transportRegistry;
|
||||
|
||||
/**
|
||||
* Channel access.
|
||||
*/
|
||||
ChannelAccess::shared_pointer _channelAccess;
|
||||
|
||||
/**
|
||||
* Channel provider name.
|
||||
*/
|
||||
std::string _channelProviderNames;
|
||||
|
||||
/**
|
||||
* Channel provider.
|
||||
*/
|
||||
std::vector<ChannelProvider::shared_pointer> _channelProviders;
|
||||
|
||||
/**
|
||||
* Run mutex.
|
||||
*/
|
||||
epics::pvData::Mutex _mutex;
|
||||
|
||||
/**
|
||||
* Run event.
|
||||
*/
|
||||
epics::pvData::Event _runEvent;
|
||||
|
||||
/**
|
||||
* Beacon server status provider interface (optional).
|
||||
*/
|
||||
BeaconServerStatusProvider::shared_pointer _beaconServerStatusProvider;
|
||||
|
||||
/**
|
||||
* Initialize logger.
|
||||
*/
|
||||
void initializeLogger();
|
||||
|
||||
/**
|
||||
* Load configuration.
|
||||
*/
|
||||
void loadConfiguration();
|
||||
|
||||
/**
|
||||
* Internal initialization.
|
||||
*/
|
||||
void internalInitialize();
|
||||
|
||||
/**
|
||||
* Initialize broadcast DP transport (broadcast socket and repeater connection).
|
||||
*/
|
||||
void initializeBroadcastTransport();
|
||||
|
||||
/**
|
||||
* Internal destroy.
|
||||
*/
|
||||
void internalDestroy();
|
||||
|
||||
/**
|
||||
* Destroy all transports.
|
||||
*/
|
||||
void destroyAllTransports();
|
||||
|
||||
Configuration::shared_pointer configuration;
|
||||
};
|
||||
|
||||
epicsShareExtern ServerContext::shared_pointer startPVAServer(
|
||||
epics::pvData::String const & providerNames = PVACCESS_ALL_PROVIDERS,
|
||||
int timeToRun = 0,
|
||||
bool runInSeparateThread = false,
|
||||
bool printInfo = false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SERVERCONTEXT_H_ */
|
||||
Reference in New Issue
Block a user