interim commit. pvCopy how works

This commit is contained in:
Marty Kraimer
2013-04-04 07:21:52 -04:00
parent d96ccf3776
commit 500ecfd4ad
23 changed files with 2551 additions and 898 deletions

View File

@@ -1,5 +1,6 @@
TOP = ..
include $(TOP)/configure/CONFIG
DIRS += record
DIRS += pvCopy
include $(TOP)/configure/RULES_DIRS

12
test/pvCopy/Makefile Normal file
View File

@@ -0,0 +1,12 @@
TOP=../..
include $(TOP)/configure/CONFIG
PROD_HOST += testPVCopy
testPVCopy_SRCS += testPVCopy.cpp
testPVCopy_LIBS += pvDatabase pvAccess pvData Com
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

409
test/pvCopy/testPVCopy.cpp Normal file
View File

@@ -0,0 +1,409 @@
/*testPVCopyMain.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <epicsStdio.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/pvCopy.h>
#include <pv/powerSupplyRecordTest.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
class MyRequester;
typedef std::tr1::shared_ptr<MyRequester> MyRequesterPtr;
class MyRequester : public Requester {
public:
POINTER_DEFINITIONS(MyRequester);
MyRequester(String const &requesterName)
: requesterName(requesterName)
{}
virtual ~MyRequester() {}
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message,MessageType messageType)
{
cout << message << endl;
}
private:
String requesterName;
};
static PVRecordPtr createScalar(
String const & recordName,
ScalarType scalarType,
String const & properties)
{
PVStructurePtr pvStructure = getStandardPVField()->scalar(scalarType,properties);
return PVRecord::create(recordName,pvStructure);
}
static PVRecordPtr createScalarArray(
String const & recordName,
ScalarType scalarType,
String const & properties)
{
PVStructurePtr pvStructure = getStandardPVField()->scalarArray(scalarType,properties);
return PVRecord::create(recordName,pvStructure);
}
static PowerSupplyRecordTestPtr createPowerSupply(String const & recordName)
{
FieldCreatePtr fieldCreate = getFieldCreate();
StandardFieldPtr standardField = getStandardField();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
size_t nfields = 5;
StringArray names;
names.reserve(nfields);
FieldConstPtrArray powerSupply;
powerSupply.reserve(nfields);
names.push_back("alarm");
powerSupply.push_back(standardField->alarm());
names.push_back("timeStamp");
powerSupply.push_back(standardField->timeStamp());
String properties("alarm,display");
names.push_back("voltage");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
names.push_back("power");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
names.push_back("current");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
return PowerSupplyRecordTest::create(recordName,
pvDataCreate->createPVStructure(
fieldCreate->createStructure(names,powerSupply)));
}
static void testPVScalar(
String const & valueNameRecord,
String const & valueNameCopy,
PVRecordPtr const & pvRecord,
PVCopyPtr const & pvCopy)
{
PVRecordFieldPtr pvRecordField;
PVStructurePtr pvStructureRecord;
PVStructurePtr pvStructureCopy;
PVFieldPtr pvField;
PVScalarPtr pvValueRecord;
PVScalarPtr pvValueCopy;
BitSetPtr bitSet;
String builder;
size_t offset;
ConvertPtr convert = getConvert();
pvRecord->lock_guard();
cout << endl;
pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure();
pvField = pvStructureRecord->getSubField(valueNameRecord);
pvValueRecord = static_pointer_cast<PVScalar>(pvField);
convert->fromDouble(pvValueRecord,.04);
StructureConstPtr structure = pvCopy->getStructure();
builder.clear(); structure->toString(&builder);
cout << "structure from copy" << endl << builder << endl;
pvStructureCopy = pvCopy->createPVStructure();
pvField = pvStructureCopy->getSubField(valueNameCopy);
pvValueCopy = static_pointer_cast<PVScalar>(pvField);
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
pvCopy->initCopy(pvStructureCopy, bitSet, true);
cout << "after initCopy pvValueCopy " << convert->toDouble(pvValueCopy);
cout << endl;
convert->fromDouble(pvValueRecord,.06);
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet,true);
cout << "after put(.06) pvValueCopy " << convert->toDouble(pvValueCopy);
builder.clear();
bitSet->toString(&builder);
cout << " bitSet " << builder;
cout << endl;
pvRecordField = pvRecord->findPVRecordField(pvValueRecord);
offset = pvCopy->getCopyOffset(pvRecordField);
cout << "getCopyOffset() " << offset;
cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset();
cout << " pvValueRecord->getOffset() " << pvValueRecord->getFieldOffset();
cout << " bitSet " << builder;
cout << endl;
bitSet->clear();
convert->fromDouble(pvValueRecord,1.0);
builder.clear();
bitSet->toString(&builder);
cout << "before updateCopyFromBitSet";
cout << " recordValue " << convert->toDouble(pvValueRecord);
cout << " copyValue " << convert->toDouble(pvValueCopy);
cout << " bitSet " << builder;
cout << endl;
bitSet->set(0);
pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet,true);
cout << "after updateCopyFromBitSet";
cout << " recordValue " << convert->toDouble(pvValueRecord);
cout << " copyValue " << convert->toDouble(pvValueCopy);
cout << " bitSet " << builder;
cout << endl;
convert->fromDouble(pvValueCopy,2.0);
bitSet->set(0);
cout << "before updateRecord";
cout << " recordValue " << convert->toDouble(pvValueRecord);
cout << " copyValue " << convert->toDouble(pvValueCopy);
cout << " bitSet " << builder;
cout << endl;
pvCopy->updateRecord(pvStructureCopy,bitSet,true);
cout << "after updateRecord";
cout << " recordValue " << convert->toDouble(pvValueRecord);
cout << " copyValue " << convert->toDouble(pvValueCopy);
cout << " bitSet " << builder;
cout << endl;
}
static void testPVScalarArray(
ScalarType scalarType,
String const & valueNameRecord,
String const & valueNameCopy,
PVRecordPtr const & pvRecord,
PVCopyPtr const & pvCopy)
{
PVRecordFieldPtr pvRecordField;
PVStructurePtr pvStructureRecord;
PVStructurePtr pvStructureCopy;
PVScalarArrayPtr pvValueRecord;
PVScalarArrayPtr pvValueCopy;
BitSetPtr bitSet;
String builder;
size_t offset;
ConvertPtr convert = getConvert();
size_t n = 5;
DoubleArray values(n);
pvRecord->lock_guard();
cout << endl;
pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure();
pvValueRecord = pvStructureRecord->getScalarArrayField(valueNameRecord,scalarType);
for(size_t i=0; i<n; i++) values[i] = i;
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
StructureConstPtr structure = pvCopy->getStructure();
builder.clear(); structure->toString(&builder);
cout << "structure from copy" << endl << builder << endl;
pvStructureCopy = pvCopy->createPVStructure();
pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType);
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
pvCopy->initCopy(pvStructureCopy, bitSet, true);
builder.clear(); pvValueCopy->toString(&builder);
cout << "after initCopy pvValueCopy " << builder << endl;
cout << endl;
for(size_t i=0; i<n; i++) values[i] = i + .06;
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet,true);
builder.clear(); pvValueCopy->toString(&builder);
cout << "after put(i+ .06) pvValueCopy " << builder << endl;
builder.clear();
bitSet->toString(&builder);
cout << " bitSet " << builder;
cout << endl;
pvRecordField = pvRecord->findPVRecordField(pvValueRecord);
offset = pvCopy->getCopyOffset(pvRecordField);
cout << "getCopyOffset() " << offset;
cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset();
cout << " pvValueRecord->getOffset() " << pvValueRecord->getFieldOffset();
cout << " bitSet " << builder;
cout << endl;
bitSet->clear();
for(size_t i=0; i<n; i++) values[i] = i + 1.0;
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
builder.clear();
bitSet->toString(&builder);
cout << "before updateCopyFromBitSet";
builder.clear(); pvValueRecord->toString(&builder);
cout << " recordValue " << builder << endl;
builder.clear(); pvValueCopy->toString(&builder);
cout << " copyValue " << builder << endl;
cout << " bitSet " << builder;
cout << endl;
bitSet->set(0);
pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet,true);
cout << "after updateCopyFromBitSet";
builder.clear(); pvValueRecord->toString(&builder);
cout << " recordValue " << builder << endl;
builder.clear(); pvValueCopy->toString(&builder);
cout << " copyValue " << builder << endl;
cout << " bitSet " << builder;
cout << endl;
for(size_t i=0; i<n; i++) values[i] = i + 2.0;
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
bitSet->set(0);
cout << "before updateRecord";
builder.clear(); pvValueRecord->toString(&builder);
cout << " recordValue " << builder << endl;
builder.clear(); pvValueCopy->toString(&builder);
cout << " copyValue " << builder << endl;
cout << " bitSet " << builder;
cout << endl;
pvCopy->updateRecord(pvStructureCopy,bitSet,true);
cout << "after updateRecord";
builder.clear(); pvValueRecord->toString(&builder);
cout << " recordValue " << builder << endl;
builder.clear(); pvValueCopy->toString(&builder);
cout << " copyValue " << builder << endl;
cout << " bitSet " << builder;
cout << endl;
}
static void scalarTest()
{
cout << endl << endl << "****scalarTest****" << endl;
RequesterPtr requester(new MyRequester("exampleTest"));
PVRecordPtr pvRecord;
String request;
PVStructurePtr pvRequest;
PVRecordFieldPtr pvRecordField;
PVCopyPtr pvCopy;
String builder;
String valueNameRecord;
String valueNameCopy;
pvRecord = createScalar("doubleRecord",pvDouble,"alarm,timeStamp,display");
valueNameRecord = request = "value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl;
cout << "pvRequest" << endl << builder;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "";
valueNameRecord = "value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,value";
valueNameRecord = "value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
}
static void arrayTest()
{
cout << endl << endl << "****arrayTest****" << endl;
RequesterPtr requester(new MyRequester("exampleTest"));
PVRecordPtr pvRecord;
String request;
PVStructurePtr pvRequest;
PVRecordFieldPtr pvRecordField;
PVCopyPtr pvCopy;
String builder;
String valueNameRecord;
String valueNameCopy;
pvRecord = createScalarArray("doubleArrayRecord",pvDouble,"alarm,timeStamp");
valueNameRecord = request = "value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl;
cout << "pvRequest" << endl << builder;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "";
valueNameRecord = "value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,value";
valueNameRecord = "value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
}
static void powerSupplyTest()
{
cout << endl << endl << "****powerSupplyTest****" << endl;
RequesterPtr requester(new MyRequester("exampleTest"));
PowerSupplyRecordTestPtr pvRecord;
String request;
PVStructurePtr pvRequest;
PVRecordFieldPtr pvRecordField;
PVCopyPtr pvCopy;
String builder;
String valueNameRecord;
String valueNameCopy;
pvRecord = createPowerSupply("powerSupply");
valueNameRecord = request = "power.value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl;
cout << "pvRequest" << endl << builder;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "";
valueNameRecord = "power.value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,voltage.value,power.value,current.value";
valueNameRecord = "power.value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "power";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
valueNameRecord = "power.value";
pvRequest = getCreateRequest()->createRequest(request,requester);
builder.clear(); pvRequest->toString(&builder);
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
valueNameCopy = "power.value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
}
int main(int argc,char *argv[])
{
scalarTest();
arrayTest();
powerSupplyTest();
return 0;
}

View File

@@ -2,10 +2,10 @@ TOP=../..
include $(TOP)/configure/CONFIG
PROD_HOST += testRecord
testRecord_SRCS += testRecord.cpp
testRecord_SRCS += testRecordMain.cpp
testRecord_LIBS += pvDatabase pvAccess pvData Com
PROD_HOST += testExampleRecord
testExampleRecord_SRCS += testExampleRecordMain.cpp
testExampleRecord_LIBS += pvDatabase pvAccess pvData Com
include $(TOP)/configure/RULES
#----------------------------------------

View File

@@ -0,0 +1,126 @@
/*testExampleRecordMain.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <epicsStdio.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <epicsExport.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/powerSupplyRecordTest.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
static PVStructurePtr createPowerSupply()
{
FieldCreatePtr fieldCreate = getFieldCreate();
StandardFieldPtr standardField = getStandardField();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
size_t nfields = 5;
StringArray names;
names.reserve(nfields);
FieldConstPtrArray powerSupply;
powerSupply.reserve(nfields);
names.push_back("alarm");
powerSupply.push_back(standardField->alarm());
names.push_back("timeStamp");
powerSupply.push_back(standardField->timeStamp());
String properties("alarm,display");
names.push_back("voltage");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
names.push_back("power");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
names.push_back("current");
powerSupply.push_back(standardField->scalar(pvDouble,properties));
return pvDataCreate->createPVStructure(
fieldCreate->createStructure(names,powerSupply));
}
int main(int argc,char *argv[])
{
StandardPVFieldPtr standardPVField = getStandardPVField();
String properties;
ScalarType scalarType;
String recordName;
properties = "alarm,timeStamp";
scalarType = pvDouble;
recordName = "exampleDouble";
PVStructurePtr pvStructure;
pvStructure = standardPVField->scalar(scalarType,properties);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
{
pvRecord->lock_guard();
pvRecord->process();
}
cout << "processed exampleDouble " << endl;
recordName = "powerSupplyExample";
pvStructure.reset();
pvStructure = createPowerSupply();
PowerSupplyRecordTestPtr psr =
PowerSupplyRecordTest::create(recordName,pvStructure);
if(psr.get()==NULL) {
cout << "PowerSupplyRecordTest::create failed" << endl;
return 1;
}
double voltage,power,current;
{
psr->lock_guard();
voltage = psr->getVoltage();
power = psr->getPower();
current = psr->getCurrent();
}
cout << "initial ";
cout << " voltage " << voltage ;
cout << " power " << power;
cout << " current " << current;
cout << endl;
voltage = 1.0;
power = 1.0;
cout << "before put ";
cout << " voltage " << voltage ;
cout << " power " << power;
cout << endl;
{
psr->lock_guard();
psr->put(power,voltage);
psr->process();
}
{
psr->lock_guard();
cout << "after put ";
cout << " voltage " << psr->getVoltage() ;
cout << " power " << psr->getPower();
cout << " current " << psr->getCurrent();
cout << endl;
}
return 0;
}

View File

@@ -1,90 +0,0 @@
/* testRecord.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Marty Kraimer 2011.03 */
/* This connects to a V3 record and presents the data as a PVStructure
* It provides access to value, alarm, display, and control.
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <stdexcept>
#include <memory>
#include <pv/standardPVField.h>
#include "testRecord.h"
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
TestRecord::~TestRecord(){}
PVRecordPtr TestRecord::create(
String const & recordName)
{
String properties("alarm,timeStamp,display,control,valueAlarm");
PVStructurePtr pvStructure = getStandardPVField()->scalar(pvLong,properties);
PVLongPtr pvValue = pvStructure->getLongField("value");
TestRecordPtr pvRecord(
new TestRecord(recordName,pvStructure,pvValue));
pvRecord->init();
PVFieldPtr pvField = pvStructure->getSubField("display.description");
pvRecord->immediatePutOK = pvField;
return pvRecord;
}
TestRecord::TestRecord(
String const & recordName,
PVStructurePtr const & pvStructure,
PVLongPtr const &pvValue)
: PVRecord(recordName,pvStructure),
pvValue(pvValue)
{}
void TestRecord::process(
RecordProcessRequesterPtr const &processRequester,bool alreadyLocked)
{
if(!alreadyLocked) lock();
pvValue->put(pvValue->get() + 1);
processRequester->recordProcessResult(Status::Ok);
unlock();
processRequester->recordProcessComplete();
dequeueProcessRequest(processRequester);
}
bool TestRecord::isSynchronous() {return true;}
void TestRecord::destroy()
{
PVRecord::destroy();
pvValue.reset();
immediatePutOK.reset();
}
bool TestRecord::requestImmediatePut(PVFieldPtr const &pvField)
{
if(pvField!=immediatePutOK) return false;
lock();
return true;
}
void TestRecord::immediatePutDone()
{
unlock();
}
}}

View File

@@ -1,50 +0,0 @@
/* testRecord.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#ifndef TEST_RECORD_H
#define TEST_RECORD_H
#include <string>
#include <cstring>
#include <stdexcept>
#include <memory>
#include <pv/pvDatabase.h>
namespace epics { namespace pvDatabase {
class TestRecord;
typedef std::tr1::shared_ptr<TestRecord> TestRecordPtr;
class TestRecord :
public virtual PVRecord
{
public:
POINTER_DEFINITIONS(TestRecord);
static PVRecordPtr create(
epics::pvData::String const & recordName);
virtual ~TestRecord();
virtual void process(
epics::pvDatabase::RecordProcessRequesterPtr const &processRequester,
bool alreadyLocked);
virtual bool isSynchronous();
virtual void destroy();
virtual bool requestImmediatePut(epics::pvData::PVFieldPtr const &pvField);
virtual void immediatePutDone();
private:
TestRecord(epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure,
epics::pvData::PVLongPtr const &pvValue);
epics::pvData::PVLongPtr pvValue;
epics::pvData::PVFieldPtr immediatePutOK;
};
}}
#endif /* TEST_RECORD_H */

View File

@@ -1,378 +0,0 @@
/*testRecordMain.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <epicsStdio.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <epicsExport.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/event.h>
#include "testRecord.h"
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
class MyPVListener;
typedef std::tr1::shared_ptr<MyPVListener> MyPVListenerPtr;
class MyProcessRequester;
typedef std::tr1::shared_ptr<MyProcessRequester> MyProcessRequesterPtr;
class MyPutRequester;
typedef std::tr1::shared_ptr<MyPutRequester> MyPutRequesterPtr;
class MyPVListener :
public PVListener,
public std::tr1::enable_shared_from_this<MyPVListener>
{
public:
POINTER_DEFINITIONS(PVListener);
static MyPVListenerPtr create(
String const & requesterName,
PVRecordPtr const & pvRecord,
PVRecordFieldPtr const &pvRecordField)
{
MyPVListenerPtr pvPVListener(
new MyPVListener(requesterName,pvRecord,pvRecordField));
pvPVListener->init();
return pvPVListener;
}
virtual ~MyPVListener() {}
virtual void detach(PVRecordPtr const & pvRecord)
{
printf("%s MyPVListener::detach\n",requesterName.c_str());
}
virtual void dataPut(PVRecordFieldPtr const & pvRecordField)
{
String fieldName = pvRecordField->getFullFieldName();
printf("%s dataPut(requested(%s))\n",
requesterName.c_str(),
fieldName.c_str());
}
virtual void dataPut(
PVRecordStructurePtr const & requested,
PVRecordFieldPtr const & pvRecordField)
{
String requestedName = requested->getFullFieldName();
String fieldName = pvRecordField->getFullFieldName();
printf("%s dataPut(requested(%s),pvRecordField(%s))\n",
requesterName.c_str(),
requestedName.c_str(),
fieldName.c_str());
}
virtual void beginGroupPut(PVRecordPtr const & pvRecord)
{
printf("beginGroupPut\n");
}
virtual void endGroupPut(PVRecordPtr const & pvRecord)
{
printf("endGroupPut\n");
}
virtual void unlisten(PVRecordPtr const & pvRecord)
{
printf("unlisten\n");
}
private:
MyPVListenerPtr getPtrSelf()
{
return shared_from_this();
}
MyPVListener(
String const & requesterName,
PVRecordPtr const & pvRecord,
PVRecordFieldPtr const &pvRecordField)
: isDetached(false),
requesterName(requesterName),
pvRecord(pvRecord),
pvRecordField(pvRecordField)
{}
void init() {
pvRecord->addPVRecordClient(getPtrSelf());
pvRecord->addListener(getPtrSelf());
pvRecordField->addListener(getPtrSelf());
}
bool isDetached;
String requesterName;
PVRecordPtr pvRecord;
PVRecordFieldPtr pvRecordField;
};
class MyProcessRequester :
public virtual Requester,
public virtual RecordProcessRequester,
public std::tr1::enable_shared_from_this<MyProcessRequester>
{
public:
static MyProcessRequesterPtr create(
String const &requesterName,
PVRecordPtr const & pvRecord)
{
MyProcessRequesterPtr pvProcessRequester(
new MyProcessRequester(requesterName,pvRecord));
pvProcessRequester->init();
return pvProcessRequester;
}
bool process()
{
if(isDetached) {
message("process request but detached",errorMessage);
return false;
}
pvRecord->queueProcessRequest(getPtrSelf());
event.wait();
return true;
}
virtual ~MyProcessRequester() {}
virtual void detach(PVRecordPtr const & pvRecord)
{
isDetached = true;
message("detached",infoMessage);
}
virtual String getRequesterName() {return requesterName;}
virtual void message(
String const & message,
MessageType messageType)
{
String messageTypeName = getMessageTypeName(messageType);
printf("%s %s %s\n",
requesterName.c_str(),
message.c_str(),
messageTypeName.c_str());
}
virtual void recordDestroyed()
{
printf("%s MyProcessRequester::recordDestroyed\n",
requesterName.c_str());
}
virtual void becomeProcessor()
{
pvRecord->process(getPtrSelf(),false);
}
virtual void recordProcessResult(epics::pvData::Status status)
{
String xxx("recordProcessResult ");
message( xxx + status.getMessage(),infoMessage);
}
virtual void recordProcessComplete()
{
message("recordProcessComplete",infoMessage);
event.signal();
}
private:
MyProcessRequesterPtr getPtrSelf()
{
return shared_from_this();
}
MyProcessRequester(
String const &requesterName,
PVRecordPtr const & pvRecord)
: isDetached(false),
requesterName(requesterName),
pvRecord(pvRecord)
{}
void init() {
pvRecord->addPVRecordClient(getPtrSelf());
pvRecord->addRequester(getPtrSelf());
}
Event event;
bool isDetached;
String requesterName;
PVRecordPtr pvRecord;
};
class MyPutRequester :
public virtual RecordPutRequester,
public std::tr1::enable_shared_from_this<MyPutRequester>
{
public:
MyPutRequester(PVRecordPtr const & pvRecord)
: pvRecord(pvRecord),
result(false)
{}
virtual ~MyPutRequester() {}
virtual void requestResult(bool result)
{
this->result = result;
event.signal();
}
bool makeRequest()
{
pvRecord->queuePutRequest(getPtrSelf());
event.wait();
return result;
}
private:
MyPutRequesterPtr getPtrSelf()
{
return shared_from_this();
}
Event event;
PVRecordPtr pvRecord;
bool result;
};
void dumpPVRecordField(PVRecordFieldPtr pvRecordField)
{
PVRecordStructurePtr pvRecordStructure = pvRecordField->getParent();
PVFieldPtr pvField = pvRecordField->getPVField();
String fieldName = pvField->getFieldName();
String fullFieldName = pvRecordField->getFullFieldName();
String fullName = pvRecordField->getFullName();
PVRecordPtr pvRecord = pvRecordField->getPVRecord();
String recordName = pvRecord->getRecordName();
printf("recordName %s fullName %s fullFieldName %s fieldName %s\n",
recordName.c_str(),
fullName.c_str(),
fullFieldName.c_str(),
fieldName.c_str());
}
void dumpPVRecordStructure(PVRecordStructurePtr pvRecordStructure)
{
dumpPVRecordField(pvRecordStructure);
PVRecordFieldPtrArrayPtr pvRecordFields =
pvRecordStructure->getPVRecordFields();
size_t num = pvRecordFields->size();
for(size_t i=0; i<num; i++) {
PVRecordFieldPtr pvRecordField = (*pvRecordFields.get())[i];
if(pvRecordField->getPVField()->getField()->getType()==structure) {
PVRecordStructurePtr xxx =
static_pointer_cast<PVRecordStructure>(pvRecordField);
dumpPVRecordStructure(xxx);
} else {
dumpPVRecordField(pvRecordField);
}
}
}
int main(int argc,char *argv[])
{
String recordName("testRecord");
PVRecordPtr pvRecord = TestRecord::create(recordName);
dumpPVRecordStructure(pvRecord->getPVRecordStructure());
PVStructurePtr pvStructure =
pvRecord->getPVRecordStructure()->getPVStructure();
PVLongPtr pvValue = pvStructure->getLongField("value");
String builder;
pvStructure->toString(&builder);
printf("pvStructure\n%s\n",builder.c_str());
builder.clear();
pvValue->toString(&builder);
printf("value\n%s\n",builder.c_str());
PVRecordFieldPtr recordFieldValue = pvRecord->findPVRecordField(pvValue);
MyPVListenerPtr listenTop = MyPVListener::create(
"listenTop", pvRecord, pvRecord->getPVRecordStructure());
MyPVListenerPtr listenValue = MyPVListener::create(
"listenValue", pvRecord,recordFieldValue);
PVFieldPtr pvDisplay = pvStructure->getSubField("display");
PVRecordFieldPtr recordFieldDisplay =
pvRecord->findPVRecordField(pvDisplay);
MyPVListenerPtr listenDisplay = MyPVListener::create(
"listenDisplay", pvRecord,recordFieldDisplay);
PVStringPtr pvDisplayDescription =
pvStructure->getStringField("display.description");
PVRecordFieldPtr recordFieldDisplayDescription =
pvRecord->findPVRecordField(pvDisplayDescription);
MyPVListenerPtr listenDisplayDescription = MyPVListener::create(
"listenDisplayDescription", pvRecord,recordFieldDisplayDescription);
recordFieldDisplayDescription->message("test message",infoMessage);
MyProcessRequesterPtr process1 =
MyProcessRequester::create("process1",pvRecord);
MyProcessRequesterPtr process2 =
MyProcessRequester::create("process2",pvRecord);
process1->process();
builder.clear();
pvValue->toString(&builder);
printf("%s\n",builder.c_str());
process2->process();
builder.clear();
pvValue->toString(&builder);
printf("%s\n",builder.c_str());
bool requestResult;
requestResult = pvRecord->requestImmediatePut(pvValue);
if(requestResult) {
printf("error requestImmediatePut for pvValue returned true");
pvRecord->immediatePutDone();
}
requestResult = pvRecord->requestImmediatePut(pvDisplayDescription);
if(!requestResult) {
printf("error requestImmediatePut for pvDisplayDescription returned false");
} else {
pvDisplayDescription->put("this is description");
pvRecord->immediatePutDone();
}
MyPutRequesterPtr myPut(new MyPutRequester(pvRecord));
requestResult = myPut->makeRequest();
if(!requestResult) {
printf("error myPut->makeRequest() returned false");
} else {
pvDisplayDescription->put("this is new description");
pvValue->put(1000);
PVIntPtr pvSeverity = pvStructure->getIntField("alarm.severity");
pvSeverity->put(3);
PVIntPtr pvStatus = pvStructure->getIntField("alarm.status");
pvStatus->put(2);
PVStringPtr pvMessage = pvStructure->getStringField("alarm.message");
pvMessage->put("alarmMessage");
pvRecord->putDone(myPut);
}
builder.clear();
pvStructure->toString(&builder);
printf("pvStructure\n%s\n",builder.c_str());
builder.clear();
pvRecord->destroy();
printf("all done\n");
#ifdef XXXXXX
PVDatabasePtr pvDatabase = PVDatabase::getMaster();
pvDatabase->addRecord(pvRecord);
cout << recordName << "\n";
string str;
while(true) {
cout << "Type exit to stop: \n";
getline(cin,str);
if(str.compare("exit")==0) break;
}
#endif
return 0;
}