pvDatabaseCPP  4.7.0
channelLocal.cpp
Go to the documentation of this file.
1 /* channelLocal.cpp */
12 #include <sstream>
13 #include <vector>
14 
15 #include <asLib.h>
16 #include <epicsGuard.h>
17 #include <epicsThread.h>
18 #include <pv/pvData.h>
19 #include <pv/pvAccess.h>
20 #include <pv/pvTimeStamp.h>
21 #include <pv/rpcService.h>
22 #include <pv/timeStamp.h>
23 #include <pv/createRequest.h>
24 #include <pv/pvaVersion.h>
25 #include <pv/pvaVersionNum.h>
26 #include <pv/serverContext.h>
27 #include <pv/pvSubArrayCopy.h>
28 #include <pv/security.h>
29 
30 #define epicsExportSharedSymbols
31 #include "pv/pvStructureCopy.h"
32 #include "pv/pvDatabase.h"
34 
35 using namespace epics::pvData;
36 using namespace epics::pvAccess;
37 using namespace epics::pvCopy;
38 using std::tr1::static_pointer_cast;
39 using std::tr1::dynamic_pointer_cast;
40 using std::cout;
41 using std::endl;
42 using std::string;
43 
44 namespace epics { namespace pvDatabase {
45 
46 static StructureConstPtr nullStructure;
47 
48 class ChannelProcessLocal;
49 typedef std::tr1::shared_ptr<ChannelProcessLocal> ChannelProcessLocalPtr;
50 class ChannelGetLocal;
51 typedef std::tr1::shared_ptr<ChannelGetLocal> ChannelGetLocalPtr;
52 class ChannelPutLocal;
53 typedef std::tr1::shared_ptr<ChannelPutLocal> ChannelPutLocalPtr;
54 class ChannelPutGetLocal;
55 typedef std::tr1::shared_ptr<ChannelPutGetLocal> ChannelPutGetLocalPtr;
56 class ChannelRPCLocal;
57 typedef std::tr1::shared_ptr<ChannelRPCLocal> ChannelRPCLocalPtr;
58 class ChannelArrayLocal;
59 typedef std::tr1::shared_ptr<ChannelArrayLocal> ChannelArrayLocalPtr;
60 
61 static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
62 {
63  PVFieldPtr pvField = pvRequest->getSubField("record._options.process");
64  if(!pvField || pvField->getField()->getType()!=scalar) {
65  return processDefault;
66  }
67  ScalarConstPtr scalar = static_pointer_cast<const Scalar>(
68  pvField->getField());
69  if(scalar->getScalarType()==pvString) {
70  PVStringPtr pvString = static_pointer_cast<PVString>(pvField);
71  return pvString->get().compare("true")==0 ? true : false;
72  } else if(scalar->getScalarType()==pvBoolean) {
73  PVBooleanPtr pvBoolean = static_pointer_cast<PVBoolean>(pvField);
74  return pvBoolean->get();
75  }
76  return processDefault;
77 }
78 
79 class ChannelProcessLocal :
80  public epics::pvAccess::ChannelProcess,
81  public std::tr1::enable_shared_from_this<ChannelProcessLocal>
82 {
83 public:
84  POINTER_DEFINITIONS(ChannelProcessLocal);
85  virtual ~ChannelProcessLocal();
86  static ChannelProcessLocalPtr create(
87  ChannelLocalPtr const &channelLocal,
88  ChannelProcessRequester::shared_pointer const & channelProcessRequester,
89  PVStructurePtr const & pvRequest,
90  PVRecordPtr const &pvRecord);
91  virtual void process();
92  virtual std::tr1::shared_ptr<Channel> getChannel();
93  virtual void cancel(){}
94  virtual void lock();
95  virtual void unlock();
96  virtual void lastRequest() {}
97 private:
98  shared_pointer getPtrSelf()
99  {
100  return shared_from_this();
101  }
102  ChannelProcessLocal(
103  ChannelLocalPtr const &channelLocal,
104  ChannelProcessRequester::shared_pointer const & channelProcessRequester,
105  PVRecordPtr const &pvRecord,
106  int nProcess)
107  :
108  channelLocal(channelLocal),
109  channelProcessRequester(channelProcessRequester),
110  pvRecord(pvRecord),
111  nProcess(nProcess)
112  {
113  }
114  ChannelLocalWPtr channelLocal;
115  ChannelProcessRequester::weak_pointer channelProcessRequester;
116  PVRecordWPtr pvRecord;
117  int nProcess;
118  Mutex mutex;
119 };
120 
121 ChannelProcessLocalPtr ChannelProcessLocal::create(
122  ChannelLocalPtr const &channelLocal,
123  ChannelProcessRequester::shared_pointer const & channelProcessRequester,
124  PVStructurePtr const & pvRequest,
125  PVRecordPtr const &pvRecord)
126 {
127  PVFieldPtr pvField;
128  PVStructurePtr pvOptions;
129  int nProcess = 1;
130  if(pvRequest) pvField = pvRequest->getSubField("record._options");
131  if(pvField) {
132  pvOptions = static_pointer_cast<PVStructure>(pvField);
133  pvField = pvOptions->getSubField("nProcess");
134  if(pvField) {
135  PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess");
136  if(pvString) {
137  int size=0;
138  std::stringstream ss;
139  ss << pvString->get();
140  ss >> size;
141  nProcess = size;
142  }
143  }
144  }
145  ChannelProcessLocalPtr process(new ChannelProcessLocal(
146  channelLocal,
147  channelProcessRequester,
148  pvRecord,
149  nProcess));
150  if(pvRecord->getTraceLevel()>0)
151  {
152  cout << "ChannelProcessLocal::create";
153  cout << " recordName " << pvRecord->getRecordName() << endl;
154  }
155  channelProcessRequester->channelProcessConnect(Status::Ok, process);
156  return process;
157 }
158 
159 ChannelProcessLocal::~ChannelProcessLocal()
160 {
161 //cout << "~ChannelProcessLocal()\n";
162 }
163 
164 std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
165 {
166  ChannelLocalPtr channel(channelLocal.lock());
167  return channel;
168 }
169 
170 void ChannelProcessLocal::lock()
171 {
172  PVRecordPtr pvr(pvRecord.lock());
173  if(!pvr) throw std::logic_error("pvRecord is deleted");
174  pvr->lock();
175 }
176 void ChannelProcessLocal::unlock()
177 {
178  PVRecordPtr pvr(pvRecord.lock());
179  if(!pvr) throw std::logic_error("pvRecord is deleted");
180  pvr->unlock();
181 }
182 
183 void ChannelProcessLocal::process()
184 {
185  ChannelProcessRequester::shared_pointer requester = channelProcessRequester.lock();
186  if(!requester) return;
187  PVRecordPtr pvr(pvRecord.lock());
188  if(!pvr) throw std::logic_error("pvRecord is deleted");
189  if(pvr->getTraceLevel()>1)
190  {
191  cout << "ChannelProcessLocal::process";
192  cout << " nProcess " << nProcess << endl;
193  }
194  try {
195  for(int i=0; i< nProcess; i++) {
196  epicsGuard <PVRecord> guard(*pvr);
197  pvr->beginGroupPut();
198  pvr->process();
199  pvr->endGroupPut();
200  }
201  requester->processDone(Status::Ok,getPtrSelf());
202  } catch(std::exception& ex) {
203  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
204  requester->processDone(status,getPtrSelf());
205  }
206 }
207 
208 class ChannelGetLocal :
209  public epics::pvAccess::ChannelGet,
210  public std::tr1::enable_shared_from_this<ChannelGetLocal>
211 {
212 public:
213  POINTER_DEFINITIONS(ChannelGetLocal);
214  virtual ~ChannelGetLocal();
215  static ChannelGetLocalPtr create(
216  ChannelLocalPtr const &channelLocal,
217  ChannelGetRequester::shared_pointer const & channelGetRequester,
218  PVStructurePtr const & pvRequest,
219  PVRecordPtr const &pvRecord);
220  virtual void get();
221  virtual std::tr1::shared_ptr<Channel> getChannel();
222  virtual void cancel(){}
223  virtual void lock();
224  virtual void unlock();
225  virtual void lastRequest() {}
226 private:
227  shared_pointer getPtrSelf()
228  {
229  return shared_from_this();
230  }
231  ChannelGetLocal(
232  bool callProcess,
233  ChannelLocalPtr const &channelLocal,
234  ChannelGetRequester::shared_pointer const & channelGetRequester,
235  PVCopyPtr const &pvCopy,
236  PVStructurePtr const&pvStructure,
237  BitSetPtr const & bitSet,
238  PVRecordPtr const &pvRecord)
239  :
240  firstTime(true),
241  callProcess(callProcess),
242  channelLocal(channelLocal),
243  channelGetRequester(channelGetRequester),
244  pvCopy(pvCopy),
245  pvStructure(pvStructure),
246  bitSet(bitSet),
247  pvRecord(pvRecord)
248  {
249  }
250  bool firstTime;
251  bool callProcess;
252  ChannelLocalWPtr channelLocal;
253  ChannelGetRequester::weak_pointer channelGetRequester;
254  PVCopyPtr pvCopy;
255  PVStructurePtr pvStructure;
256  BitSetPtr bitSet;
257  PVRecordWPtr pvRecord;
258  Mutex mutex;
259 };
260 
261 ChannelGetLocalPtr ChannelGetLocal::create(
262  ChannelLocalPtr const &channelLocal,
263  ChannelGetRequester::shared_pointer const & channelGetRequester,
264  PVStructurePtr const & pvRequest,
265  PVRecordPtr const &pvRecord)
266 {
267  PVCopyPtr pvCopy = PVCopy::create(
268  pvRecord->getPVRecordStructure()->getPVStructure(),
269  pvRequest,
270  "");
271  if(!pvCopy) {
272  Status status(
273  Status::STATUSTYPE_ERROR,
274  "invalid pvRequest");
275  ChannelGet::shared_pointer channelGet;
276  channelGetRequester->channelGetConnect(
277  status,
278  channelGet,
279  nullStructure);
280  ChannelGetLocalPtr localGet;
281  return localGet;
282  }
283  PVStructurePtr pvStructure = pvCopy->createPVStructure();
284  BitSetPtr bitSet(new BitSet(pvStructure->getNumberFields()));
285  ChannelGetLocalPtr get(new ChannelGetLocal(
286  getProcess(pvRequest,false),
287  channelLocal,
288  channelGetRequester,
289  pvCopy,
290  pvStructure,
291  bitSet,
292  pvRecord));
293  if(pvRecord->getTraceLevel()>0)
294  {
295  cout << "ChannelGetLocal::create";
296  cout << " recordName " << pvRecord->getRecordName() << endl;
297  }
298  channelGetRequester->channelGetConnect(
299  Status::Ok,get,pvStructure->getStructure());
300  return get;
301 }
302 
303 ChannelGetLocal::~ChannelGetLocal()
304 {
305 //cout << "~ChannelGetLocal()\n";
306 }
307 
308 std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
309 {
310  ChannelLocalPtr channel(channelLocal.lock());
311  return channel;
312 }
313 
314 void ChannelGetLocal::lock()
315 {
316  PVRecordPtr pvr(pvRecord.lock());
317  if(!pvr) throw std::logic_error("pvRecord is deleted");
318  pvr->lock();
319 }
320 void ChannelGetLocal::unlock()
321 {
322  PVRecordPtr pvr(pvRecord.lock());
323  if(!pvr) throw std::logic_error("pvRecord is deleted");
324  pvr->unlock();
325 }
326 
327 
328 void ChannelGetLocal::get()
329 {
330  ChannelGetRequester::shared_pointer requester = channelGetRequester.lock();
331  if(!requester) return;
332  ChannelLocalPtr channel(channelLocal.lock());
333  if(!channel) throw std::logic_error("channel is deleted");
334  if(!channel->canRead()) {
335  Status status = Status::error("ChannelGet::get is not allowed");
336  requester->getDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
337  return;
338  }
339  PVRecordPtr pvr(pvRecord.lock());
340  if(!pvr) throw std::logic_error("pvRecord is deleted");
341  try {
342  bool notifyClient = true;
343  bitSet->clear();
344  {
345  epicsGuard <PVRecord> guard(*pvr);
346  if(callProcess) {
347  pvr->beginGroupPut();
348  pvr->process();
349  pvr->endGroupPut();
350  }
351  notifyClient = pvCopy->updateCopySetBitSet(pvStructure, bitSet);
352  }
353  if(firstTime) {
354  bitSet->clear();
355  bitSet->set(0);
356  firstTime = false;
357  notifyClient = true;
358  }
359  if(notifyClient) {
360  requester->getDone(
361  Status::Ok,
362  getPtrSelf(),
363  pvStructure,
364  bitSet);
365  bitSet->clear();
366  } else {
367  BitSetPtr temp(new BitSet(bitSet->size()));
368  requester->getDone(
369  Status::Ok,
370  getPtrSelf(),
371  pvStructure,
372  temp);
373  }
374  if(pvr->getTraceLevel()>1)
375  {
376  cout << "ChannelGetLocal::get" << endl;
377  }
378  } catch(std::exception& ex) {
379  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
380  requester->getDone(status,getPtrSelf(),pvStructure,bitSet);
381  }
382 
383 }
384 
385 class ChannelPutLocal :
386  public epics::pvAccess::ChannelPut,
387  public std::tr1::enable_shared_from_this<ChannelPutLocal>
388 {
389 public:
390  POINTER_DEFINITIONS(ChannelPutLocal);
391  virtual ~ChannelPutLocal();
392  static ChannelPutLocalPtr create(
393  ChannelLocalPtr const &channelLocal,
394  ChannelPutRequester::shared_pointer const & channelPutRequester,
395  PVStructurePtr const & pvRequest,
396  PVRecordPtr const &pvRecord);
397  virtual void put(PVStructurePtr const &pvStructure,BitSetPtr const &bitSet);
398  virtual void get();
399  virtual std::tr1::shared_ptr<Channel> getChannel();
400  virtual void cancel(){}
401  virtual void lock();
402  virtual void unlock();
403  virtual void lastRequest() {}
404 private:
405  shared_pointer getPtrSelf()
406  {
407  return shared_from_this();
408  }
409  ChannelPutLocal(
410  bool callProcess,
411  ChannelLocalPtr const &channelLocal,
412  ChannelPutRequester::shared_pointer const & channelPutRequester,
413  PVCopyPtr const &pvCopy,
414  PVRecordPtr const &pvRecord)
415  :
416  callProcess(callProcess),
417  channelLocal(channelLocal),
418  channelPutRequester(channelPutRequester),
419  pvCopy(pvCopy),
420  pvRecord(pvRecord)
421  {
422  }
423  bool callProcess;
424  ChannelLocalWPtr channelLocal;
425  ChannelPutRequester::weak_pointer channelPutRequester;
426  PVCopyPtr pvCopy;
427  PVRecordWPtr pvRecord;
428  Mutex mutex;
429 };
430 
431 ChannelPutLocalPtr ChannelPutLocal::create(
432  ChannelLocalPtr const &channelLocal,
433  ChannelPutRequester::shared_pointer const & channelPutRequester,
434  PVStructurePtr const & pvRequest,
435  PVRecordPtr const &pvRecord)
436 {
437  PVCopyPtr pvCopy = PVCopy::create(
438  pvRecord->getPVRecordStructure()->getPVStructure(),
439  pvRequest,
440  "");
441  if(!pvCopy) {
442  Status status(
443  Status::STATUSTYPE_ERROR,
444  "invalid pvRequest");
445  ChannelPut::shared_pointer channelPut;
446  PVStructurePtr pvStructure;
447  BitSetPtr bitSet;
448  channelPutRequester->channelPutConnect(
449  status,
450  channelPut,
451  nullStructure);
452  ChannelPutLocalPtr localPut;
453  return localPut;
454  }
455  ChannelPutLocalPtr put(new ChannelPutLocal(
456  getProcess(pvRequest,true),
457  channelLocal,
458  channelPutRequester,
459  pvCopy,
460  pvRecord));
461  channelPutRequester->channelPutConnect(
462  Status::Ok, put, pvCopy->getStructure());
463  if(pvRecord->getTraceLevel()>0)
464  {
465  cout << "ChannelPutLocal::create";
466  cout << " recordName " << pvRecord->getRecordName() << endl;
467  }
468  return put;
469 }
470 
471 ChannelPutLocal::~ChannelPutLocal()
472 {
473 //cout << "~ChannelPutLocal()\n";
474 }
475 
476 std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
477 {
478  ChannelLocalPtr channel(channelLocal.lock());
479  return channel;
480 }
481 
482 void ChannelPutLocal::lock()
483 {
484  PVRecordPtr pvr(pvRecord.lock());
485  if(!pvr) throw std::logic_error("pvRecord is deleted");
486  pvr->lock();
487 }
488 void ChannelPutLocal::unlock()
489 {
490  PVRecordPtr pvr(pvRecord.lock());
491  if(!pvr) throw std::logic_error("pvRecord is deleted");
492  pvr->unlock();
493 }
494 
495 
496 void ChannelPutLocal::get()
497 {
498  ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
499  if(!requester) return;
500  ChannelLocalPtr channel(channelLocal.lock());
501  if(!channel) throw std::logic_error("channel is deleted");
502  if(!channel->canRead()) {
503  Status status = Status::error("ChannelPut::get is not allowed");
504  requester->getDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
505  return;
506  }
507  PVRecordPtr pvr(pvRecord.lock());
508  if(!pvr) throw std::logic_error("pvRecord is deleted");
509  try {
510  PVStructurePtr pvStructure = pvCopy->createPVStructure();
511  BitSetPtr bitSet(new BitSet(pvStructure->getNumberFields()));
512  bitSet->clear();
513  bitSet->set(0);
514  {
515  epicsGuard <PVRecord> guard(*pvr);
516  pvCopy->updateCopyFromBitSet(pvStructure, bitSet);
517  }
518  requester->getDone(
519  Status::Ok,getPtrSelf(),pvStructure,bitSet);
520  if(pvr->getTraceLevel()>1)
521  {
522  cout << "ChannelPutLocal::get" << endl;
523  }
524  } catch(std::exception& ex) {
525  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
526  PVStructurePtr pvStructure;
527  BitSetPtr bitSet;
528  requester->getDone(status,getPtrSelf(),pvStructure,bitSet);
529  }
530 }
531 
532 void ChannelPutLocal::put(
533  PVStructurePtr const &pvStructure,BitSetPtr const &bitSet)
534 {
535  ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
536  if(!requester) return;
537  ChannelLocalPtr channel(channelLocal.lock());
538  if(!channel) throw std::logic_error("channel is deleted");
539  if(!channel->canWrite()) {
540  Status status = Status::error("ChannelPut::put is not allowed");
541  requester->putDone(status,getPtrSelf());
542  return;
543  }
544 
545  PVRecordPtr pvr(pvRecord.lock());
546  if(!pvr) throw std::logic_error("pvRecord is deleted");
547  try {
548  {
549  epicsGuard <PVRecord> guard(*pvr);
550  pvr->beginGroupPut();
551  pvCopy->updateMaster(pvStructure, bitSet);
552  if(callProcess) {
553  pvr->process();
554  }
555  pvr->endGroupPut();
556  }
557  requester->putDone(Status::Ok,getPtrSelf());
558  if(pvr->getTraceLevel()>1)
559  {
560  cout << "ChannelPutLocal::put" << endl;
561  }
562  } catch(std::exception& ex) {
563  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
564  requester->putDone(status,getPtrSelf());
565  }
566 }
567 
568 
569 class ChannelPutGetLocal :
570  public epics::pvAccess::ChannelPutGet,
571  public std::tr1::enable_shared_from_this<ChannelPutGetLocal>
572 {
573 public:
574  POINTER_DEFINITIONS(ChannelPutGetLocal);
575  virtual ~ChannelPutGetLocal();
576  static ChannelPutGetLocalPtr create(
577  ChannelLocalPtr const &channelLocal,
578  ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
579  PVStructurePtr const & pvRequest,
580  PVRecordPtr const &pvRecord);
581  virtual void putGet(
582  PVStructurePtr const &pvPutStructure,
583  BitSetPtr const &putBitSet);
584  virtual void getPut();
585  virtual void getGet();
586  virtual std::tr1::shared_ptr<Channel> getChannel();
587  virtual void cancel(){}
588  virtual void lock();
589  virtual void unlock();
590  virtual void lastRequest() {}
591 private:
592  shared_pointer getPtrSelf()
593  {
594  return shared_from_this();
595  }
596  ChannelPutGetLocal(
597  bool callProcess,
598  ChannelLocalPtr const &channelLocal,
599  ChannelPutGetRequester::weak_pointer const & channelPutGetRequester,
600  PVCopyPtr const &pvPutCopy,
601  PVCopyPtr const &pvGetCopy,
602  PVStructurePtr const&pvGetStructure,
603  BitSetPtr const & getBitSet,
604  PVRecordPtr const &pvRecord)
605  :
606  callProcess(callProcess),
607  channelLocal(channelLocal),
608  channelPutGetRequester(channelPutGetRequester),
609  pvPutCopy(pvPutCopy),
610  pvGetCopy(pvGetCopy),
611  pvGetStructure(pvGetStructure),
612  getBitSet(getBitSet),
613  pvRecord(pvRecord)
614  {
615  }
616  bool callProcess;
617  ChannelLocalWPtr channelLocal;
618  ChannelPutGetRequester::weak_pointer channelPutGetRequester;
619  PVCopyPtr pvPutCopy;
620  PVCopyPtr pvGetCopy;
621  PVStructurePtr pvGetStructure;
622  BitSetPtr getBitSet;
623  PVRecordWPtr pvRecord;
624  Mutex mutex;
625 };
626 
627 ChannelPutGetLocalPtr ChannelPutGetLocal::create(
628  ChannelLocalPtr const &channelLocal,
629  ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
630  PVStructurePtr const & pvRequest,
631  PVRecordPtr const &pvRecord)
632 {
633  PVCopyPtr pvPutCopy = PVCopy::create(
634  pvRecord->getPVRecordStructure()->getPVStructure(),
635  pvRequest,
636  "putField");
637  PVCopyPtr pvGetCopy = PVCopy::create(
638  pvRecord->getPVRecordStructure()->getPVStructure(),
639  pvRequest,
640  "getField");
641  if(!pvPutCopy || !pvGetCopy) {
642  Status status(
643  Status::STATUSTYPE_ERROR,
644  "invalid pvRequest");
645  ChannelPutGet::shared_pointer channelPutGet;
646  channelPutGetRequester->channelPutGetConnect(
647  status,
648  channelPutGet,
649  nullStructure,
650  nullStructure);
651  ChannelPutGetLocalPtr localPutGet;
652  return localPutGet;
653  }
654  PVStructurePtr pvGetStructure = pvGetCopy->createPVStructure();
655  BitSetPtr getBitSet(new BitSet(pvGetStructure->getNumberFields()));
656  ChannelPutGetLocalPtr putGet(new ChannelPutGetLocal(
657  getProcess(pvRequest,true),
658  channelLocal,
659  channelPutGetRequester,
660  pvPutCopy,
661  pvGetCopy,
662  pvGetStructure,
663  getBitSet,
664  pvRecord));
665  if(pvRecord->getTraceLevel()>0)
666  {
667  cout << "ChannelPutGetLocal::create";
668  cout << " recordName " << pvRecord->getRecordName() << endl;
669  }
670  channelPutGetRequester->channelPutGetConnect(
671  Status::Ok, putGet, pvPutCopy->getStructure(),pvGetCopy->getStructure());
672  return putGet;
673 }
674 
675 ChannelPutGetLocal::~ChannelPutGetLocal()
676 {
677 //cout << "~ChannelPutGetLocal()\n";
678 }
679 
680 std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
681 {
682  ChannelLocalPtr channel(channelLocal.lock());
683  return channel;
684 }
685 
686 void ChannelPutGetLocal::lock()
687 {
688  PVRecordPtr pvr(pvRecord.lock());
689  if(!pvr) throw std::logic_error("pvRecord is deleted");
690  pvr->lock();
691 }
692 void ChannelPutGetLocal::unlock()
693 {
694  PVRecordPtr pvr(pvRecord.lock());
695  if(!pvr) throw std::logic_error("pvRecord is deleted");
696  pvr->unlock();
697 }
698 
699 
700 void ChannelPutGetLocal::putGet(
701  PVStructurePtr const &pvPutStructure,BitSetPtr const &putBitSet)
702 {
703  ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
704  if(!requester) return;
705  ChannelLocalPtr channel(channelLocal.lock());
706  if(!channel) throw std::logic_error("channel is deleted");
707  if(!channel->canWrite()||!channel->canRead() ) {
708  Status status = Status::error("ChannelPutGet::putGet is not allowed");
709  requester->putGetDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
710  return;
711  }
712  PVRecordPtr pvr(pvRecord.lock());
713  if(!pvr) throw std::logic_error("pvRecord is deleted");
714  try {
715  {
716  epicsGuard <PVRecord> guard(*pvr);
717  pvr->beginGroupPut();
718  pvPutCopy->updateMaster(pvPutStructure, putBitSet);
719  if(callProcess) pvr->process();
720  getBitSet->clear();
721  pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet);
722  pvr->endGroupPut();
723  }
724  requester->putGetDone(
725  Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
726  if(pvr->getTraceLevel()>1)
727  {
728  cout << "ChannelPutGetLocal::putGet" << endl;
729  }
730  } catch(std::exception& ex) {
731  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
732  requester->putGetDone(status,getPtrSelf(),pvGetStructure,getBitSet);
733  }
734 }
735 
736 void ChannelPutGetLocal::getPut()
737 {
738  ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
739  if(!requester) return;
740  ChannelLocalPtr channel(channelLocal.lock());
741  if(!channel) throw std::logic_error("channel is deleted");
742  if(!channel->canRead()) {
743  Status status = Status::error("ChannelPutGet::getPut is not allowed");
744  requester->getPutDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
745  return;
746  }
747  PVRecordPtr pvr(pvRecord.lock());
748  if(!pvr) throw std::logic_error("pvRecord is deleted");
749  try {
750  PVStructurePtr pvPutStructure = pvPutCopy->createPVStructure();
751  BitSetPtr putBitSet(new BitSet(pvPutStructure->getNumberFields()));
752  {
753  epicsGuard <PVRecord> guard(*pvr);
754  pvPutCopy->initCopy(pvPutStructure, putBitSet);
755  }
756  requester->getPutDone(
757  Status::Ok,getPtrSelf(),pvPutStructure,putBitSet);
758  if(pvr->getTraceLevel()>1)
759  {
760  cout << "ChannelPutGetLocal::getPut" << endl;
761  }
762  } catch(std::exception& ex) {
763  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
764  PVStructurePtr pvPutStructure;
765  BitSetPtr putBitSet;
766  requester->getPutDone(status,getPtrSelf(),pvGetStructure,getBitSet);
767  }
768 }
769 
770 void ChannelPutGetLocal::getGet()
771 {
772  ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
773  if(!requester) return;
774  ChannelLocalPtr channel(channelLocal.lock());
775  if(!channel) throw std::logic_error("channel is deleted");
776  if(!channel->canRead()) {
777  Status status = Status::error("ChannelPutGet::getGet is not allowed");
778  requester->getPutDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
779  return;
780  }
781  PVRecordPtr pvr(pvRecord.lock());
782  if(!pvr) throw std::logic_error("pvRecord is deleted");
783  try {
784  getBitSet->clear();
785  {
786  epicsGuard <PVRecord> guard(*pvr);
787  pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet);
788  }
789  requester->getGetDone(
790  Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
791  if(pvr->getTraceLevel()>1)
792  {
793  cout << "ChannelPutGetLocal::getGet" << endl;
794  }
795  } catch(std::exception& ex) {
796  Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
797  PVStructurePtr pvPutStructure;
798  BitSetPtr putBitSet;
799  requester->getGetDone(status,getPtrSelf(),pvGetStructure,getBitSet);
800  }
801 }
802 
803 
804 class ChannelRPCLocal :
805  public epics::pvAccess::ChannelRPC,
806  public epics::pvAccess::RPCResponseCallback,
807  public std::tr1::enable_shared_from_this<ChannelRPCLocal>
808 {
809 public:
810  POINTER_DEFINITIONS(ChannelRPCLocal);
811  static ChannelRPCLocalPtr create(
812  ChannelLocalPtr const & channelLocal,
813  ChannelRPCRequester::shared_pointer const & channelRPCRequester,
814  PVStructurePtr const & pvRequest,
815  PVRecordPtr const & pvRecord);
816 
817  ChannelRPCLocal(
818  ChannelLocalPtr const & channelLocal,
819  ChannelRPCRequester::shared_pointer const & channelRPCRequester,
820  RPCServiceAsync::shared_pointer const & service,
821  PVRecordPtr const & pvRecord) :
822  channelLocal(channelLocal),
823  channelRPCRequester(channelRPCRequester),
824  service(service),
825  pvRecord(pvRecord)
826  {
827  }
828 
829  virtual ~ChannelRPCLocal();
830  void processRequest(RPCService::shared_pointer const & service,
831  PVStructurePtr const & pvArgument);
832 
833  virtual void requestDone(Status const & status,
834  PVStructurePtr const & result)
835  {
836  ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
837  if(!requester) return;
838  requester->requestDone(status, getPtrSelf(), result);
839  }
840 
841  void processRequest(RPCServiceAsync::shared_pointer const & service,
842  PVStructurePtr const & pvArgument);
843 
844  virtual void request(PVStructurePtr const & pvArgument);
845  virtual Channel::shared_pointer getChannel();
846  virtual void cancel() {}
847  virtual void lock() {}
848  virtual void unlock() {}
849  virtual void lastRequest() {}
850 private:
851  shared_pointer getPtrSelf()
852  {
853  return shared_from_this();
854  }
855  ChannelLocalWPtr channelLocal;
856  ChannelRPCRequester::weak_pointer channelRPCRequester;
857  RPCServiceAsync::shared_pointer service;
858  PVRecordWPtr pvRecord;
859 };
860 
861 ChannelRPCLocalPtr ChannelRPCLocal::create(
862  ChannelLocalPtr const &channelLocal,
863  ChannelRPCRequester::shared_pointer const & channelRPCRequester,
864  PVStructurePtr const & pvRequest,
865  PVRecordPtr const &pvRecord)
866 {
867  RPCServiceAsync::shared_pointer service = pvRecord->getService(pvRequest);
868  if (!service)
869  {
870  Status status(Status::STATUSTYPE_ERROR,
871  "ChannelRPC not supported");
872  channelRPCRequester->channelRPCConnect(status,ChannelRPCLocalPtr());
873  return ChannelRPCLocalPtr();
874  }
875 
876  if (!channelRPCRequester)
877  throw std::invalid_argument("channelRPCRequester == null");
878 
879  // TODO use std::make_shared
880  ChannelRPCLocalPtr rpc(
881  new ChannelRPCLocal(channelLocal, channelRPCRequester, service, pvRecord)
882  );
883  channelRPCRequester->channelRPCConnect(Status::Ok, rpc);
884  if(pvRecord->getTraceLevel()>0)
885  {
886  cout << "ChannelRPCLocal::create";
887  cout << " recordName " << pvRecord->getRecordName() << endl;
888  }
889  return rpc;
890 }
891 
892 ChannelRPCLocal::~ChannelRPCLocal()
893 {
894 //cout << "~ChannelRPCLocal()\n";
895 }
896 
897 std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
898 {
899  ChannelLocalPtr channel(channelLocal.lock());
900  return channel;
901 }
902 
903 
904 void ChannelRPCLocal::processRequest(
905  RPCService::shared_pointer const & service,
906  PVStructurePtr const & pvArgument)
907 {
908  PVStructurePtr result;
909  Status status = Status::Ok;
910  bool ok = true;
911  try
912  {
913  result = service->request(pvArgument);
914  }
915  catch (epics::pvAccess::RPCRequestException& rre)
916  {
917  status = Status(rre.getStatus(), rre.what());
918  ok = false;
919  }
920  catch (std::exception& ex)
921  {
922  status = Status(Status::STATUSTYPE_FATAL, ex.what());
923  ok = false;
924  }
925  catch (...)
926  {
927  // handle user unexpected errors
928  status = Status(Status::STATUSTYPE_FATAL, "Unexpected exception caught while calling RPCService.request(PVStructure).");
929  ok = false;
930  }
931 
932  // check null result
933  if (ok && !result)
934  {
935  status = Status(Status::STATUSTYPE_FATAL, "RPCService.request(PVStructure) returned null.");
936  }
937  ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
938  if(requester) requester->requestDone(status, getPtrSelf(), result);
939 }
940 
941 void ChannelRPCLocal::processRequest(
942  RPCServiceAsync::shared_pointer const & service,
943  PVStructurePtr const & pvArgument)
944 {
945  try
946  {
947  service->request(pvArgument, getPtrSelf());
948  }
949  catch (std::exception& ex)
950  {
951  // handle user unexpected errors
952  Status errorStatus(Status::STATUSTYPE_FATAL, ex.what());
953  ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
954  if(requester) requester->requestDone(errorStatus, getPtrSelf(), PVStructurePtr());
955  }
956  catch (...)
957  {
958  // handle user unexpected errors
959  Status errorStatus(Status::STATUSTYPE_FATAL,
960  "Unexpected exception caught while calling RPCServiceAsync.request(PVStructure, RPCResponseCallback).");
961  ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
962  if(requester) requester->requestDone(errorStatus, shared_from_this(), PVStructurePtr());
963  }
964 
965  // we wait for callback to be called
966 }
967 
968 
969 void ChannelRPCLocal::request(PVStructurePtr const & pvArgument)
970 {
971  PVRecordPtr pvr(pvRecord.lock());
972  if(pvr && pvr->getTraceLevel()>0) {
973  cout << "ChannelRPCLocal::request " << pvr->getRecordName() << endl;
974  }
975  RPCService::shared_pointer rpcService =
976  std::tr1::dynamic_pointer_cast<RPCService>(service);
977  if (rpcService)
978  {
979  processRequest(rpcService, pvArgument);
980  return;
981  }
982 
983  RPCServiceAsync::shared_pointer rpcServiceAsync =
984  std::tr1::dynamic_pointer_cast<RPCServiceAsync>(service);
985  if (rpcServiceAsync)
986  {
987  processRequest(rpcServiceAsync, pvArgument);
988  return;
989  }
990 }
991 
992 
993 typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
994 
995 class ChannelArrayLocal :
996  public epics::pvAccess::ChannelArray,
997  public std::tr1::enable_shared_from_this<ChannelArrayLocal>
998 {
999 public:
1000  POINTER_DEFINITIONS(ChannelArrayLocal);
1001  virtual ~ChannelArrayLocal();
1002  static ChannelArrayLocalPtr create(
1003  ChannelLocalPtr const &channelLocal,
1004  ChannelArrayRequester::shared_pointer const & channelArrayRequester,
1005  PVStructurePtr const & pvRequest,
1006  PVRecordPtr const &pvRecord);
1007  virtual void getArray(size_t offset, size_t count, size_t stride);
1008  virtual void putArray(
1009  PVArrayPtr const &putArray,
1010  size_t offset, size_t count, size_t stride);
1011  virtual void getLength();
1012  virtual void setLength(size_t length);
1013  virtual std::tr1::shared_ptr<Channel> getChannel();
1014  virtual void cancel(){}
1015  virtual void lock();
1016  virtual void unlock();
1017  virtual void lastRequest() {}
1018 private:
1019  shared_pointer getPtrSelf()
1020  {
1021  return shared_from_this();
1022  }
1023  ChannelArrayLocal(
1024  ChannelLocalPtr const &channelLocal,
1025  ChannelArrayRequester::shared_pointer const & channelArrayRequester,
1026  PVArrayPtr const &pvArray,
1027  PVArrayPtr const &pvCopy,
1028  PVRecordPtr const &pvRecord)
1029  :
1030  channelLocal(channelLocal),
1031  channelArrayRequester(channelArrayRequester),
1032  pvArray(pvArray),
1033  pvCopy(pvCopy),
1034  pvRecord(pvRecord)
1035  {
1036  }
1037 
1038  ChannelLocalWPtr channelLocal;
1039  ChannelArrayRequester::weak_pointer channelArrayRequester;
1040  PVArrayPtr pvArray;
1041  PVArrayPtr pvCopy;
1042  PVRecordWPtr pvRecord;
1043  Mutex mutex;
1044 };
1045 
1046 
1047 ChannelArrayLocalPtr ChannelArrayLocal::create(
1048  ChannelLocalPtr const &channelLocal,
1049  ChannelArrayRequester::shared_pointer const & channelArrayRequester,
1050  PVStructurePtr const & pvRequest,
1051  PVRecordPtr const &pvRecord)
1052 {
1053  PVFieldPtrArray const & pvFields = pvRequest->getPVFields();
1054  if(pvFields.size()!=1) {
1055  Status status(
1056  Status::STATUSTYPE_ERROR,"invalid pvRequest");
1057  ChannelArrayLocalPtr channelArray;
1058  ArrayConstPtr array;
1059  channelArrayRequester->channelArrayConnect(status,channelArray,array);
1060  return channelArray;
1061  }
1062  PVFieldPtr pvField = pvFields[0];
1063  string fieldName("");
1064  while(true) {
1065  string name = pvField->getFieldName();
1066  if(fieldName.size()>0) fieldName += '.';
1067  fieldName += name;
1068  PVStructurePtr pvs = static_pointer_cast<PVStructure>(pvField);
1069  PVFieldPtrArray const & pvfs = pvs->getPVFields();
1070  if(pvfs.size()!=1) break;
1071  pvField = pvfs[0];
1072  }
1073  size_t indfield = fieldName.find_first_of("field.");
1074  if(indfield==0) {
1075  fieldName = fieldName.substr(6);
1076  }
1077  pvField = pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(fieldName);
1078  if(!pvField) {
1079  Status status(
1080  Status::STATUSTYPE_ERROR,fieldName +" not found");
1081  ChannelArrayLocalPtr channelArray;
1082  ArrayConstPtr array;
1083  channelArrayRequester->channelArrayConnect(
1084  status,channelArray,array);
1085  return channelArray;
1086  }
1087  if(pvField->getField()->getType()!=scalarArray
1088  && pvField->getField()->getType()!=structureArray
1089  && pvField->getField()->getType()!=unionArray)
1090  {
1091  Status status(
1092  Status::STATUSTYPE_ERROR,fieldName +" not array");
1093  ChannelArrayLocalPtr channelArray;
1094  ArrayConstPtr array;
1095  channelArrayRequester->channelArrayConnect(
1096  status,channelArray,array);
1097  return channelArray;
1098  }
1099  PVArrayPtr pvArray = static_pointer_cast<PVArray>(pvField);
1100  PVArrayPtr pvCopy;
1101  if(pvField->getField()->getType()==scalarArray) {
1102  PVScalarArrayPtr xxx = static_pointer_cast<PVScalarArray>(pvField);
1103  pvCopy = getPVDataCreate()->createPVScalarArray(
1104  xxx->getScalarArray()->getElementType());
1105  } else if(pvField->getField()->getType()==structureArray) {
1106  PVStructureArrayPtr xxx = static_pointer_cast<PVStructureArray>(pvField);
1107  pvCopy = getPVDataCreate()->createPVStructureArray(
1108  xxx->getStructureArray()->getStructure());
1109  } else {
1110  PVUnionArrayPtr xxx = static_pointer_cast<PVUnionArray>(pvField);
1111  pvCopy = getPVDataCreate()->createPVUnionArray(
1112  xxx->getUnionArray()->getUnion());
1113  }
1114  ChannelArrayLocalPtr array(new ChannelArrayLocal(
1115  channelLocal,
1116  channelArrayRequester,
1117  pvArray,
1118  pvCopy,
1119  pvRecord));
1120  if(pvRecord->getTraceLevel()>0)
1121  {
1122  cout << "ChannelArrayLocal::create";
1123  cout << " recordName " << pvRecord->getRecordName() << endl;
1124  }
1125  channelArrayRequester->channelArrayConnect(
1126  Status::Ok, array, pvCopy->getArray());
1127  return array;
1128 }
1129 
1130 ChannelArrayLocal::~ChannelArrayLocal()
1131 {
1132 //cout << "~ChannelArrayLocal()\n";
1133 }
1134 
1135 std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
1136 {
1137  ChannelLocalPtr channel(channelLocal.lock());
1138  return channel;
1139 }
1140 
1141 void ChannelArrayLocal::lock()
1142 {
1143  PVRecordPtr pvr(pvRecord.lock());
1144  if(!pvr) throw std::logic_error("pvRecord is deleted");
1145  pvr->lock();
1146 }
1147 void ChannelArrayLocal::unlock()
1148 {
1149  PVRecordPtr pvr(pvRecord.lock());
1150  if(!pvr) throw std::logic_error("pvRecord is deleted");
1151  pvr->unlock();
1152 }
1153 
1154 void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
1155 {
1156  ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1157  if(!requester) return;
1158  PVRecordPtr pvr(pvRecord.lock());
1159  if(!pvr) throw std::logic_error("pvRecord is deleted");
1160  if(pvr->getTraceLevel()>1)
1161  {
1162  cout << "ChannelArrayLocal::getArray" << endl;
1163  }
1164  const char *exceptionMessage = NULL;
1165  try {
1166  bool ok = false;
1167  epicsGuard <PVRecord> guard(*pvr);
1168  while(true) {
1169  size_t length = pvArray->getLength();
1170  if(length<=0) break;
1171  if(count<=0) {
1172  count = (length -offset + stride -1)/stride;
1173  if(count>0) ok = true;
1174  break;
1175  }
1176  size_t maxcount = (length -offset + stride -1)/stride;
1177  if(count>maxcount) count = maxcount;
1178  ok = true;
1179  break;
1180  }
1181  if(ok) {
1182  pvCopy->setLength(count);
1183  copy(pvArray,offset,stride,pvCopy,0,1,count);
1184  }
1185  } catch(std::exception& e) {
1186  exceptionMessage = e.what();
1187  }
1188  Status status = Status::Ok;
1189  if(exceptionMessage!=NULL) {
1190  status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1191  }
1192  requester->getArrayDone(status,getPtrSelf(),pvCopy);
1193 }
1194 
1195 void ChannelArrayLocal::putArray(
1196  PVArrayPtr const & pvArray, size_t offset, size_t count, size_t stride)
1197 {
1198  ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1199  if(!requester) return;
1200  PVRecordPtr pvr(pvRecord.lock());
1201  if(!pvr) throw std::logic_error("pvRecord is deleted");
1202  if(pvr->getTraceLevel()>1)
1203  {
1204  cout << "ChannelArrayLocal::putArray" << endl;
1205  }
1206  size_t newLength = offset + count*stride;
1207  if(newLength<pvArray->getLength()) pvArray->setLength(newLength);
1208  const char *exceptionMessage = NULL;
1209  try {
1210  epicsGuard <PVRecord> guard(*pvr);
1211  copy(pvArray,0,1,this->pvArray,offset,stride,count);
1212  } catch(std::exception& e) {
1213  exceptionMessage = e.what();
1214  }
1215  Status status = Status::Ok;
1216  if(exceptionMessage!=NULL) {
1217  status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1218  }
1219  requester->putArrayDone(status,getPtrSelf());
1220 }
1221 
1222 void ChannelArrayLocal::getLength()
1223 {
1224  ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1225  if(!requester) return;
1226  PVRecordPtr pvr(pvRecord.lock());
1227  if(!pvr) throw std::logic_error("pvRecord is deleted");
1228  size_t length = 0;
1229  const char *exceptionMessage = NULL;
1230  try {
1231  epicsGuard <PVRecord> guard(*pvr);
1232  length = pvArray->getLength();
1233  } catch(std::exception& e) {
1234  exceptionMessage = e.what();
1235  }
1236  Status status = Status::Ok;
1237  if(exceptionMessage!=NULL) {
1238  status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1239  }
1240  requester->getLengthDone(status,getPtrSelf(),length);
1241 }
1242 
1243 void ChannelArrayLocal::setLength(size_t length)
1244 {
1245  ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1246  if(!requester) return;
1247  PVRecordPtr pvr(pvRecord.lock());
1248  if(!pvr) throw std::logic_error("pvRecord is deleted");
1249  if(pvr->getTraceLevel()>1)
1250  {
1251  cout << "ChannelArrayLocal::setLength" << endl;
1252  }
1253  try {
1254  {
1255  epicsGuard <PVRecord> guard(*pvr);
1256  if(pvArray->getLength()!=length) pvArray->setLength(length);
1257  }
1258  requester->setLengthDone(Status::Ok,getPtrSelf());
1259  } catch(std::exception& e) {
1260  string exceptionMessage = e.what();
1261  Status status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1262  requester->setLengthDone(status,getPtrSelf());
1263  }
1264 }
1265 
1266 
1267 ChannelLocal::ChannelLocal(
1268  ChannelProviderLocalPtr const & provider,
1269  ChannelRequester::shared_pointer const & requester,
1270  PVRecordPtr const & pvRecord)
1271 :
1272  requester(requester),
1273  provider(provider),
1274  pvRecord(pvRecord),
1275  asLevel(pvRecord->getAsLevel()),
1276  asGroup(getAsGroup(pvRecord)),
1277  asUser(getAsUser(requester)),
1278  asHost(getAsHost(requester)),
1279  asMemberPvt(0),
1280  asClientPvt(0)
1281 {
1282  if(pvRecord->getTraceLevel()>0) {
1283  cout << "ChannelLocal::ChannelLocal()"
1284  << " recordName " << pvRecord->getRecordName()
1285  << " requester exists " << (requester ? "true" : "false")
1286  << endl;
1287  }
1288  if (pvRecord->getAsGroup().empty() || asAddMember(&asMemberPvt, &asGroup[0]) != 0) {
1289  asMemberPvt = 0;
1290  }
1291  if (asMemberPvt) {
1292  asAddClient(&asClientPvt, asMemberPvt, asLevel, &asUser[0], &asHost[0]);
1293  }
1294 }
1295 
1296 std::vector<char> ChannelLocal::toCharArray(const std::string& s)
1297 {
1298  std::vector<char> v(s.begin(), s.end());
1299  v.push_back('\0');
1300  return v;
1301 }
1302 
1303 std::vector<char> ChannelLocal::getAsGroup(const PVRecordPtr& pvRecord)
1304 {
1305  return toCharArray(pvRecord->getAsGroup());
1306 }
1307 
1308 std::vector<char> ChannelLocal::getAsUser(const ChannelRequester::shared_pointer& requester)
1309 {
1310  PeerInfo::const_shared_pointer info(requester->getPeerInfo());
1311  std::string user;
1312  if(info && info->identified) {
1313  if(info->authority=="ca") {
1314  user = info->account;
1315  size_t first = user.find_last_of('/');
1316  if(first != std::string::npos) {
1317  // prevent CA accounts like "<authority>/<user>"
1318  user = user.substr(first+1);
1319  }
1320  }
1321  else {
1322  user = info->authority + "/" + info->account;
1323  }
1324  }
1325  return toCharArray(user);
1326 }
1327 
1328 std::vector<char> ChannelLocal::getAsHost(const epics::pvAccess::ChannelRequester::shared_pointer& requester)
1329 {
1330  PeerInfo::const_shared_pointer info(requester->getPeerInfo());
1331  std::string host;
1332  if(info && info->identified) {
1333  host= info->peer;
1334  }
1335  else {
1336  // anonymous
1337  host = requester->getRequesterName();
1338  }
1339 
1340  // handle form "ip:port"
1341  size_t last = host.find_first_of(':');
1342  if(last == std::string::npos) {
1343  last = host.size();
1344  }
1345  host.resize(last);
1346  return toCharArray(host);
1347 }
1348 
1350 {
1351  if(!asActive || (asClientPvt && asCheckPut(asClientPvt))) {
1352  return true;
1353  }
1354  return false;
1355 }
1356 
1358 {
1359  if(!asActive || (asClientPvt && asCheckGet(asClientPvt))) {
1360  return true;
1361  }
1362  return false;
1363 }
1365 {
1366  if(asMemberPvt) {
1367  asRemoveMember(&asMemberPvt);
1368  asMemberPvt = 0;
1369  }
1370  if(asClientPvt) {
1371  asRemoveClient(&asClientPvt);
1372  asClientPvt = 0;
1373  }
1374 }
1375 
1376 ChannelProvider::shared_pointer ChannelLocal::getProvider()
1377 {
1378  return provider.lock();
1379 }
1380 
1381 void ChannelLocal::detach(PVRecordPtr const & pvRecord)
1382 {
1383  if(pvRecord->getTraceLevel()>0) {
1384  cout << "ChannelLocal::detach() "
1385  << " recordName " << pvRecord->getRecordName()
1386  << " requester exists " << (requester ? "true" : "false")
1387  << endl;
1388  }
1389  if(!requester) return;
1390  requester->channelStateChange(shared_from_this(),Channel::DESTROYED);
1391 }
1392 
1393 
1395 {
1396  PVRecordPtr pvr(pvRecord.lock());
1397  if(pvr && pvr->getTraceLevel()>0) {
1398  cout << "ChannelLocal::getRequesterName() "
1399  << " recordName " << pvr->getRecordName()
1400  << " requester exists " << (requester ? "true" : "false")
1401  << endl;
1402  }
1403 
1404  if(!requester) return string();
1405  return requester->getRequesterName();
1406 }
1407 
1409  string const &message,
1410  MessageType messageType)
1411 {
1412  PVRecordPtr pvr(pvRecord.lock());
1413  if(pvr && pvr->getTraceLevel()>1) {
1414  cout << "ChannelLocal::message() "
1415  << " recordName " << pvr->getRecordName()
1416  << " requester exists " << (requester ? "true" : "false")
1417  << endl;
1418  }
1419  if(requester) {
1420  requester->message(message,messageType);
1421  return;
1422  }
1423  string recordName("record deleted");
1424  if(pvr) recordName = pvr->getRecordName();
1425  cout << recordName
1426  << " message " << message
1427  << " messageType " << getMessageTypeName(messageType)
1428  << endl;
1429 }
1430 
1432 {
1433  return string("local");
1434 }
1435 
1436 Channel::ConnectionState ChannelLocal::getConnectionState()
1437 {
1438  return Channel::CONNECTED;
1439 }
1440 
1442 {
1443  PVRecordPtr pvr(pvRecord.lock());
1444  string name("record deleted");
1445  if(pvr) name = pvr->getRecordName();
1446  return name;
1447 }
1448 
1449 ChannelRequester::shared_pointer ChannelLocal::getChannelRequester()
1450 {
1451  return requester;
1452 }
1453 
1455 {
1456  return true;
1457 }
1458 
1459 void ChannelLocal::getField(GetFieldRequester::shared_pointer const &requester,
1460  string const &subField)
1461 {
1462  PVRecordPtr pvr(pvRecord.lock());
1463  if(!pvr) throw std::logic_error("pvRecord is deleted");
1464  if(subField.size()<1) {
1465  StructureConstPtr structure =
1466  pvr->getPVRecordStructure()->getPVStructure()->getStructure();
1467  requester->getDone(Status::Ok,structure);
1468  return;
1469  }
1470  PVFieldPtr pvField =
1471  pvr->getPVRecordStructure()->getPVStructure()->getSubField(subField);
1472  if(pvField) {
1473  requester->getDone(Status::Ok,pvField->getField());
1474  return;
1475  }
1476  Status status(Status::STATUSTYPE_ERROR,
1477  "client asked for illegal field");
1478  requester->getDone(status,FieldConstPtr());
1479 }
1480 
1482  PVField::shared_pointer const &pvField)
1483 {
1484  throw std::logic_error("Not Implemented");
1485 }
1486 
1487 ChannelProcess::shared_pointer ChannelLocal::createChannelProcess(
1488  ChannelProcessRequester::shared_pointer const & channelProcessRequester,
1489  PVStructure::shared_pointer const & pvRequest)
1490 {
1491  PVRecordPtr pvr(pvRecord.lock());
1492  if(!pvr) throw std::logic_error("pvRecord is deleted");
1493  if(pvr->getTraceLevel()>0) {
1494  cout << "ChannelLocal::createChannelProcess() "
1495  << " recordName " << pvr->getRecordName()
1496  << " requester exists " << (requester ? "true" : "false")
1497  << endl;
1498  }
1499  ChannelProcessLocalPtr channelProcess =
1500  ChannelProcessLocal::create(
1501  getPtrSelf(),
1502  channelProcessRequester,
1503  pvRequest,
1504  pvr);
1505  return channelProcess;
1506 }
1507 
1508 ChannelGet::shared_pointer ChannelLocal::createChannelGet(
1509  ChannelGetRequester::shared_pointer const &channelGetRequester,
1510  PVStructure::shared_pointer const &pvRequest)
1511 {
1512  PVRecordPtr pvr(pvRecord.lock());
1513  if(!pvr) throw std::logic_error("pvRecord is deleted");
1514  if(pvr->getTraceLevel()>0) {
1515  cout << "ChannelLocal::createChannelGet() "
1516  << " recordName " << pvr->getRecordName()
1517  << " requester exists " << (requester ? "true" : "false")
1518  << endl;
1519  }
1520  ChannelGetLocalPtr channelGet =
1521  ChannelGetLocal::create(
1522  getPtrSelf(),
1523  channelGetRequester,
1524  pvRequest,
1525  pvr);
1526  return channelGet;
1527 }
1528 
1529 ChannelPut::shared_pointer ChannelLocal::createChannelPut(
1530  ChannelPutRequester::shared_pointer const &channelPutRequester,
1531  PVStructure::shared_pointer const &pvRequest)
1532 {
1533  PVRecordPtr pvr(pvRecord.lock());
1534  if(!pvr) throw std::logic_error("pvRecord is deleted");
1535  if(pvr->getTraceLevel()>0) {
1536  cout << "ChannelLocal::createChannelPut() "
1537  << " recordName " << pvr->getRecordName()
1538  << " requester exists " << (requester ? "true" : "false")
1539  << endl;
1540  }
1541 
1542  ChannelPutLocalPtr channelPut =
1543  ChannelPutLocal::create(
1544  getPtrSelf(),
1545  channelPutRequester,
1546  pvRequest,
1547  pvr);
1548  return channelPut;
1549 }
1550 
1551 ChannelPutGet::shared_pointer ChannelLocal::createChannelPutGet(
1552  ChannelPutGetRequester::shared_pointer const &channelPutGetRequester,
1553  PVStructure::shared_pointer const &pvRequest)
1554 {
1555  PVRecordPtr pvr(pvRecord.lock());
1556  if(!pvr) throw std::logic_error("pvRecord is deleted");
1557  if(pvr->getTraceLevel()>0) {
1558  cout << "ChannelLocal::createChannelPutGet() "
1559  << " recordName " << pvr->getRecordName()
1560  << " requester exists " << (requester ? "true" : "false")
1561  << endl;
1562  }
1563 
1564  ChannelPutGetLocalPtr channelPutGet =
1565  ChannelPutGetLocal::create(
1566  getPtrSelf(),
1567  channelPutGetRequester,
1568  pvRequest,
1569  pvr);
1570  return channelPutGet;
1571 }
1572 
1573 ChannelRPC::shared_pointer ChannelLocal::createChannelRPC(
1574  ChannelRPCRequester::shared_pointer const & channelRPCRequester,
1575  PVStructure::shared_pointer const & pvRequest)
1576 {
1577  PVRecordPtr pvr(pvRecord.lock());
1578  if(!pvr) throw std::logic_error("pvRecord is deleted");
1579  if(pvr->getTraceLevel()>0) {
1580  cout << "ChannelLocal::createChannelRPC() "
1581  << " recordName " << pvr->getRecordName()
1582  << " requester exists " << (requester ? "true" : "false")
1583  << endl;
1584  }
1585 
1586  ChannelRPCLocalPtr channelRPC =
1587  ChannelRPCLocal::create(
1588  getPtrSelf(),
1589  channelRPCRequester,
1590  pvRequest,
1591  pvr);
1592  return channelRPC;
1593 }
1594 
1595 Monitor::shared_pointer ChannelLocal::createMonitor(
1596  MonitorRequester::shared_pointer const &monitorRequester,
1597  PVStructure::shared_pointer const &pvRequest)
1598 {
1599  PVRecordPtr pvr(pvRecord.lock());
1600  if(!pvr) throw std::logic_error("pvRecord is deleted");
1601  if(pvr->getTraceLevel()>0) {
1602  cout << "ChannelLocal::createMonitor() "
1603  << " recordName " << pvr->getRecordName()
1604  << " requester exists " << (requester ? "true" : "false")
1605  << endl;
1606  }
1607 
1608  MonitorPtr monitor = createMonitorLocal(
1609  pvr,
1610  monitorRequester,
1611  pvRequest);
1612  return monitor;
1613 }
1614 
1615 ChannelArray::shared_pointer ChannelLocal::createChannelArray(
1616  ChannelArrayRequester::shared_pointer const &channelArrayRequester,
1617  PVStructure::shared_pointer const &pvRequest)
1618 {
1619  PVRecordPtr pvr(pvRecord.lock());
1620  if(!pvr) throw std::logic_error("pvRecord is deleted");
1621  if(pvr->getTraceLevel()>0) {
1622  cout << "ChannelLocal::createChannelArray() "
1623  << " recordName " << pvr->getRecordName()
1624  << " requester exists " << (requester ? "true" : "false")
1625  << endl;
1626  }
1627  ChannelArrayLocalPtr channelArray =
1628  ChannelArrayLocal::create(
1629  getPtrSelf(),
1630  channelArrayRequester,
1631  pvRequest,
1632  pvr);
1633  return channelArray;
1634 }
1635 
1637 {
1638  printInfo(std::cout);
1639 }
1640 
1641 void ChannelLocal::printInfo(std::ostream& out)
1642 {
1643  out << "ChannelLocal provides access to a record in the local PVDatabase";
1644 }
1645 
1646 }}
virtual void printInfo()
calls printInfo(std::cout);
virtual epics::pvAccess::ChannelPut::shared_pointer createChannelPut(epics::pvAccess::ChannelPutRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a channelPut.
virtual bool canRead()
determines if client can read
std::tr1::shared_ptr< PVCopy > PVCopyPtr
Definition: pvPlugin.h:25
virtual bool canWrite()
determines if client can write
virtual std::string getRequesterName()
Get the requester name.
std::tr1::shared_ptr< ChannelRPCLocal > ChannelRPCLocalPtr
std::tr1::shared_ptr< ChannelLocal > ChannelLocalPtr
std::tr1::shared_ptr< PVArray > PVArrayPtr
virtual ~ChannelLocal()
Destructor.
std::tr1::weak_ptr< ChannelLocal > ChannelLocalWPtr
virtual void getField(epics::pvAccess::GetFieldRequester::shared_pointer const &requester, std::string const &subField)
Get the introspection interface for subField.
virtual epics::pvAccess::ChannelRPC::shared_pointer createChannelRPC(epics::pvAccess::ChannelRPCRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a channelRPC.
virtual epics::pvData::Monitor::shared_pointer createMonitor(epics::pvData::MonitorRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a monitor.
virtual epics::pvAccess::ChannelArray::shared_pointer createChannelArray(epics::pvAccess::ChannelArrayRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a channelArray.
epicsShareFunc epics::pvData::MonitorPtr createMonitorLocal(PVRecordPtr const &pvRecord, epics::pvData::MonitorRequester::shared_pointer const &monitorRequester, epics::pvData::PVStructurePtr const &pvRequest)
std::tr1::shared_ptr< ChannelProviderLocal > ChannelProviderLocalPtr
virtual epics::pvAccess::ChannelPutGet::shared_pointer createChannelPutGet(epics::pvAccess::ChannelPutGetRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a channelPutGet.
virtual epics::pvAccess::ChannelProvider::shared_pointer getProvider()
Get the channel provider.
virtual epics::pvAccess::AccessRights getAccessRights(epics::pvData::PVField::shared_pointer const &pvField)
std::tr1::shared_ptr< ChannelPutGetLocal > ChannelPutGetLocalPtr
std::tr1::shared_ptr< PVRecord > PVRecordPtr
Definition: pvDatabase.h:21
std::tr1::shared_ptr< ChannelArrayLocal > ChannelArrayLocalPtr
std::tr1::shared_ptr< ChannelProcessLocal > ChannelProcessLocalPtr
std::tr1::shared_ptr< ChannelGetLocal > ChannelGetLocalPtr
virtual std::string getChannelName()
Get the channel name.
std::tr1::weak_ptr< PVRecord > PVRecordWPtr
Definition: pvDatabase.h:23
virtual epics::pvAccess::ChannelProcess::shared_pointer createChannelProcess(epics::pvAccess::ChannelProcessRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a channelProcess.
virtual epics::pvAccess::ChannelGet::shared_pointer createChannelGet(epics::pvAccess::ChannelGetRequester::shared_pointer const &requester, epics::pvData::PVStructurePtr const &pvRequest)
Create a channelGet.
std::tr1::shared_ptr< ChannelPutLocal > ChannelPutLocalPtr
virtual bool isConnected()
Is the channel connected?
virtual void message(std::string const &message, epics::pvData::MessageType messageType)
Passes the message to the channel requester.
virtual std::string getRemoteAddress()
Get the remote address.
virtual epics::pvAccess::ChannelRequester::shared_pointer getChannelRequester()
Get the channel requester.
virtual epics::pvAccess::Channel::ConnectionState getConnectionState()
virtual void detach(PVRecordPtr const &pvRecord)
Detach from the record.