ca provider skeleton done, connection, getField
This commit is contained in:
@@ -87,7 +87,9 @@ LIBSRCS += rpcClient.cpp
|
||||
|
||||
SRC_DIRS += $(PVACCESS)/ca
|
||||
INC += caProvider.h
|
||||
INC += caChannel.h
|
||||
LIBSRCS += caProvider.cpp
|
||||
LIBSRCS += caChannel.cpp
|
||||
|
||||
SRC_DIRS += $(PVACCESS)/mb
|
||||
INC += pvAccessMB.h
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
/**
|
||||
* 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/logger.h>
|
||||
#include <pv/caChannel.h>
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
#define EXCEPTION_GUARD(code) try { code; } \
|
||||
catch (std::exception &e) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \
|
||||
catch (...) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); }
|
||||
|
||||
#define PVACCESS_REFCOUNT_MONITOR_DEFINE(name)
|
||||
#define PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(name)
|
||||
#define PVACCESS_REFCOUNT_MONITOR_DESTRUCT(name)
|
||||
|
||||
PVACCESS_REFCOUNT_MONITOR_DEFINE(caChannel);
|
||||
|
||||
CAChannel::shared_pointer CAChannel::create(ChannelProvider::shared_pointer const & channelProvider,
|
||||
epics::pvData::String const & channelName,
|
||||
short priority,
|
||||
ChannelRequester::shared_pointer const & channelRequester)
|
||||
{
|
||||
CAChannel::shared_pointer thisPtr(new CAChannel(channelProvider, channelRequester));
|
||||
thisPtr->activate(channelName, priority);
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
static void ca_connection_handler(struct connection_handler_args args)
|
||||
{
|
||||
CAChannel *channel = static_cast<CAChannel*>(ca_puser(args.chid));
|
||||
|
||||
if (args.op == CA_OP_CONN_UP)
|
||||
channel->connected();
|
||||
else if (args.op == CA_OP_CONN_DOWN)
|
||||
channel->disconnected();
|
||||
}
|
||||
|
||||
void CAChannel::connected()
|
||||
{
|
||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
PVStructure::shared_pointer pvStructure;
|
||||
|
||||
// TODO
|
||||
String properties("value,timeStamp");
|
||||
// TODO arrays
|
||||
unsigned elementCount = ca_element_count(channelID);
|
||||
|
||||
chtype type = ca_field_type(channelID);
|
||||
switch (type)
|
||||
{
|
||||
case DBR_CHAR:
|
||||
// byte
|
||||
break;
|
||||
case DBR_SHORT:
|
||||
// short
|
||||
break;
|
||||
case DBR_ENUM:
|
||||
// enum
|
||||
break;
|
||||
case DBR_LONG:
|
||||
// int
|
||||
break;
|
||||
case DBR_FLOAT:
|
||||
// float
|
||||
break;
|
||||
case DBR_DOUBLE:
|
||||
// double
|
||||
pvStructure = (elementCount > 1) ?
|
||||
standardPVField->scalarArray(pvDouble, properties) :
|
||||
standardPVField->scalar(pvDouble, properties);
|
||||
break;
|
||||
case DBR_STRING:
|
||||
// string
|
||||
break;
|
||||
default:
|
||||
// TODO !!!
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO thread sync
|
||||
this->pvStructure = pvStructure;
|
||||
|
||||
// TODO call channelCreated if structure has changed
|
||||
EXCEPTION_GUARD(channelRequester->channelStateChange(shared_from_this(), Channel::CONNECTED));
|
||||
}
|
||||
|
||||
void CAChannel::disconnected()
|
||||
{
|
||||
EXCEPTION_GUARD(channelRequester->channelStateChange(shared_from_this(), Channel::DISCONNECTED));
|
||||
}
|
||||
|
||||
CAChannel::CAChannel(ChannelProvider::shared_pointer const & _channelProvider,
|
||||
ChannelRequester::shared_pointer const & _channelRequester) :
|
||||
channelProvider(_channelProvider),
|
||||
channelRequester(_channelRequester)
|
||||
{
|
||||
PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(caChannel);
|
||||
}
|
||||
|
||||
void CAChannel::activate(epics::pvData::String const & channelName, short priority)
|
||||
{
|
||||
int result = ca_create_channel(channelName.c_str(),
|
||||
ca_connection_handler,
|
||||
this,
|
||||
priority, // TODO mapping
|
||||
&channelID);
|
||||
if (result == ECA_NORMAL)
|
||||
{
|
||||
// TODO be sure that ca_connection_handler is not called before this call
|
||||
EXCEPTION_GUARD(channelRequester->channelCreated(Status::Ok, shared_from_this()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(result)));
|
||||
EXCEPTION_GUARD(channelRequester->channelCreated(errorStatus, shared_from_this()));
|
||||
}
|
||||
}
|
||||
|
||||
CAChannel::~CAChannel()
|
||||
{
|
||||
PVACCESS_REFCOUNT_MONITOR_DESTRUCT(caChannel);
|
||||
}
|
||||
|
||||
|
||||
std::tr1::shared_ptr<ChannelProvider> CAChannel::getProvider()
|
||||
{
|
||||
return channelProvider;
|
||||
}
|
||||
|
||||
|
||||
epics::pvData::String CAChannel::getRemoteAddress()
|
||||
{
|
||||
return epics::pvData::String(ca_host_name(channelID));
|
||||
}
|
||||
|
||||
|
||||
static Channel::ConnectionState cs2CS[] =
|
||||
{
|
||||
Channel::NEVER_CONNECTED, // cs_never_conn
|
||||
Channel::DISCONNECTED, // cs_prev_conn
|
||||
Channel::CONNECTED, // cs_conn
|
||||
Channel::DESTROYED // cs_closed
|
||||
};
|
||||
|
||||
Channel::ConnectionState CAChannel::getConnectionState()
|
||||
{
|
||||
return cs2CS[ca_state(channelID)];
|
||||
}
|
||||
|
||||
|
||||
epics::pvData::String CAChannel::getChannelName()
|
||||
{
|
||||
return epics::pvData::String(ca_name(channelID));
|
||||
}
|
||||
|
||||
|
||||
std::tr1::shared_ptr<ChannelRequester> CAChannel::getChannelRequester()
|
||||
{
|
||||
return channelRequester;
|
||||
}
|
||||
|
||||
|
||||
bool CAChannel::isConnected()
|
||||
{
|
||||
return (ca_state(channelID) == cs_conn);
|
||||
}
|
||||
|
||||
|
||||
void CAChannel::getField(GetFieldRequester::shared_pointer const & requester,
|
||||
epics::pvData::String const & subField)
|
||||
{
|
||||
PVField::shared_pointer pvField =
|
||||
subField.empty() ?
|
||||
std::tr1::static_pointer_cast<PVField>(pvStructure) :
|
||||
pvStructure->getSubField(subField);
|
||||
|
||||
if (pvField)
|
||||
{
|
||||
EXCEPTION_GUARD(requester->getDone(Status::Ok, pvField->getField()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "field '" + subField + "' not found");
|
||||
EXCEPTION_GUARD(requester->getDone(errorStatus, FieldConstPtr()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AccessRights CAChannel::getAccessRights(epics::pvData::PVField::shared_pointer const & /*pvField*/)
|
||||
{
|
||||
if (ca_write_access(channelID))
|
||||
return readWrite;
|
||||
else if (ca_read_access(channelID))
|
||||
return read;
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
|
||||
ChannelProcess::shared_pointer CAChannel::createChannelProcess(
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented");
|
||||
ChannelProcess::shared_pointer nullChannelProcess;
|
||||
EXCEPTION_GUARD(channelProcessRequester->channelProcessConnect(errorStatus, nullChannelProcess));
|
||||
return nullChannelProcess;
|
||||
}
|
||||
|
||||
ChannelGet::shared_pointer CAChannel::createChannelGet(
|
||||
ChannelGetRequester::shared_pointer const & channelGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented");
|
||||
ChannelGet::shared_pointer nullChannelGet;
|
||||
EXCEPTION_GUARD(channelGetRequester->channelGetConnect(errorStatus, nullChannelGet,
|
||||
PVStructure::shared_pointer(), BitSet::shared_pointer()));
|
||||
return nullChannelGet;
|
||||
}
|
||||
|
||||
|
||||
ChannelPut::shared_pointer CAChannel::createChannelPut(
|
||||
ChannelPutRequester::shared_pointer const & channelPutRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented");
|
||||
ChannelPut::shared_pointer nullChannelPut;
|
||||
EXCEPTION_GUARD(channelPutRequester->channelPutConnect(errorStatus, nullChannelPut,
|
||||
PVStructure::shared_pointer(), BitSet::shared_pointer()));
|
||||
return nullChannelPut;
|
||||
}
|
||||
|
||||
ChannelPutGet::shared_pointer CAChannel::createChannelPutGet(
|
||||
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not supported");
|
||||
ChannelPutGet::shared_pointer nullChannelPutGet;
|
||||
EXCEPTION_GUARD(channelPutGetRequester->channelPutGetConnect(errorStatus, nullChannelPutGet,
|
||||
PVStructure::shared_pointer(), PVStructure::shared_pointer()));
|
||||
return nullChannelPutGet;
|
||||
}
|
||||
|
||||
|
||||
ChannelRPC::shared_pointer CAChannel::createChannelRPC(
|
||||
ChannelRPCRequester::shared_pointer const & channelRPCRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not supported");
|
||||
ChannelRPC::shared_pointer nullChannelRPC;
|
||||
EXCEPTION_GUARD(channelRPCRequester->channelRPCConnect(errorStatus, nullChannelRPC));
|
||||
return nullChannelRPC;
|
||||
}
|
||||
|
||||
|
||||
epics::pvData::Monitor::shared_pointer CAChannel::createMonitor(
|
||||
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented");
|
||||
Monitor::shared_pointer nullMonitor;
|
||||
EXCEPTION_GUARD(monitorRequester->monitorConnect(errorStatus, nullMonitor,
|
||||
Structure::shared_pointer()));
|
||||
return nullMonitor;
|
||||
}
|
||||
|
||||
|
||||
ChannelArray::shared_pointer CAChannel::createChannelArray(
|
||||
ChannelArrayRequester::shared_pointer const & channelArrayRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not supported");
|
||||
ChannelArray::shared_pointer nullChannelArray;
|
||||
EXCEPTION_GUARD(channelArrayRequester->channelArrayConnect(errorStatus, nullChannelArray,
|
||||
PVArray::shared_pointer()));
|
||||
return nullChannelArray;
|
||||
}
|
||||
|
||||
|
||||
void CAChannel::printInfo()
|
||||
{
|
||||
String info;
|
||||
printInfo(&info);
|
||||
std::cout << info.c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void CAChannel::printInfo(epics::pvData::StringBuilder out)
|
||||
{
|
||||
out->append( "CHANNEL : "); out->append(getChannelName());
|
||||
ConnectionState state = getConnectionState();
|
||||
out->append("\nSTATE : "); out->append(ConnectionStateNames[state]);
|
||||
if (state == CONNECTED)
|
||||
{
|
||||
out->append("\nADDRESS : "); out->append(getRemoteAddress());
|
||||
//out->append("\nRIGHTS : "); out->append(getAccessRights());
|
||||
}
|
||||
out->append("\n");
|
||||
}
|
||||
|
||||
|
||||
/* --------------- epics::pvData::Requester --------------- */
|
||||
|
||||
|
||||
String CAChannel::getRequesterName()
|
||||
{
|
||||
return getChannelName();
|
||||
}
|
||||
|
||||
|
||||
void CAChannel::message(String const & message,MessageType messageType)
|
||||
{
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
|
||||
void CAChannel::destroy()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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 CACHANNEL_H
|
||||
#define CACHANNEL_H
|
||||
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
/* for CA */
|
||||
#include <cadef.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class CAChannel :
|
||||
public Channel,
|
||||
public std::tr1::enable_shared_from_this<CAChannel>
|
||||
{
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(CAChannel);
|
||||
|
||||
static CAChannel::shared_pointer create(ChannelProvider::shared_pointer const & channelProvider,
|
||||
epics::pvData::String const & channelName,
|
||||
short priority,
|
||||
ChannelRequester::shared_pointer const & channelRequester);
|
||||
|
||||
virtual ~CAChannel();
|
||||
|
||||
void connected();
|
||||
void disconnected();
|
||||
|
||||
/* --------------- epics::pvAccess::Channel --------------- */
|
||||
|
||||
virtual std::tr1::shared_ptr<ChannelProvider> getProvider();
|
||||
virtual epics::pvData::String getRemoteAddress();
|
||||
virtual ConnectionState getConnectionState();
|
||||
virtual epics::pvData::String getChannelName();
|
||||
virtual std::tr1::shared_ptr<ChannelRequester> getChannelRequester();
|
||||
virtual bool isConnected();
|
||||
|
||||
virtual void getField(GetFieldRequester::shared_pointer const & requester,epics::pvData::String const & subField);
|
||||
|
||||
virtual AccessRights getAccessRights(epics::pvData::PVField::shared_pointer const & pvField);
|
||||
|
||||
virtual ChannelProcess::shared_pointer createChannelProcess(
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ChannelGet::shared_pointer createChannelGet(
|
||||
ChannelGetRequester::shared_pointer const & channelGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ChannelPut::shared_pointer createChannelPut(
|
||||
ChannelPutRequester::shared_pointer const & channelPutRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ChannelPutGet::shared_pointer createChannelPutGet(
|
||||
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ChannelRPC::shared_pointer createChannelRPC(
|
||||
ChannelRPCRequester::shared_pointer const & channelRPCRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual epics::pvData::Monitor::shared_pointer createMonitor(
|
||||
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ChannelArray::shared_pointer createChannelArray(
|
||||
ChannelArrayRequester::shared_pointer const & channelArrayRequester,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual void printInfo();
|
||||
|
||||
virtual void printInfo(epics::pvData::StringBuilder out);
|
||||
|
||||
/* --------------- epics::pvData::Requester --------------- */
|
||||
|
||||
virtual epics::pvData::String getRequesterName();
|
||||
|
||||
virtual void message(epics::pvData::String const & message, epics::pvData::MessageType messageType);
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
private:
|
||||
|
||||
CAChannel(ChannelProvider::shared_pointer const & channelProvider,
|
||||
ChannelRequester::shared_pointer const & channelRequester);
|
||||
void activate(epics::pvData::String const & channelName, short priority);
|
||||
|
||||
// TODO weak_ptr usage?
|
||||
ChannelProvider::shared_pointer channelProvider;
|
||||
ChannelRequester::shared_pointer channelRequester;
|
||||
|
||||
chid channelID;
|
||||
epics::pvData::PVStructure::shared_pointer pvStructure;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* CACHANNEL_H */
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#include <pv/logger.h>
|
||||
#include <pv/caProvider.h>
|
||||
#include <pv/caChannel.h>
|
||||
|
||||
/* for CA */
|
||||
#include <cadef.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
@@ -70,11 +72,7 @@ Channel::shared_pointer CAChannelProvider::createChannel(
|
||||
if (!address.empty())
|
||||
throw std::invalid_argument("CA does not support 'address' parameter");
|
||||
|
||||
// TODO
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented");
|
||||
Channel::shared_pointer nullChannel;
|
||||
EXCEPTION_GUARD(channelRequester->channelCreated(errorStatus, nullChannel));
|
||||
return nullChannel;
|
||||
return CAChannel::create(shared_from_this(), channelName, priority, channelRequester);
|
||||
|
||||
// NOTE it's up to internal code to respond w/ error to requester and return 0 in case of errors
|
||||
}
|
||||
@@ -94,7 +92,7 @@ void CAChannelProvider::poll()
|
||||
void CAChannelProvider::initialize()
|
||||
{
|
||||
/* Create Channel Access */
|
||||
int result = ca_context_create(ca_disable_preemptive_callback);
|
||||
int result = ca_context_create(ca_enable_preemptive_callback);
|
||||
if (result != ECA_NORMAL) {
|
||||
throw std::runtime_error(std::string("CA error %s occurred while trying "
|
||||
"to start channel access:") + ca_message(result));
|
||||
@@ -103,9 +101,12 @@ void CAChannelProvider::initialize()
|
||||
// TODO create a ca_poll thread
|
||||
}
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
ChannelProvider::shared_pointer createCAChannelProvider()
|
||||
{
|
||||
ChannelProvider::shared_pointer ptr(new CAChannelProvider());
|
||||
return ptr;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class CAChannelProvider :
|
||||
public ChannelProvider
|
||||
public ChannelProvider,
|
||||
public std::tr1::enable_shared_from_this<CAChannelProvider>
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
// TODO add write-only?
|
||||
// change names
|
||||
enum AccessRights {
|
||||
/**
|
||||
* Neither read or write access is allowed.
|
||||
|
||||
@@ -189,3 +189,5 @@ TODO
|
||||
testApp/remote/pvinfo.cpp
|
||||
pvAccessApp/ca/caProvider.h
|
||||
pvAccessApp/ca/caProvider.cpp
|
||||
pvAccessApp/ca/caChannel.h
|
||||
pvAccessApp/ca/caChannel.cpp
|
||||
|
||||
Reference in New Issue
Block a user