pva2pva  1.4.1
 All Classes Functions Variables Pages
pvalink_jlif.cpp
1 #include <sstream>
2 
3 #include <epicsStdio.h> // redirects stdout/stderr
4 
5 #include "pvalink.h"
6 
7 namespace pvalink {
8 pvaLinkConfig::pvaLinkConfig()
9  :queueSize(4)
10  ,pp(Default)
11  ,ms(NMS)
12  ,defer(false)
13  ,pipeline(false)
14  ,time(false)
15  ,retry(false)
16  ,local(false)
17  ,always(false)
18  ,monorder(0)
19 {}
20 pvaLinkConfig::~pvaLinkConfig() {}
21 }
22 
23 namespace {
24 
25 using namespace pvalink;
26 
27 /* link options.
28  *
29  * "pvname" # short-hand, sets PV name only
30  *
31  * {
32  * "pv":"name",
33  * "field":"blah.foo",
34  * "Q":5,
35  * "pipeline":false,
36  * "proc":true, // false, true, none, "", "NPP", "PP", "CP", "CPP"
37  * "sevr":true, // false, true, "NMS", "MS", "MSI", "MSS"
38  * "time":true, // false, true
39  * "monorder":#,// order of processing during CP scan
40  * "defer":true,// whether to immediately start Put, or only queue value to be sent
41  * "retry":true,// queue Put while disconnected, and retry on connect
42  * "always":true,// CP/CPP updates always process a like, even if its input field hasn't changed
43  * "local":false,// Require local channel
44  * }
45  */
46 
47 jlink* pva_alloc_jlink(short dbr)
48 {
49  try {
50  TRACE();
51  return new pvaLink;
52 
53  }catch(std::exception& e){
54  errlogPrintf("Error allocating pva link: %s\n", e.what());
55  return NULL;
56  }
57 }
58 
59 #define TRY pvaLinkConfig *pvt = static_cast<pvaLinkConfig*>(pjlink); (void)pvt; try
60 #define CATCH(RET) catch(std::exception& e){ \
61  errlogPrintf("Error in %s link: %s\n", __FUNCTION__, e.what()); \
62  return RET; }
63 
64 void pva_free_jlink(jlink *pjlink)
65 {
66  TRY {
67  TRACE();
68  delete pvt;
69  }catch(std::exception& e){
70  errlogPrintf("Error freeing pva link: %s\n", e.what());
71  }
72 }
73 
74 jlif_result pva_parse_null(jlink *pjlink)
75 {
76  TRY {
77  TRACE(<<pvt->jkey<<" ");
78  if(pvt->parseDepth!=1) {
79  // ignore
80  } else if(pvt->jkey == "proc") {
81  pvt->pp = pvaLinkConfig::Default;
82  } else if(pvt->jkey == "sevr") {
83  pvt->ms = pvaLinkConfig::NMS;
84  } else if(pvt->jkey == "local") {
85  pvt->local = false; // alias for local:false
86  } else if(pvt->debug) {
87  printf("pva link parsing unknown none depth=%u key=\"%s\"\n",
88  pvt->parseDepth, pvt->jkey.c_str());
89  }
90 
91  pvt->jkey.clear();
92  return jlif_continue;
93  }CATCH(jlif_stop)
94 }
95 
96 jlif_result pva_parse_bool(jlink *pjlink, int val)
97 {
98  TRY {
99  TRACE(<<pvt->jkey<<" "<<(val?"true":"false"));
100  if(pvt->parseDepth!=1) {
101  // ignore
102  } else if(pvt->jkey == "proc") {
103  pvt->pp = val ? pvaLinkConfig::PP : pvaLinkConfig::NPP;
104  } else if(pvt->jkey == "sevr") {
105  pvt->ms = val ? pvaLinkConfig::MS : pvaLinkConfig::NMS;
106  } else if(pvt->jkey == "defer") {
107  pvt->defer = !!val;
108  } else if(pvt->jkey == "pipeline") {
109  pvt->pipeline = !!val;
110  } else if(pvt->jkey == "time") {
111  pvt->time = !!val;
112  } else if(pvt->jkey == "retry") {
113  pvt->retry = !!val;
114  } else if(pvt->jkey == "local") {
115  pvt->local = !!val;
116  } else if(pvt->jkey == "always") {
117  pvt->always = !!val;
118  } else if(pvt->debug) {
119  printf("pva link parsing unknown integer depth=%u key=\"%s\" value=%s\n",
120  pvt->parseDepth, pvt->jkey.c_str(), val ? "true" : "false");
121  }
122 
123  pvt->jkey.clear();
124  return jlif_continue;
125  }CATCH(jlif_stop)
126 }
127 
128 jlif_result pva_parse_integer(jlink *pjlink, long long val)
129 {
130  TRY {
131  TRACE(<<pvt->jkey<<" "<<val);
132  if(pvt->parseDepth!=1) {
133  // ignore
134  } else if(pvt->jkey == "Q") {
135  pvt->queueSize = val < 1 ? 1 : size_t(val);
136  } else if(pvt->jkey == "monorder") {
137  pvt->monorder = std::max(-1024, std::min(int(val), 1024));
138  } else if(pvt->debug) {
139  printf("pva link parsing unknown integer depth=%u key=\"%s\" value=%lld\n",
140  pvt->parseDepth, pvt->jkey.c_str(), val);
141  }
142 
143  pvt->jkey.clear();
144  return jlif_continue;
145  }CATCH(jlif_stop)
146 }
147 
148 jlif_result pva_parse_string(jlink *pjlink, const char *val, size_t len)
149 {
150  TRY{
151  std::string sval(val, len);
152  TRACE(<<pvt->jkey<<" "<<sval);
153  if(pvt->parseDepth==0 || (pvt->parseDepth==1 && pvt->jkey=="pv")) {
154  pvt->channelName = sval;
155 
156  } else if(pvt->parseDepth > 1) {
157  // ignore
158 
159  } else if(pvt->jkey=="field") {
160  pvt->fieldName = sval;
161 
162  } else if(pvt->jkey=="proc") {
163  if(sval.empty()) {
164  pvt->pp = pvaLinkConfig::Default;
165  } else if(sval=="CP") {
166  pvt->pp = pvaLinkConfig::CP;
167  } else if(sval=="CPP") {
168  pvt->pp = pvaLinkConfig::CPP;
169  } else if(sval=="PP") {
170  pvt->pp = pvaLinkConfig::PP;
171  } else if(sval=="NPP") {
172  pvt->pp = pvaLinkConfig::NPP;
173  } else if(pvt->debug) {
174  printf("pva link parsing unknown proc depth=%u key=\"%s\" value=\"%s\"\n",
175  pvt->parseDepth, pvt->jkey.c_str(), sval.c_str());
176  }
177 
178  } else if(pvt->jkey=="sevr") {
179  if(sval=="NMS") {
180  pvt->ms = pvaLinkConfig::NMS;
181  } else if(sval=="MS") {
182  pvt->ms = pvaLinkConfig::MS;
183  } else if(sval=="MSI") {
184  pvt->ms = pvaLinkConfig::MSI;
185  } else if(sval=="MSS") {
186  // not sure how to handle mapping severity for MSS.
187  // leave room for this to happen compatibly later by
188  // handling as alias for MS until then.
189  pvt->ms = pvaLinkConfig::MS;
190  } else if(pvt->debug) {
191  printf("pva link parsing unknown sevr depth=%u key=\"%s\" value=\"%s\"\n",
192  pvt->parseDepth, pvt->jkey.c_str(), sval.c_str());
193  }
194 
195  } else if(pvt->debug) {
196  printf("pva link parsing unknown string depth=%u key=\"%s\" value=\"%s\"\n",
197  pvt->parseDepth, pvt->jkey.c_str(), sval.c_str());
198  }
199 
200  pvt->jkey.clear();
201  return jlif_continue;
202  }CATCH(jlif_stop)
203 }
204 
205 jlif_key_result pva_parse_start_map(jlink *pjlink)
206 {
207  TRY {
208  TRACE();
209  return jlif_key_continue;
210  }CATCH(jlif_key_stop)
211 }
212 
213 jlif_result pva_parse_key_map(jlink *pjlink, const char *key, size_t len)
214 {
215  TRY {
216  std::string sval(key, len);
217  TRACE(<<sval);
218  pvt->jkey = sval;
219 
220  return jlif_continue;
221  }CATCH(jlif_stop)
222 }
223 
224 jlif_result pva_parse_end_map(jlink *pjlink)
225 {
226  TRY {
227  TRACE();
228  return jlif_continue;
229  }CATCH(jlif_stop)
230 }
231 
232 struct lset* pva_get_lset(const jlink *pjlink)
233 {
234  TRACE();
235  return &pva_lset;
236 }
237 
238 void pva_report(const jlink *rpjlink, int lvl, int indent)
239 {
240  const pvaLink *pval = static_cast<const pvaLink*>(rpjlink);
241  try {
242  (void)pval;
243  printf("%*s'pva': %s", indent, "", pval->channelName.c_str());
244  if(!pval->fieldName.empty())
245  printf("|.%s", pval->fieldName.c_str());
246 
247  switch(pval->pp) {
248  case pvaLinkConfig::NPP: printf(" NPP"); break;
249  case pvaLinkConfig::Default: printf(" Def"); break;
250  case pvaLinkConfig::PP: printf(" PP"); break;
251  case pvaLinkConfig::CP: printf(" CP"); break;
252  case pvaLinkConfig::CPP: printf(" CPP"); break;
253  }
254  switch(pval->ms) {
255  case pvaLinkConfig::NMS: printf(" NMS"); break;
256  case pvaLinkConfig::MS: printf(" MS"); break;
257  case pvaLinkConfig::MSI: printf(" MSI"); break;
258  }
259  if(lvl>0) {
260  printf(" Q=%u pipe=%c defer=%c time=%c retry=%c morder=%d",
261  unsigned(pval->queueSize),
262  pval->pipeline ? 'T' : 'F',
263  pval->defer ? 'T' : 'F',
264  pval->time ? 'T' : 'F',
265  pval->retry ? 'T' : 'F',
266  pval->monorder);
267  }
268 
269  if(pval->lchan) {
270  // after open()
271  Guard G(pval->lchan->lock);
272 
273  printf(" conn=%c", pval->lchan->connected ? 'T' : 'F');
274  if(pval->lchan->op_put.valid()) {
275  printf(" Put");
276  }
277 
278  if(lvl>0) {
279  printf(" #disconn=%zu prov=%s", pval->lchan->num_disconnect, pval->lchan->providerName.c_str());
280  }
281  if(lvl>1) {
282  printf(" inprog=%c",
283  pval->lchan->queued?'T':'F');
284  }
285  if(lvl>5) {
286  std::ostringstream strm;
287  pval->lchan->chan.show(strm);
288  printf("\n%*s CH: %s", indent, "", strm.str().c_str());
289  }
290  } else {
291  printf(" No Channel");
292  }
293  printf("\n");
294  }CATCH()
295 }
296 
297 } //namespace
298 
299 namespace pvalink {
300 
301 jlif lsetPVA = {
302  "pva",
303  &pva_alloc_jlink,
304  &pva_free_jlink,
305  &pva_parse_null,
306  &pva_parse_bool,
307  &pva_parse_integer,
308  NULL,
309  &pva_parse_string,
310  &pva_parse_start_map,
311  &pva_parse_key_map,
312  &pva_parse_end_map,
313  NULL,
314  NULL,
315  NULL,
316  &pva_get_lset,
317  &pva_report,
318  NULL
319 };
320 
321 } //namespace pvalink