pvDatabaseCPP  4.7.0
pvdbcrProcessRecord.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 
10 #include <epicsThread.h>
11 #include <epicsGuard.h>
12 #include <pv/event.h>
13 #include <pv/lock.h>
14 #include <iocsh.h>
15 #include <pv/standardField.h>
16 #include <pv/standardPVField.h>
17 #include <pv/timeStamp.h>
18 #include <pv/pvTimeStamp.h>
19 #include <pv/alarm.h>
20 #include <pv/pvAlarm.h>
21 #include <pv/pvAccess.h>
22 #include <pv/serverContext.h>
23 #include <pv/rpcService.h>
24 
25 #include <epicsExport.h>
26 #define epicsExportSharedSymbols
27 #include "pv/pvDatabase.h"
28 #include "pv/pvdbcrProcessRecord.h"
29 using namespace epics::pvData;
30 using namespace std;
31 
32 namespace epics { namespace pvDatabase {
33 
34 PvdbcrProcessRecordPtr PvdbcrProcessRecord::create(
35  std::string const & recordName,double delay,
36  int asLevel,std::string const & asGroup)
37 {
38  FieldCreatePtr fieldCreate = getFieldCreate();
39  PVDataCreatePtr pvDataCreate = getPVDataCreate();
40  StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
41  addNestedStructure("argument")->
42  add("command",pvString)->
43  add("recordName",pvString)->
44  endNested()->
45  addNestedStructure("result") ->
46  add("status",pvString) ->
47  endNested()->
48  createStructure();
49  PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
50  PvdbcrProcessRecordPtr pvRecord(
51  new PvdbcrProcessRecord(recordName,pvStructure,delay,asLevel,asGroup));
52  if(!pvRecord->init()) pvRecord.reset();
53  return pvRecord;
54 }
55 
56 
57 PvdbcrProcessRecord::PvdbcrProcessRecord(
58  std::string const & recordName,
59  epics::pvData::PVStructurePtr const & pvStructure,double delay,
60  int asLevel,std::string const & asGroup)
61 : PVRecord(recordName,pvStructure,asLevel,asGroup),
62  delay(delay),
63  pvDatabase(PVDatabase::getMaster())
64 {
65 }
66 
67 bool PvdbcrProcessRecord::init()
68 {
69  initPVRecord();
70  PVStructurePtr pvStructure = getPVStructure();
71  pvCommand = pvStructure->getSubField<PVString>("argument.command");
72  pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
73  if(!pvRecordName) return false;
74  pvResult = pvStructure->getSubField<PVString>("result.status");
75  if(!pvResult) return false;
76  startThread();
77  return true;
78 }
79 
80 void PvdbcrProcessRecord::setDelay(double delay) {this->delay = delay;}
81 
82 double PvdbcrProcessRecord::getDelay() {return delay;}
83 
84 void PvdbcrProcessRecord::startThread()
85 {
86  thread = EpicsThreadPtr(new epicsThread(
87  *this,
88  "processRecord",
89  epicsThreadGetStackSize(epicsThreadStackSmall),
90  epicsThreadPriorityLow));
91  thread->start();
92 }
93 
94 void PvdbcrProcessRecord::stop()
95 {
96  runStop.signal();
97  runReturn.wait();
98 }
99 
100 void PvdbcrProcessRecord::process()
101 {
102  string recordName = pvRecordName->get();
103  string command = pvCommand->get();
104  if(command.compare("add")==0) {
105  epicsGuard<epics::pvData::Mutex> guard(mutex);
106  std::map<std::string,PVRecordPtr>::iterator iter = pvRecordMap.find(recordName);
107  if(iter!=pvRecordMap.end()) {
108  pvResult->put(recordName + " already present");
109  return;
110  }
111  PVRecordPtr pvRecord = pvDatabase->findRecord(recordName);
112  if(!pvRecord) {
113  pvResult->put(recordName + " not in pvDatabase");
114  return;
115  }
116  pvRecordMap.insert(PVRecordMap::value_type(recordName,pvRecord));
117  pvResult->put("success");
118  return;
119  } else if(command.compare("remove")==0) {
120  epicsGuard<epics::pvData::Mutex> guard(mutex);
121  std::map<std::string,PVRecordPtr>::iterator iter = pvRecordMap.find(recordName);
122  if(iter==pvRecordMap.end()) {
123  pvResult->put(recordName + " not found");
124  return;
125  }
126  pvRecordMap.erase(iter);
127  pvResult->put("success");
128  return;
129  } else {
130  pvResult->put(command + " not a valid command: only add and remove are valid");
131  return;
132  }
133 }
134 
135 void PvdbcrProcessRecord::run()
136 {
137  while(true) {
138  if(runStop.tryWait()) {
139  runReturn.signal();
140  return;
141  }
142  if(delay>0.0) epicsThreadSleep(delay);
143  epicsGuard<epics::pvData::Mutex> guard(mutex);
144  PVRecordMap::iterator iter;
145  for(iter = pvRecordMap.begin(); iter!=pvRecordMap.end(); ++iter) {
146  PVRecordPtr pvRecord = (*iter).second;
147  pvRecord->lock();
148  pvRecord->beginGroupPut();
149  try {
150  pvRecord->process();
151  } catch (std::exception& ex) {
152  std::cout << "record " << pvRecord->getRecordName() << "exception " << ex.what() << "\n";
153  } catch (...) {
154  std::cout<< "record " << pvRecord->getRecordName() << " process exception\n";
155  }
156  pvRecord->endGroupPut();
157  pvRecord->unlock();
158  }
159  }
160 }
161 }}
162 
163 static const iocshArg arg0 = { "recordName", iocshArgString };
164 static const iocshArg arg1 = { "delay", iocshArgDouble };
165 static const iocshArg arg2 = { "asLevel", iocshArgInt };
166 static const iocshArg arg3 = { "asGroup", iocshArgString };
167 static const iocshArg *args[] = {&arg0,&arg1,&arg2,&arg3};
168 
169 static const iocshFuncDef pvdbcrProcessRecordFuncDef = {"pvdbcrProcessRecord", 4,args};
170 
171 static void pvdbcrProcessRecordCallFunc(const iocshArgBuf *args)
172 {
173  char *sval = args[0].sval;
174  if(!sval) {
175  throw std::runtime_error("pvdbcrProcessRecord recordName not specified");
176  }
177  string recordName = string(sval);
178  double delay = args[1].dval;
179  if(delay<0.0) delay = 1.0;
180  int asLevel = args[2].ival;
181  string asGroup("DEFAULT");
182  sval = args[3].sval;
183  if(sval) {
184  asGroup = string(sval);
185  }
188  record->setAsLevel(asLevel);
189  record->setAsGroup(asGroup);
191  bool result = master->addRecord(record);
192  if(!result) cout << "recordname " << recordName << " not added" << endl;
193 }
194 
195 static void pvdbcrProcessRecord(void)
196 {
197  static int firstTime = 1;
198  if (firstTime) {
199  firstTime = 0;
200  iocshRegister(&pvdbcrProcessRecordFuncDef, pvdbcrProcessRecordCallFunc);
201  }
202 }
203 
204 extern "C" {
205  epicsExportRegistrar(pvdbcrProcessRecord);
206 }
PvdbcrProcessRecord A record that processes other records in the master database. ...
STL namespace.
epicsExportRegistrar(pvdbcrProcessRecord)
Base interface for a PVRecord.
Definition: pvDatabase.h:56
std::tr1::shared_ptr< PVDatabase > PVDatabasePtr
Definition: pvDatabase.h:43
static PVDatabasePtr getMaster()
Get the master database.
Definition: pvDatabase.cpp:38
std::tr1::shared_ptr< PVRecord > PVRecordPtr
Definition: pvDatabase.h:21
std::tr1::shared_ptr< PvdbcrProcessRecord > PvdbcrProcessRecordPtr
static PvdbcrProcessRecordPtr create(std::string const &recordName, double delay=1.0, int asLevel=0, std::string const &asGroup=std::string("DEFAULT"))
Create a record.
std::tr1::shared_ptr< epicsThread > EpicsThreadPtr