14 #include <pv/bitSetUtil.h> 15 #include <pv/rpcService.h> 17 #define epicsExportSharedSymbols 25 namespace epics {
namespace pvaClient {
27 class RPCRequesterImpl :
public ChannelRPCRequester
29 PvaClientRPC::weak_pointer pvaClientRPC;
30 PvaClient::weak_pointer pvaClient;
35 : pvaClientRPC(pvaClientRPC),
38 virtual ~RPCRequesterImpl() {
39 if(PvaClient::getDebug()) std::cout <<
"~RPCRequesterImpl" << std::endl;
42 virtual std::string getRequesterName() {
44 if(!clientRPC)
return string(
"pvaClientRPC is null");
45 return clientRPC->getRequesterName();
48 virtual void message(std::string
const & message, MessageType messageType) {
50 if(!clientRPC)
return;
51 clientRPC->message(message,messageType);
54 virtual void channelRPCConnect(
56 ChannelRPC::shared_pointer
const & channelRPC)
59 if(!clientRPC)
return;
60 clientRPC->rpcConnect(status,channelRPC);
63 virtual void requestDone(
65 ChannelRPC::shared_pointer
const & channelRPC,
66 PVStructure::shared_pointer
const & pvResponse)
69 if(!clientRPC)
return;
70 clientRPC->requestDone(status,channelRPC,pvResponse);
76 Channel::shared_pointer
const & channel)
78 StructureConstPtr structure(getFieldCreate()->createStructure());
79 PVStructurePtr pvRequest(getPVDataCreate()->createPVStructure(structure));
80 return create(pvaClient,channel,pvRequest);
84 Channel::shared_pointer
const & channel,
85 PVStructurePtr
const &pvRequest)
89 new RPCRequesterImpl(epv,pvaClient));
93 PvaClientRPC::PvaClientRPC(
95 Channel::shared_pointer
const & channel,
96 PVStructurePtr
const &pvRequest)
98 connectState(connectIdle),
101 pvRequest(pvRequest),
105 if(PvaClient::getDebug()) {
106 cout<<
"PvaClientRPC::PvaClientRPC()" 107 <<
" channelName " << channel->getChannelName()
112 PvaClientRPC::~PvaClientRPC()
114 if(PvaClient::getDebug()) {
115 string channelName(
"disconnected");
116 Channel::shared_pointer chan(channel.lock());
117 if(chan) channelName = chan->getChannelName();
118 cout<<
"PvaClientRPC::~PvaClientRPC" 119 <<
" channelName " << channelName
124 void PvaClientRPC::checkRPCState()
126 if(PvaClient::getDebug()) {
127 string channelName(
"disconnected");
128 Channel::shared_pointer chan(channel.lock());
129 if(chan) channelName = chan->getChannelName();
130 cout <<
"PvaClientRPC::checkRPCState" 131 <<
" channelName " << channelName
132 <<
" connectState " << connectState
135 if(connectState==connectIdle) connect();
138 string PvaClientRPC::getRequesterName()
141 if(!yyy)
return string(
"PvaClientRPC::getRequesterName() PvaClient isDestroyed");
142 return yyy->getRequesterName();
145 void PvaClientRPC::message(
string const & message,MessageType messageType)
149 yyy->message(message, messageType);
152 void PvaClientRPC::rpcConnect(
153 const Status& status,
154 ChannelRPC::shared_pointer
const & channelRPC)
156 Channel::shared_pointer chan(channel.lock());
157 if(PvaClient::getDebug()) {
158 string channelName(
"disconnected");
159 Channel::shared_pointer chan(channel.lock());
160 if(chan) channelName = chan->getChannelName();
161 cout <<
"PvaClientRPC::rpcConnect" 162 <<
" channelName " << channelName
163 <<
" status.isOK " << (status.isOK() ?
"true" :
"false")
167 connectStatus = status;
168 connectState = connected;
169 if(PvaClient::getDebug()) {
170 cout <<
"PvaClientRPC::rpcConnect calling waitForConnect.signal\n";
172 waitForConnect.signal();
176 void PvaClientRPC::requestDone(
177 const Status& status,
178 ChannelRPC::shared_pointer
const & channelRPC,
179 PVStructure::shared_pointer
const & pvResponse)
184 requestStatus = status;
185 if(PvaClient::getDebug()) {
186 string channelName(
"disconnected");
187 Channel::shared_pointer chan(channel.lock());
188 if(chan) channelName = chan->getChannelName();
189 cout <<
"PvaClientRPC::requestDone" 190 <<
" channelName " << channelName
193 if(rpcState!=rpcActive) {
194 string channelName(
"disconnected");
195 Channel::shared_pointer chan(channel.lock());
196 if(chan) channelName = chan->getChannelName();
197 string message =
"channel " 199 +
" PvaClientRPC::requestDone" 201 throw std::runtime_error(message);
203 if(req && (responseTimeout<=0.0)) {
206 rpcState = rpcComplete;
207 if(!req) this->pvResponse = pvResponse;
208 waitForDone.signal();
212 req->requestDone(status,shared_from_this(),pvResponse);
216 void PvaClientRPC::connect()
218 if(PvaClient::getDebug()) cout <<
"PvaClientRPC::connect\n";
220 Status status = waitConnect();
221 if(status.isOK())
return;
222 Channel::shared_pointer chan(channel.lock());
223 string channelName(
"disconnected");
224 if(chan) channelName = chan->getChannelName();
225 string message = string(
"channel ")
227 +
" PvaClientRPC::connect " 228 + status.getMessage();
229 throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
232 void PvaClientRPC::issueConnect()
234 if(PvaClient::getDebug()) cout <<
"PvaClientRPC::issueConnect\n";
235 Channel::shared_pointer chan(channel.lock());
236 if(connectState!=connectIdle) {
237 string channelName(
"disconnected");
238 if(chan) channelName = chan->getChannelName();
239 string message = string(
"channel ")
241 +
" pvaClientRPC already connected ";
242 throw std::runtime_error(message);
245 connectState = connectActive;
246 channelRPC = chan->createChannelRPC(rpcRequester,pvRequest);
249 throw std::runtime_error(
"PvaClientRPC::issueConnect() but channel disconnected");
252 Status PvaClientRPC::waitConnect()
254 if(PvaClient::getDebug()) cout <<
"PvaClientRPC::waitConnect\n";
255 if(connectState==connected) {
256 if(!connectStatus.isOK()) connectState = connectIdle;
257 return connectStatus;
259 if(connectState!=connectActive) {
260 Channel::shared_pointer chan(channel.lock());
261 string channelName(
"disconnected");
262 if(chan) channelName = chan->getChannelName();
263 string message = string(
"channel ")
265 +
" PvaClientRPC::waitConnect illegal connect state ";
266 throw std::runtime_error(message);
268 if(PvaClient::getDebug()) {
269 cout <<
"PvaClientRPC::waitConnect calling waitForConnect.wait\n";
271 waitForConnect.wait();
272 connectState = connectStatus.isOK() ? connected : connectIdle;
273 if(PvaClient::getDebug()) {
274 cout <<
"PvaClientRPC::waitConnect" 275 <<
" connectStatus " << (connectStatus.isOK() ?
"connected" :
"not connected");
277 return connectStatus;
280 PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer
const & pvArgument)
285 if(rpcState!=rpcIdle) {
286 Channel::shared_pointer chan(channel.lock());
287 string channelName(
"disconnected");
288 if(chan) channelName = chan->getChannelName();
289 string message =
"channel " 291 +
" PvaClientRPC::request request aleady active ";
292 throw std::runtime_error(message);
294 rpcState = rpcActive;
296 channelRPC->request(pvArgument);
297 if(responseTimeout>0.0) {
298 waitForDone.wait(responseTimeout);
303 if(rpcState!=rpcComplete) {
304 Channel::shared_pointer chan(channel.lock());
305 string channelName(
"disconnected");
306 if(chan) channelName = chan->getChannelName();
307 string message =
"channel " 309 +
" PvaClientRPC::request request timeout ";
310 throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
313 if(requestStatus.isOK())
return pvResponse;
314 Channel::shared_pointer chan(channel.lock());
315 string channelName(
"disconnected");
316 if(chan) channelName = chan->getChannelName();
317 string message =
"channel " 319 +
" PvaClientRPC::request status ";
320 message += requestStatus.getMessage();
321 throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
325 void PvaClientRPC::request(
326 PVStructure::shared_pointer
const & pvArgument,
330 this->pvaClientRPCRequester = pvaClientRPCRequester;
331 if(responseTimeout<=0.0) {
334 if(rpcState!=rpcIdle) {
335 Channel::shared_pointer chan(channel.lock());
336 string channelName(
"disconnected");
337 if(chan) channelName = chan->getChannelName();
338 string message =
"channel " 340 +
" PvaClientRPC::request request aleady active ";
341 throw std::runtime_error(message);
343 rpcState = rpcActive;
345 channelRPC->request(pvArgument);
std::tr1::shared_ptr< PvaClient > PvaClientPtr
std::tr1::shared_ptr< RPCRequesterImpl > RPCRequesterImplPtr
std::tr1::shared_ptr< PvaClientRPC > PvaClientRPCPtr
std::tr1::shared_ptr< PvaClientRPCRequester > PvaClientRPCRequesterPtr