This is Unofficial EPICS BASE Doxygen Site
processRecord.cpp
Go to the documentation of this file.
1 /* processRecord.cpp */
11 #include <map>
12 #include <epicsThread.h>
13 #include <pv/event.h>
14 #include <shareLib.h>
15 #include <string>
16 #include <cstring>
17 #include <stdexcept>
18 #include <memory>
19 #include <set>
20 
21 #include <pv/lock.h>
22 #include <pv/pvType.h>
23 #include <pv/pvData.h>
24 #include <pv/pvTimeStamp.h>
25 #include <pv/timeStamp.h>
26 #include <pv/rpcService.h>
27 #include <pv/pvAccess.h>
28 #include <pv/status.h>
29 #include <pv/serverContext.h>
30 
31 #define epicsExportSharedSymbols
32 #include "pv/pvStructureCopy.h"
33 #include "pv/pvDatabase.h"
34 #include "pv/processRecord.h"
35 
37 using namespace epics::pvData;
38 using namespace epics::pvAccess;
39 using namespace std;
40 
41 namespace epics { namespace pvDatabase {
42 
43 ProcessRecordPtr ProcessRecord::create(
44  std::string const & recordName,double delay)
45 {
46  FieldCreatePtr fieldCreate = getFieldCreate();
47  PVDataCreatePtr pvDataCreate = getPVDataCreate();
48  StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
49  addNestedStructure("argument")->
50  add("command",pvString)->
51  add("recordName",pvString)->
52  endNested()->
53  addNestedStructure("result") ->
54  add("status",pvString) ->
55  endNested()->
56  createStructure();
57  PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
58  ProcessRecordPtr pvRecord(
59  new ProcessRecord(recordName,pvStructure,delay));
60  if(!pvRecord->init()) pvRecord.reset();
61  return pvRecord;
62 }
63 
64 void ProcessRecord::startThread()
65 {
66  thread = EpicsThreadPtr(new epicsThread(
67  *this,
68  "processRecord",
71  thread->start();
72 }
73 
74 void ProcessRecord::stop()
75 {
76  runStop.signal();
77  runReturn.wait();
78 }
79 
80 
81 ProcessRecord::ProcessRecord(
82  std::string const & recordName,
83  epics::pvData::PVStructurePtr const & pvStructure,double delay)
84 : PVRecord(recordName,pvStructure),
85  delay(delay),
86  pvDatabase(PVDatabase::getMaster())
87 {
88 }
89 
90 bool ProcessRecord::init()
91 {
92  initPVRecord();
93  PVStructurePtr pvStructure = getPVStructure();
94  pvCommand = pvStructure->getSubField<PVString>("argument.command");
95  pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
96  if(!pvRecordName) return false;
97  pvResult = pvStructure->getSubField<PVString>("result.status");
98  if(!pvResult) return false;
99  startThread();
100  return true;
101 }
102 
103 void ProcessRecord::process()
104 {
105  string recordName = pvRecordName->get();
106  string command = pvCommand->get();
107  if(command.compare("add")==0) {
109  std::map<std::string,PVRecordPtr>::iterator iter = pvRecordMap.find(recordName);
110  if(iter!=pvRecordMap.end()) {
111  pvResult->put(recordName + " already present");
112  return;
113  }
114  PVRecordPtr pvRecord = pvDatabase->findRecord(recordName);
115  if(!pvRecord) {
116  pvResult->put(recordName + " not in pvDatabase");
117  return;
118  }
119  pvRecordMap.insert(PVRecordMap::value_type(recordName,pvRecord));
120  pvResult->put("success");
121  return;
122  } else if(command.compare("remove")==0) {
124  std::map<std::string,PVRecordPtr>::iterator iter = pvRecordMap.find(recordName);
125  if(iter==pvRecordMap.end()) {
126  pvResult->put(recordName + " not found");
127  return;
128  }
129  pvRecordMap.erase(iter);
130  pvResult->put("success");
131  return;
132  } else {
133  pvResult->put(command + " not a valid command: only add and remove are valid");
134  return;
135  }
136 }
137 
138 void ProcessRecord::run()
139 {
140  while(true) {
141  if(runStop.tryWait()) {
142  runReturn.signal();
143  return;
144  }
145  if(delay>0.0) epicsThreadSleep(delay);
147  PVRecordMap::iterator iter;
148  for(iter = pvRecordMap.begin(); iter!=pvRecordMap.end(); ++iter) {
149  PVRecordPtr pvRecord = (*iter).second;
150  pvRecord->lock();
151  pvRecord->beginGroupPut();
152  try {
153  pvRecord->process();
154  } catch (std::exception& ex) {
155  std::cout << "record " << pvRecord->getRecordName() << "exception " << ex.what() << "\n";
156  } catch (...) {
157  std::cout<< "record " << pvRecord->getRecordName() << " process exception\n";
158  }
159  pvRecord->endGroupPut();
160  pvRecord->unlock();
161  }
162  }
163 }
164 
165 
166 }}
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:788
Definition: memory.hpp:41
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
Mark external symbols and entry points for shared libraries.
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass size)
Definition: osdThread.c:466
Base interface for a PVRecord.
Definition: pvDatabase.h:56
std::tr1::shared_ptr< PVDataCreate > PVDataCreatePtr
Definition: pvData.h:124
Holds all PVA related.
Definition: pvif.h:34
PVString is special case, since it implements SerializableArray.
Definition: pvData.h:521
pvData
Definition: monitor.h:428
epicsMutex mutex
Definition: pvAccess.cpp:71
#define epicsThreadPriorityLow
Definition: epicsThread.h:75
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
std::tr1::shared_ptr< PVRecord > PVRecordPtr
Definition: pvDatabase.h:21
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
Process another record in the same database.
Definition: processRecord.h:36
std::tr1::shared_ptr< FieldCreate > FieldCreatePtr
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
std::tr1::shared_ptr< epicsThread > EpicsThreadPtr
Definition: thread.h:41
C++ and C descriptions for a thread.
std::tr1::shared_ptr< ProcessRecord > ProcessRecordPtr
Definition: processRecord.h:25
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
Definition: pvData.h:1648