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> 30 #define epicsExportSharedSymbols 38 using std::tr1::static_pointer_cast;
39 using std::tr1::dynamic_pointer_cast;
44 namespace epics {
namespace pvDatabase {
46 static StructureConstPtr nullStructure;
48 class ChannelProcessLocal;
50 class ChannelGetLocal;
52 class ChannelPutLocal;
54 class ChannelPutGetLocal;
56 class ChannelRPCLocal;
58 class ChannelArrayLocal;
61 static bool getProcess(PVStructurePtr pvRequest,
bool processDefault)
63 PVFieldPtr pvField = pvRequest->getSubField(
"record._options.process");
64 if(!pvField || pvField->getField()->getType()!=scalar) {
65 return processDefault;
67 ScalarConstPtr scalar = static_pointer_cast<
const Scalar>(
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();
76 return processDefault;
79 class ChannelProcessLocal :
80 public epics::pvAccess::ChannelProcess,
81 public std::tr1::enable_shared_from_this<ChannelProcessLocal>
84 POINTER_DEFINITIONS(ChannelProcessLocal);
85 virtual ~ChannelProcessLocal();
86 static ChannelProcessLocalPtr create(
88 ChannelProcessRequester::shared_pointer
const & channelProcessRequester,
89 PVStructurePtr
const & pvRequest,
91 virtual void process();
92 virtual std::tr1::shared_ptr<Channel> getChannel();
93 virtual void cancel(){}
95 virtual void unlock();
96 virtual void lastRequest() {}
98 shared_pointer getPtrSelf()
100 return shared_from_this();
104 ChannelProcessRequester::shared_pointer
const & channelProcessRequester,
108 channelLocal(channelLocal),
109 channelProcessRequester(channelProcessRequester),
115 ChannelProcessRequester::weak_pointer channelProcessRequester;
121 ChannelProcessLocalPtr ChannelProcessLocal::create(
123 ChannelProcessRequester::shared_pointer
const & channelProcessRequester,
124 PVStructurePtr
const & pvRequest,
128 PVStructurePtr pvOptions;
130 if(pvRequest) pvField = pvRequest->getSubField(
"record._options");
132 pvOptions = static_pointer_cast<PVStructure>(pvField);
133 pvField = pvOptions->getSubField(
"nProcess");
135 PVStringPtr pvString = pvOptions->getSubField<PVString>(
"nProcess");
138 std::stringstream ss;
139 ss << pvString->get();
145 ChannelProcessLocalPtr process(
new ChannelProcessLocal(
147 channelProcessRequester,
150 if(pvRecord->getTraceLevel()>0)
152 cout <<
"ChannelProcessLocal::create";
153 cout <<
" recordName " << pvRecord->getRecordName() << endl;
155 channelProcessRequester->channelProcessConnect(Status::Ok, process);
159 ChannelProcessLocal::~ChannelProcessLocal()
164 std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
170 void ChannelProcessLocal::lock()
173 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
176 void ChannelProcessLocal::unlock()
179 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
183 void ChannelProcessLocal::process()
185 ChannelProcessRequester::shared_pointer requester = channelProcessRequester.lock();
186 if(!requester)
return;
188 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
189 if(pvr->getTraceLevel()>1)
191 cout <<
"ChannelProcessLocal::process";
192 cout <<
" nProcess " << nProcess << endl;
195 for(
int i=0; i< nProcess; i++) {
196 epicsGuard <PVRecord> guard(*pvr);
197 pvr->beginGroupPut();
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());
208 class ChannelGetLocal :
209 public epics::pvAccess::ChannelGet,
210 public std::tr1::enable_shared_from_this<ChannelGetLocal>
213 POINTER_DEFINITIONS(ChannelGetLocal);
214 virtual ~ChannelGetLocal();
215 static ChannelGetLocalPtr create(
217 ChannelGetRequester::shared_pointer
const & channelGetRequester,
218 PVStructurePtr
const & pvRequest,
221 virtual std::tr1::shared_ptr<Channel> getChannel();
222 virtual void cancel(){}
224 virtual void unlock();
225 virtual void lastRequest() {}
227 shared_pointer getPtrSelf()
229 return shared_from_this();
234 ChannelGetRequester::shared_pointer
const & channelGetRequester,
236 PVStructurePtr
const&pvStructure,
237 BitSetPtr
const & bitSet,
241 callProcess(callProcess),
242 channelLocal(channelLocal),
243 channelGetRequester(channelGetRequester),
245 pvStructure(pvStructure),
253 ChannelGetRequester::weak_pointer channelGetRequester;
255 PVStructurePtr pvStructure;
261 ChannelGetLocalPtr ChannelGetLocal::create(
263 ChannelGetRequester::shared_pointer
const & channelGetRequester,
264 PVStructurePtr
const & pvRequest,
268 pvRecord->getPVRecordStructure()->getPVStructure(),
273 Status::STATUSTYPE_ERROR,
274 "invalid pvRequest");
275 ChannelGet::shared_pointer channelGet;
276 channelGetRequester->channelGetConnect(
280 ChannelGetLocalPtr localGet;
283 PVStructurePtr pvStructure = pvCopy->createPVStructure();
284 BitSetPtr bitSet(
new BitSet(pvStructure->getNumberFields()));
285 ChannelGetLocalPtr
get(
new ChannelGetLocal(
286 getProcess(pvRequest,
false),
293 if(pvRecord->getTraceLevel()>0)
295 cout <<
"ChannelGetLocal::create";
296 cout <<
" recordName " << pvRecord->getRecordName() << endl;
298 channelGetRequester->channelGetConnect(
299 Status::Ok,
get,pvStructure->getStructure());
303 ChannelGetLocal::~ChannelGetLocal()
308 std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
314 void ChannelGetLocal::lock()
317 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
320 void ChannelGetLocal::unlock()
323 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
328 void ChannelGetLocal::get()
330 ChannelGetRequester::shared_pointer requester = channelGetRequester.lock();
331 if(!requester)
return;
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());
340 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
342 bool notifyClient =
true;
345 epicsGuard <PVRecord> guard(*pvr);
347 pvr->beginGroupPut();
351 notifyClient = pvCopy->updateCopySetBitSet(pvStructure, bitSet);
367 BitSetPtr temp(
new BitSet(bitSet->size()));
374 if(pvr->getTraceLevel()>1)
376 cout <<
"ChannelGetLocal::get" << endl;
378 }
catch(std::exception& ex) {
379 Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
380 requester->getDone(status,getPtrSelf(),pvStructure,bitSet);
385 class ChannelPutLocal :
386 public epics::pvAccess::ChannelPut,
387 public std::tr1::enable_shared_from_this<ChannelPutLocal>
390 POINTER_DEFINITIONS(ChannelPutLocal);
391 virtual ~ChannelPutLocal();
392 static ChannelPutLocalPtr create(
394 ChannelPutRequester::shared_pointer
const & channelPutRequester,
395 PVStructurePtr
const & pvRequest,
397 virtual void put(PVStructurePtr
const &pvStructure,BitSetPtr
const &bitSet);
399 virtual std::tr1::shared_ptr<Channel> getChannel();
400 virtual void cancel(){}
402 virtual void unlock();
403 virtual void lastRequest() {}
405 shared_pointer getPtrSelf()
407 return shared_from_this();
412 ChannelPutRequester::shared_pointer
const & channelPutRequester,
416 callProcess(callProcess),
417 channelLocal(channelLocal),
418 channelPutRequester(channelPutRequester),
425 ChannelPutRequester::weak_pointer channelPutRequester;
431 ChannelPutLocalPtr ChannelPutLocal::create(
433 ChannelPutRequester::shared_pointer
const & channelPutRequester,
434 PVStructurePtr
const & pvRequest,
438 pvRecord->getPVRecordStructure()->getPVStructure(),
443 Status::STATUSTYPE_ERROR,
444 "invalid pvRequest");
445 ChannelPut::shared_pointer channelPut;
446 PVStructurePtr pvStructure;
448 channelPutRequester->channelPutConnect(
452 ChannelPutLocalPtr localPut;
455 ChannelPutLocalPtr put(
new ChannelPutLocal(
456 getProcess(pvRequest,
true),
461 channelPutRequester->channelPutConnect(
462 Status::Ok, put, pvCopy->getStructure());
463 if(pvRecord->getTraceLevel()>0)
465 cout <<
"ChannelPutLocal::create";
466 cout <<
" recordName " << pvRecord->getRecordName() << endl;
471 ChannelPutLocal::~ChannelPutLocal()
476 std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
482 void ChannelPutLocal::lock()
485 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
488 void ChannelPutLocal::unlock()
491 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
496 void ChannelPutLocal::get()
498 ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
499 if(!requester)
return;
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());
508 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
510 PVStructurePtr pvStructure = pvCopy->createPVStructure();
511 BitSetPtr bitSet(
new BitSet(pvStructure->getNumberFields()));
515 epicsGuard <PVRecord> guard(*pvr);
516 pvCopy->updateCopyFromBitSet(pvStructure, bitSet);
519 Status::Ok,getPtrSelf(),pvStructure,bitSet);
520 if(pvr->getTraceLevel()>1)
522 cout <<
"ChannelPutLocal::get" << endl;
524 }
catch(std::exception& ex) {
525 Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
526 PVStructurePtr pvStructure;
528 requester->getDone(status,getPtrSelf(),pvStructure,bitSet);
532 void ChannelPutLocal::put(
533 PVStructurePtr
const &pvStructure,BitSetPtr
const &bitSet)
535 ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
536 if(!requester)
return;
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());
546 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
549 epicsGuard <PVRecord> guard(*pvr);
550 pvr->beginGroupPut();
551 pvCopy->updateMaster(pvStructure, bitSet);
557 requester->putDone(Status::Ok,getPtrSelf());
558 if(pvr->getTraceLevel()>1)
560 cout <<
"ChannelPutLocal::put" << endl;
562 }
catch(std::exception& ex) {
563 Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
564 requester->putDone(status,getPtrSelf());
569 class ChannelPutGetLocal :
570 public epics::pvAccess::ChannelPutGet,
571 public std::tr1::enable_shared_from_this<ChannelPutGetLocal>
574 POINTER_DEFINITIONS(ChannelPutGetLocal);
575 virtual ~ChannelPutGetLocal();
576 static ChannelPutGetLocalPtr create(
578 ChannelPutGetRequester::shared_pointer
const & channelPutGetRequester,
579 PVStructurePtr
const & pvRequest,
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(){}
589 virtual void unlock();
590 virtual void lastRequest() {}
592 shared_pointer getPtrSelf()
594 return shared_from_this();
599 ChannelPutGetRequester::weak_pointer
const & channelPutGetRequester,
602 PVStructurePtr
const&pvGetStructure,
603 BitSetPtr
const & getBitSet,
606 callProcess(callProcess),
607 channelLocal(channelLocal),
608 channelPutGetRequester(channelPutGetRequester),
609 pvPutCopy(pvPutCopy),
610 pvGetCopy(pvGetCopy),
611 pvGetStructure(pvGetStructure),
612 getBitSet(getBitSet),
618 ChannelPutGetRequester::weak_pointer channelPutGetRequester;
621 PVStructurePtr pvGetStructure;
627 ChannelPutGetLocalPtr ChannelPutGetLocal::create(
629 ChannelPutGetRequester::shared_pointer
const & channelPutGetRequester,
630 PVStructurePtr
const & pvRequest,
634 pvRecord->getPVRecordStructure()->getPVStructure(),
638 pvRecord->getPVRecordStructure()->getPVStructure(),
641 if(!pvPutCopy || !pvGetCopy) {
643 Status::STATUSTYPE_ERROR,
644 "invalid pvRequest");
645 ChannelPutGet::shared_pointer channelPutGet;
646 channelPutGetRequester->channelPutGetConnect(
651 ChannelPutGetLocalPtr localPutGet;
654 PVStructurePtr pvGetStructure = pvGetCopy->createPVStructure();
655 BitSetPtr getBitSet(
new BitSet(pvGetStructure->getNumberFields()));
656 ChannelPutGetLocalPtr putGet(
new ChannelPutGetLocal(
657 getProcess(pvRequest,
true),
659 channelPutGetRequester,
665 if(pvRecord->getTraceLevel()>0)
667 cout <<
"ChannelPutGetLocal::create";
668 cout <<
" recordName " << pvRecord->getRecordName() << endl;
670 channelPutGetRequester->channelPutGetConnect(
671 Status::Ok, putGet, pvPutCopy->getStructure(),pvGetCopy->getStructure());
675 ChannelPutGetLocal::~ChannelPutGetLocal()
680 std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
686 void ChannelPutGetLocal::lock()
689 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
692 void ChannelPutGetLocal::unlock()
695 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
700 void ChannelPutGetLocal::putGet(
701 PVStructurePtr
const &pvPutStructure,BitSetPtr
const &putBitSet)
703 ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
704 if(!requester)
return;
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());
713 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
716 epicsGuard <PVRecord> guard(*pvr);
717 pvr->beginGroupPut();
718 pvPutCopy->updateMaster(pvPutStructure, putBitSet);
719 if(callProcess) pvr->process();
721 pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet);
724 requester->putGetDone(
725 Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
726 if(pvr->getTraceLevel()>1)
728 cout <<
"ChannelPutGetLocal::putGet" << endl;
730 }
catch(std::exception& ex) {
731 Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
732 requester->putGetDone(status,getPtrSelf(),pvGetStructure,getBitSet);
736 void ChannelPutGetLocal::getPut()
738 ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
739 if(!requester)
return;
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());
748 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
750 PVStructurePtr pvPutStructure = pvPutCopy->createPVStructure();
751 BitSetPtr putBitSet(
new BitSet(pvPutStructure->getNumberFields()));
753 epicsGuard <PVRecord> guard(*pvr);
754 pvPutCopy->initCopy(pvPutStructure, putBitSet);
756 requester->getPutDone(
757 Status::Ok,getPtrSelf(),pvPutStructure,putBitSet);
758 if(pvr->getTraceLevel()>1)
760 cout <<
"ChannelPutGetLocal::getPut" << endl;
762 }
catch(std::exception& ex) {
763 Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
764 PVStructurePtr pvPutStructure;
766 requester->getPutDone(status,getPtrSelf(),pvGetStructure,getBitSet);
770 void ChannelPutGetLocal::getGet()
772 ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
773 if(!requester)
return;
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());
782 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
786 epicsGuard <PVRecord> guard(*pvr);
787 pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet);
789 requester->getGetDone(
790 Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
791 if(pvr->getTraceLevel()>1)
793 cout <<
"ChannelPutGetLocal::getGet" << endl;
795 }
catch(std::exception& ex) {
796 Status status = Status(Status::STATUSTYPE_FATAL, ex.what());
797 PVStructurePtr pvPutStructure;
799 requester->getGetDone(status,getPtrSelf(),pvGetStructure,getBitSet);
804 class ChannelRPCLocal :
805 public epics::pvAccess::ChannelRPC,
806 public epics::pvAccess::RPCResponseCallback,
807 public std::tr1::enable_shared_from_this<ChannelRPCLocal>
810 POINTER_DEFINITIONS(ChannelRPCLocal);
811 static ChannelRPCLocalPtr create(
813 ChannelRPCRequester::shared_pointer
const & channelRPCRequester,
814 PVStructurePtr
const & pvRequest,
819 ChannelRPCRequester::shared_pointer
const & channelRPCRequester,
820 RPCServiceAsync::shared_pointer
const & service,
822 channelLocal(channelLocal),
823 channelRPCRequester(channelRPCRequester),
829 virtual ~ChannelRPCLocal();
830 void processRequest(RPCService::shared_pointer
const & service,
831 PVStructurePtr
const & pvArgument);
833 virtual void requestDone(Status
const & status,
834 PVStructurePtr
const & result)
836 ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
837 if(!requester)
return;
838 requester->requestDone(status, getPtrSelf(), result);
841 void processRequest(RPCServiceAsync::shared_pointer
const & service,
842 PVStructurePtr
const & pvArgument);
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() {}
851 shared_pointer getPtrSelf()
853 return shared_from_this();
856 ChannelRPCRequester::weak_pointer channelRPCRequester;
857 RPCServiceAsync::shared_pointer service;
861 ChannelRPCLocalPtr ChannelRPCLocal::create(
863 ChannelRPCRequester::shared_pointer
const & channelRPCRequester,
864 PVStructurePtr
const & pvRequest,
867 RPCServiceAsync::shared_pointer service = pvRecord->getService(pvRequest);
870 Status status(Status::STATUSTYPE_ERROR,
871 "ChannelRPC not supported");
876 if (!channelRPCRequester)
877 throw std::invalid_argument(
"channelRPCRequester == null");
880 ChannelRPCLocalPtr rpc(
881 new ChannelRPCLocal(channelLocal, channelRPCRequester, service, pvRecord)
883 channelRPCRequester->channelRPCConnect(Status::Ok, rpc);
884 if(pvRecord->getTraceLevel()>0)
886 cout <<
"ChannelRPCLocal::create";
887 cout <<
" recordName " << pvRecord->getRecordName() << endl;
892 ChannelRPCLocal::~ChannelRPCLocal()
897 std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
904 void ChannelRPCLocal::processRequest(
905 RPCService::shared_pointer
const & service,
906 PVStructurePtr
const & pvArgument)
908 PVStructurePtr result;
909 Status status = Status::Ok;
913 result = service->request(pvArgument);
915 catch (epics::pvAccess::RPCRequestException& rre)
917 status = Status(rre.getStatus(), rre.what());
920 catch (std::exception& ex)
922 status = Status(Status::STATUSTYPE_FATAL, ex.what());
928 status = Status(Status::STATUSTYPE_FATAL,
"Unexpected exception caught while calling RPCService.request(PVStructure).");
935 status = Status(Status::STATUSTYPE_FATAL,
"RPCService.request(PVStructure) returned null.");
937 ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
938 if(requester) requester->requestDone(status, getPtrSelf(), result);
941 void ChannelRPCLocal::processRequest(
942 RPCServiceAsync::shared_pointer
const & service,
943 PVStructurePtr
const & pvArgument)
947 service->request(pvArgument, getPtrSelf());
949 catch (std::exception& ex)
952 Status errorStatus(Status::STATUSTYPE_FATAL, ex.what());
953 ChannelRPCRequester::shared_pointer requester = channelRPCRequester.lock();
954 if(requester) requester->requestDone(errorStatus, getPtrSelf(), PVStructurePtr());
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());
969 void ChannelRPCLocal::request(PVStructurePtr
const & pvArgument)
972 if(pvr && pvr->getTraceLevel()>0) {
973 cout <<
"ChannelRPCLocal::request " << pvr->getRecordName() << endl;
975 RPCService::shared_pointer rpcService =
976 std::tr1::dynamic_pointer_cast<RPCService>(service);
979 processRequest(rpcService, pvArgument);
983 RPCServiceAsync::shared_pointer rpcServiceAsync =
984 std::tr1::dynamic_pointer_cast<RPCServiceAsync>(service);
987 processRequest(rpcServiceAsync, pvArgument);
995 class ChannelArrayLocal :
996 public epics::pvAccess::ChannelArray,
997 public std::tr1::enable_shared_from_this<ChannelArrayLocal>
1000 POINTER_DEFINITIONS(ChannelArrayLocal);
1001 virtual ~ChannelArrayLocal();
1002 static ChannelArrayLocalPtr create(
1004 ChannelArrayRequester::shared_pointer
const & channelArrayRequester,
1005 PVStructurePtr
const & pvRequest,
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() {}
1019 shared_pointer getPtrSelf()
1021 return shared_from_this();
1025 ChannelArrayRequester::shared_pointer
const & channelArrayRequester,
1026 PVArrayPtr
const &pvArray,
1027 PVArrayPtr
const &pvCopy,
1030 channelLocal(channelLocal),
1031 channelArrayRequester(channelArrayRequester),
1039 ChannelArrayRequester::weak_pointer channelArrayRequester;
1047 ChannelArrayLocalPtr ChannelArrayLocal::create(
1049 ChannelArrayRequester::shared_pointer
const & channelArrayRequester,
1050 PVStructurePtr
const & pvRequest,
1053 PVFieldPtrArray
const & pvFields = pvRequest->getPVFields();
1054 if(pvFields.size()!=1) {
1056 Status::STATUSTYPE_ERROR,
"invalid pvRequest");
1057 ChannelArrayLocalPtr channelArray;
1058 ArrayConstPtr array;
1059 channelArrayRequester->channelArrayConnect(status,channelArray,array);
1060 return channelArray;
1062 PVFieldPtr pvField = pvFields[0];
1063 string fieldName(
"");
1065 string name = pvField->getFieldName();
1066 if(fieldName.size()>0) fieldName +=
'.';
1068 PVStructurePtr pvs = static_pointer_cast<PVStructure>(pvField);
1069 PVFieldPtrArray
const & pvfs = pvs->getPVFields();
1070 if(pvfs.size()!=1)
break;
1073 size_t indfield = fieldName.find_first_of(
"field.");
1075 fieldName = fieldName.substr(6);
1077 pvField = pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(fieldName);
1080 Status::STATUSTYPE_ERROR,fieldName +
" not found");
1081 ChannelArrayLocalPtr channelArray;
1082 ArrayConstPtr array;
1083 channelArrayRequester->channelArrayConnect(
1084 status,channelArray,array);
1085 return channelArray;
1087 if(pvField->getField()->getType()!=scalarArray
1088 && pvField->getField()->getType()!=structureArray
1089 && pvField->getField()->getType()!=unionArray)
1092 Status::STATUSTYPE_ERROR,fieldName +
" not array");
1093 ChannelArrayLocalPtr channelArray;
1094 ArrayConstPtr array;
1095 channelArrayRequester->channelArrayConnect(
1096 status,channelArray,array);
1097 return channelArray;
1099 PVArrayPtr pvArray = static_pointer_cast<PVArray>(pvField);
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());
1110 PVUnionArrayPtr xxx = static_pointer_cast<PVUnionArray>(pvField);
1111 pvCopy = getPVDataCreate()->createPVUnionArray(
1112 xxx->getUnionArray()->getUnion());
1114 ChannelArrayLocalPtr array(
new ChannelArrayLocal(
1116 channelArrayRequester,
1120 if(pvRecord->getTraceLevel()>0)
1122 cout <<
"ChannelArrayLocal::create";
1123 cout <<
" recordName " << pvRecord->getRecordName() << endl;
1125 channelArrayRequester->channelArrayConnect(
1126 Status::Ok, array, pvCopy->getArray());
1130 ChannelArrayLocal::~ChannelArrayLocal()
1135 std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
1141 void ChannelArrayLocal::lock()
1144 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
1147 void ChannelArrayLocal::unlock()
1150 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
1154 void ChannelArrayLocal::getArray(
size_t offset,
size_t count,
size_t stride)
1156 ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1157 if(!requester)
return;
1159 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
1160 if(pvr->getTraceLevel()>1)
1162 cout <<
"ChannelArrayLocal::getArray" << endl;
1164 const char *exceptionMessage = NULL;
1167 epicsGuard <PVRecord> guard(*pvr);
1169 size_t length = pvArray->getLength();
1170 if(length<=0)
break;
1172 count = (length -offset + stride -1)/stride;
1173 if(count>0) ok =
true;
1176 size_t maxcount = (length -offset + stride -1)/stride;
1177 if(count>maxcount) count = maxcount;
1182 pvCopy->setLength(count);
1183 copy(pvArray,offset,stride,pvCopy,0,1,count);
1185 }
catch(std::exception& e) {
1186 exceptionMessage = e.what();
1188 Status status = Status::Ok;
1189 if(exceptionMessage!=NULL) {
1190 status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1192 requester->getArrayDone(status,getPtrSelf(),pvCopy);
1195 void ChannelArrayLocal::putArray(
1196 PVArrayPtr
const & pvArray,
size_t offset,
size_t count,
size_t stride)
1198 ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1199 if(!requester)
return;
1201 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
1202 if(pvr->getTraceLevel()>1)
1204 cout <<
"ChannelArrayLocal::putArray" << endl;
1206 size_t newLength = offset + count*stride;
1207 if(newLength<pvArray->getLength()) pvArray->setLength(newLength);
1208 const char *exceptionMessage = NULL;
1210 epicsGuard <PVRecord> guard(*pvr);
1211 copy(pvArray,0,1,this->pvArray,offset,stride,count);
1212 }
catch(std::exception& e) {
1213 exceptionMessage = e.what();
1215 Status status = Status::Ok;
1216 if(exceptionMessage!=NULL) {
1217 status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1219 requester->putArrayDone(status,getPtrSelf());
1222 void ChannelArrayLocal::getLength()
1224 ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1225 if(!requester)
return;
1227 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
1229 const char *exceptionMessage = NULL;
1231 epicsGuard <PVRecord> guard(*pvr);
1232 length = pvArray->getLength();
1233 }
catch(std::exception& e) {
1234 exceptionMessage = e.what();
1236 Status status = Status::Ok;
1237 if(exceptionMessage!=NULL) {
1238 status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
1240 requester->getLengthDone(status,getPtrSelf(),length);
1243 void ChannelArrayLocal::setLength(
size_t length)
1245 ChannelArrayRequester::shared_pointer requester = channelArrayRequester.lock();
1246 if(!requester)
return;
1248 if(!pvr)
throw std::logic_error(
"pvRecord is deleted");
1249 if(pvr->getTraceLevel()>1)
1251 cout <<
"ChannelArrayLocal::setLength" << endl;
1255 epicsGuard <PVRecord> guard(*pvr);
1256 if(pvArray->getLength()!=length) pvArray->setLength(length);
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());
1267 ChannelLocal::ChannelLocal(
1269 ChannelRequester::shared_pointer
const & requester,
1272 requester(requester),
1275 asLevel(pvRecord->getAsLevel()),
1276 asGroup(getAsGroup(pvRecord)),
1277 asUser(getAsUser(requester)),
1278 asHost(getAsHost(requester)),
1282 if(pvRecord->getTraceLevel()>0) {
1283 cout <<
"ChannelLocal::ChannelLocal()" 1284 <<
" recordName " << pvRecord->getRecordName()
1285 <<
" requester exists " << (requester ?
"true" :
"false")
1288 if (pvRecord->getAsGroup().empty() || asAddMember(&asMemberPvt, &asGroup[0]) != 0) {
1292 asAddClient(&asClientPvt, asMemberPvt, asLevel, &asUser[0], &asHost[0]);
1296 std::vector<char> ChannelLocal::toCharArray(
const std::string& s)
1298 std::vector<char> v(s.begin(), s.end());
1303 std::vector<char> ChannelLocal::getAsGroup(
const PVRecordPtr& pvRecord)
1305 return toCharArray(pvRecord->getAsGroup());
1308 std::vector<char> ChannelLocal::getAsUser(
const ChannelRequester::shared_pointer& requester)
1310 PeerInfo::const_shared_pointer info(requester->getPeerInfo());
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) {
1318 user = user.substr(first+1);
1322 user = info->authority +
"/" + info->account;
1325 return toCharArray(user);
1328 std::vector<char> ChannelLocal::getAsHost(
const epics::pvAccess::ChannelRequester::shared_pointer& requester)
1330 PeerInfo::const_shared_pointer info(requester->getPeerInfo());
1332 if(info && info->identified) {
1337 host = requester->getRequesterName();
1341 size_t last = host.find_first_of(
':');
1342 if(last == std::string::npos) {
1346 return toCharArray(host);
1351 if(!asActive || (asClientPvt && asCheckPut(asClientPvt))) {
1359 if(!asActive || (asClientPvt && asCheckGet(asClientPvt))) {
1367 asRemoveMember(&asMemberPvt);
1371 asRemoveClient(&asClientPvt);
1378 return provider.lock();
1383 if(pvRecord->getTraceLevel()>0) {
1384 cout <<
"ChannelLocal::detach() " 1385 <<
" recordName " << pvRecord->getRecordName()
1386 <<
" requester exists " << (requester ?
"true" :
"false")
1389 if(!requester)
return;
1390 requester->channelStateChange(shared_from_this(),Channel::DESTROYED);
1397 if(pvr && pvr->getTraceLevel()>0) {
1398 cout <<
"ChannelLocal::getRequesterName() " 1399 <<
" recordName " << pvr->getRecordName()
1400 <<
" requester exists " << (requester ?
"true" :
"false")
1404 if(!requester)
return string();
1405 return requester->getRequesterName();
1410 MessageType messageType)
1413 if(pvr && pvr->getTraceLevel()>1) {
1414 cout <<
"ChannelLocal::message() " 1415 <<
" recordName " << pvr->getRecordName()
1416 <<
" requester exists " << (requester ?
"true" :
"false")
1420 requester->message(message,messageType);
1423 string recordName(
"record deleted");
1424 if(pvr) recordName = pvr->getRecordName();
1426 <<
" message " << message
1427 <<
" messageType " << getMessageTypeName(messageType)
1433 return string(
"local");
1438 return Channel::CONNECTED;
1444 string name(
"record deleted");
1445 if(pvr) name = pvr->getRecordName();
1460 string const &subField)
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);
1470 PVFieldPtr pvField =
1471 pvr->getPVRecordStructure()->getPVStructure()->getSubField(subField);
1473 requester->getDone(Status::Ok,pvField->getField());
1476 Status status(Status::STATUSTYPE_ERROR,
1477 "client asked for illegal field");
1478 requester->getDone(status,FieldConstPtr());
1482 PVField::shared_pointer
const &pvField)
1484 throw std::logic_error(
"Not Implemented");
1488 ChannelProcessRequester::shared_pointer
const & channelProcessRequester,
1489 PVStructure::shared_pointer
const & pvRequest)
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")
1499 ChannelProcessLocalPtr channelProcess =
1500 ChannelProcessLocal::create(
1502 channelProcessRequester,
1505 return channelProcess;
1509 ChannelGetRequester::shared_pointer
const &channelGetRequester,
1510 PVStructure::shared_pointer
const &pvRequest)
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")
1520 ChannelGetLocalPtr channelGet =
1521 ChannelGetLocal::create(
1523 channelGetRequester,
1530 ChannelPutRequester::shared_pointer
const &channelPutRequester,
1531 PVStructure::shared_pointer
const &pvRequest)
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")
1542 ChannelPutLocalPtr channelPut =
1543 ChannelPutLocal::create(
1545 channelPutRequester,
1552 ChannelPutGetRequester::shared_pointer
const &channelPutGetRequester,
1553 PVStructure::shared_pointer
const &pvRequest)
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")
1564 ChannelPutGetLocalPtr channelPutGet =
1565 ChannelPutGetLocal::create(
1567 channelPutGetRequester,
1570 return channelPutGet;
1574 ChannelRPCRequester::shared_pointer
const & channelRPCRequester,
1575 PVStructure::shared_pointer
const & pvRequest)
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")
1586 ChannelRPCLocalPtr channelRPC =
1587 ChannelRPCLocal::create(
1589 channelRPCRequester,
1596 MonitorRequester::shared_pointer
const &monitorRequester,
1597 PVStructure::shared_pointer
const &pvRequest)
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")
1616 ChannelArrayRequester::shared_pointer
const &channelArrayRequester,
1617 PVStructure::shared_pointer
const &pvRequest)
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")
1627 ChannelArrayLocalPtr channelArray =
1628 ChannelArrayLocal::create(
1630 channelArrayRequester,
1633 return channelArray;
1643 out <<
"ChannelLocal provides access to a record in the local PVDatabase";
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.
shared_pointer getPtrSelf()
virtual bool canRead()
determines if client can read
std::tr1::shared_ptr< PVCopy > PVCopyPtr
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
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
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.