pvDatabaseCPP  4.7.0
pvCopy.cpp
Go to the documentation of this file.
1 /* pvCopy.cpp */
2 /*
3  * License terms for this software can be found in the file LICENSE that is included with the distribution
4  */
9 #include <string>
10 #include <stdexcept>
11 #include <memory>
12 #include <sstream>
13 
14 #include <epicsThread.h>
15 #include <pv/pvData.h>
16 #include <pv/bitSet.h>
17 #include <pv/thread.h>
18 
19 #define epicsExportSharedSymbols
20 #include "pv/pvPlugin.h"
21 #include "pv/pvStructureCopy.h"
22 
23 using std::tr1::static_pointer_cast;
24 using std::tr1::dynamic_pointer_cast;
25 using std::string;
26 using std::size_t;
27 using std::cout;
28 using std::endl;
29 using std::vector;
30 using namespace epics::pvData;
31 
32 namespace epics { namespace pvCopy {
33 
40 static void newLine(string *buffer, int indentLevel)
41 {
42  *buffer += "\n";
43  *buffer += string(indentLevel*4, ' ');
44 }
45 
46 static PVCopyPtr NULLPVCopy;
47 static StructureConstPtr NULLStructure;
48 static PVStructurePtr NULLPVStructure;
49 
50 struct CopyNode {
51  CopyNode()
52  : isStructure(false),
53  structureOffset(0),
54  nfields(0)
55  {}
56  PVFieldPtr masterPVField;
57  bool isStructure;
58  size_t structureOffset; // In the copy
59  size_t nfields;
60  PVStructurePtr options;
61  vector<PVFilterPtr> pvFilters;
62 };
63 
64 static CopyNodePtr NULLCopyNode;
65 
66 typedef std::vector<CopyNodePtr> CopyNodePtrArray;
67 typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
68 
69 struct CopyStructureNode : public CopyNode {
70  CopyNodePtrArrayPtr nodes;
71 };
72 
73 PVCopyPtr PVCopy::create(
74  PVStructurePtr const &pvMaster,
75  PVStructurePtr const &pvRequest,
76  string const & structureName)
77 {
78  PVStructurePtr pvStructure(pvRequest);
79  if(structureName.size()>0) {
80  if(pvStructure->getStructure()->getNumberFields()>0) {
81  pvStructure = pvRequest->getSubField<PVStructure>(structureName);
82  if(!pvStructure) return NULLPVCopy;
83  }
84  } else if(pvRequest->getSubField<PVStructure>("field")) {
85  pvStructure = pvRequest->getSubField<PVStructure>("field");
86  }
87  PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvMaster));
88  bool result = pvCopy->init(pvStructure);
89  if(!result) return PVCopyPtr();
90  pvCopy->traverseMasterInitPlugin();
91  return pvCopy;
92 }
93 
94 PVStructurePtr PVCopy::getPVMaster()
95 {
96  return pvMaster;
97 }
98 
99 void PVCopy::traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback)
100 {
101  traverseMaster(headNode,callback);
102 }
103 
104 StructureConstPtr PVCopy::getStructure()
105 {
106  return structure;
107 }
108 
109 PVStructurePtr PVCopy::createPVStructure()
110 {
111  if(cacheInitStructure) {
112  PVStructurePtr save = cacheInitStructure;
113  cacheInitStructure.reset();
114  return save;
115  }
116  PVStructurePtr pvStructure =
117  getPVDataCreate()->createPVStructure(structure);
118  return pvStructure;
119 }
120 
121 
122 size_t PVCopy::getCopyOffset(PVFieldPtr const &masterPVField)
123 {
124  if(!headNode->isStructure) {
125  CopyNodePtr node = static_pointer_cast<CopyNode>(headNode);
126  if((node->masterPVField.get())==masterPVField.get()) {
127  return headNode->structureOffset;
128  }
129  PVStructure * parent = masterPVField->getParent();
130  size_t offsetParent = parent->getFieldOffset();
131  size_t off = masterPVField->getFieldOffset();
132  size_t offdiff = off -offsetParent;
133  if(offdiff<node->nfields) return headNode->structureOffset + offdiff;
134  return string::npos;
135  }
136  CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(headNode);
137  CopyNodePtr node = getCopyOffset(structNode,masterPVField);
138  if(node) return node->structureOffset;
139  return string::npos;
140 }
141 
142 size_t PVCopy::getCopyOffset(
143  PVStructurePtr const &masterPVStructure,
144  PVFieldPtr const &masterPVField)
145 {
146  CopyNodePtr node;
147  if(!headNode->isStructure) {
148  node = static_pointer_cast<CopyNode>(headNode);
149  if(node->masterPVField.get()!=masterPVStructure.get()) return string::npos;
150  } else {
151  CopyStructureNodePtr snode = static_pointer_cast<CopyStructureNode>(headNode);
152  node = getCopyOffset(snode,masterPVField);
153  }
154  if(!node) return string::npos;
155  size_t diff = masterPVField->getFieldOffset()
156  - masterPVStructure->getFieldOffset();
157  return node->structureOffset + diff;
158 }
159 
160 PVFieldPtr PVCopy::getMasterPVField(size_t structureOffset)
161 {
162  CopyNodePtr node;
163  if(!headNode->isStructure) {
164  node = headNode;
165  } else {
166  CopyStructureNodePtr snode = static_pointer_cast<CopyStructureNode>(headNode);
167  node = getMasterNode(snode,structureOffset);
168  }
169  if(!node) {
170  throw std::logic_error(
171  "PVCopy::getMasterPVField: structureOffset not valid");
172  }
173  size_t diff = structureOffset - node->structureOffset;
174  PVFieldPtr pvMasterField = node->masterPVField;
175  if(diff==0) return pvMasterField;
176  PVStructurePtr pvStructure
177  = static_pointer_cast<PVStructure>(pvMasterField);
178  return pvStructure->getSubField(
179  pvMasterField->getFieldOffset() + diff);
180 }
181 
182 void PVCopy::initCopy(
183  PVStructurePtr const &copyPVStructure,
184  BitSetPtr const &bitSet)
185 {
186  for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) {
187  bitSet->set(i,true);
188  }
189  updateCopyFromBitSet(copyPVStructure,headNode,bitSet);
190 }
191 
192 
193 bool PVCopy::updateCopySetBitSet(
194  PVStructurePtr const &copyPVStructure,
195  BitSetPtr const &bitSet)
196 {
197  updateCopySetBitSet(copyPVStructure,headNode,bitSet);
198  return checkIgnore(copyPVStructure,bitSet);
199 }
200 
201 bool PVCopy::updateCopyFromBitSet(
202  PVStructurePtr const &copyPVStructure,
203  BitSetPtr const &bitSet)
204 {
205  if(bitSet->get(0)) {
206  for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) {
207  bitSet->set(i,true);
208  }
209  }
210  updateCopyFromBitSet(copyPVStructure,headNode,bitSet);
211  return checkIgnore(copyPVStructure,bitSet);
212 }
213 
214 void PVCopy::updateMasterField(
215  CopyNodePtr const & node,
216  PVFieldPtr const & pvCopy,
217  PVFieldPtr const &pvMaster,
218  BitSetPtr const &bitSet)
219 {
220  bool result = false;
221  for(size_t i=0; i< node->pvFilters.size(); ++i) {
222  PVFilterPtr pvFilter = node->pvFilters[i];
223  if(pvFilter->filter(pvCopy,bitSet,false)) result = true;
224  }
225  if(result) return;
226  pvMaster->copyUnchecked(*pvCopy);
227 }
228 
229 void PVCopy::updateMasterCheckBitSet(
230  PVStructurePtr const &copyPVStructure,
231  BitSetPtr const &bitSet,
232  size_t nextSet)
233 {
234  if(!bitSet->get(nextSet)) {
235  size_t next = bitSet->nextSetBit(nextSet);
236  if(next==string::npos) return;
237  updateMasterCheckBitSet(copyPVStructure,bitSet,next);
238  return;
239  }
240  PVFieldPtr pvField = copyPVStructure;
241  if(nextSet!=0) pvField = copyPVStructure->getSubField(nextSet);
242  if(pvField->getField()->getType()==epics::pvData::structure) {
243  bitSet->clear(nextSet);
244  PVStructurePtr pv = static_pointer_cast<PVStructure>(pvField);
245  PVFieldPtrArray pvFieldArray = pv->getPVFields();
246  for(size_t i=0; i<pvFieldArray.size(); ++i) {
247  PVFieldPtr pvField = pvFieldArray[i];
248  bitSet->set(pvField->getFieldOffset());
249  }
250  }
251  size_t next = bitSet->nextSetBit(nextSet+1);
252  if(next==string::npos) return;
253  updateMasterCheckBitSet(copyPVStructure,bitSet,next);
254 }
255 
256 CopyNodePtr PVCopy::getCopyNode(std::size_t fieldOffset)
257 {
258  if(fieldOffset==0) return headNode;
259  CopyNodePtr node = headNode;
260  while(true) {
261  if(!node->isStructure) return node;
262  CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
263  CopyNodePtrArrayPtr nodes = structNode->nodes;
264  bool okToContinue = false;
265  for(size_t i=0; i< nodes->size(); i++) {
266  node = (*nodes)[i];
267  size_t soff = node->structureOffset;
268  if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
269  okToContinue = true;
270  break;
271  }
272  }
273  if(okToContinue) continue;
274  }
275  throw std::logic_error("PVCopy::getCopyNode fieldOffset not valid");
276 }
277 
278 
279 void PVCopy::updateMaster(
280  PVStructurePtr const &copyPVStructure,
281  BitSetPtr const &bitSet)
282 {
283  updateMasterCheckBitSet(copyPVStructure,bitSet,0);
284  size_t nextSet =0;
285  while(true) {
286  nextSet = bitSet->nextSetBit(nextSet);
287  if(nextSet==string::npos) return;
288  PVFieldPtr pvCopy = copyPVStructure->getSubField(nextSet);
289  PVFieldPtr pvMaster = headNode->masterPVField;
290  if(pvMaster->getField()->getType()==epics::pvData::structure) {
291  PVStructurePtr pv = static_pointer_cast<PVStructure>(pvMaster);
292  pvMaster = pv->getSubField(pvCopy->getFullName());
293  }
294  updateMasterField(getCopyNode(nextSet),pvCopy,pvMaster,bitSet);
295  bitSet->clear(nextSet);
296  }
297 }
298 
299 PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
300 {
301  if(fieldOffset==0) return headNode->options;
302  CopyNodePtr node = headNode;
303  while(true) {
304  if(node->structureOffset==fieldOffset) return node->options;
305  if(!node->isStructure) return NULLPVStructure;
306  CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
307  CopyNodePtrArrayPtr nodes = structNode->nodes;
308  bool okToContinue = false;
309  for(size_t i=0; i< nodes->size(); i++) {
310  node = (*nodes)[i];
311  size_t soff = node->structureOffset;
312  if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
313  if(fieldOffset==soff) return node->options;
314  if(!node->isStructure) {
315  return NULLPVStructure;
316  }
317  okToContinue = true;
318  break;
319  }
320  }
321  if(okToContinue) continue;
322  throw std::logic_error("PVCopy::getOptions logic error: fieldOffset not valid");
323  }
324 }
325 
326 string PVCopy::dump()
327 {
328  string builder;
329  dump(&builder,headNode,0);
330  return builder;
331 }
332 
333 void PVCopy::traverseMaster(
334  CopyNodePtr const &innode,
335  PVCopyTraverseMasterCallbackPtr const & callback)
336 {
337  CopyNodePtr node = innode;
338  if(!node->isStructure) {
339  callback->nextMasterPVField(node->masterPVField);
340  return;
341  }
342  CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
343  CopyNodePtrArrayPtr nodes = structNode->nodes;
344  for(size_t i=0; i< nodes->size(); i++) {
345  node = (*nodes)[i];
346  traverseMaster(node,callback);
347  }
348 }
349 
350 void PVCopy::updateCopySetBitSet(
351  PVFieldPtr const & pvCopy,
352  PVFieldPtr const & pvMaster,
353  BitSetPtr const & bitSet)
354 {
355  if(pvCopy->getField()->getType()!=epics::pvData::structure) {
356  if(*pvCopy==*pvMaster) return;
357  pvCopy->copy(*pvMaster);
358  bitSet->set(pvCopy->getFieldOffset());
359  return;
360  }
361  PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
362  PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
363  for(size_t i=0; i<pvCopyFields.size(); ++i) {
364  PVFieldPtr master = getMasterPVField(pvCopyFields[i]->getFieldOffset());
365  updateCopySetBitSet(pvCopyFields[i],master,bitSet);
366  }
367 }
368 
369 void PVCopy::updateCopySetBitSet(
370  PVFieldPtr const & pvCopy,
371  CopyNodePtr const & node,
372  BitSetPtr const & bitSet)
373 {
374  bool result = false;
375  for(size_t i=0; i< node->pvFilters.size(); ++i) {
376  PVFilterPtr pvFilter = node->pvFilters[i];
377  if(pvFilter->filter(pvCopy,bitSet,true)) result = true;
378  }
379  if(!node->isStructure) {
380  if(result) return;
381  updateCopySetBitSet(pvCopy,node->masterPVField,bitSet);
382  return;
383  }
384  CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
385  PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
386  PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
387  for(size_t i=0; i<pvCopyFields.size(); ++i) {
388  updateCopySetBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
389  }
390 }
391 
392 
393 void PVCopy::updateCopyFromBitSet(
394  PVFieldPtr const & pvCopy,
395  CopyNodePtr const & node,
396  BitSetPtr const & bitSet)
397 {
398  bool result = false;
399  bool update = bitSet->get(pvCopy->getFieldOffset());
400  if(update) {
401  for(size_t i=0; i< node->pvFilters.size(); ++i) {
402  PVFilterPtr pvFilter = node->pvFilters[i];
403  if(pvFilter->filter(pvCopy,bitSet,true)) result = true;
404  }
405  }
406  if(!node->isStructure) {
407  if(result) return;
408  PVFieldPtr pvMaster = node->masterPVField;
409  pvCopy->copy(*pvMaster);
410  return;
411  }
412  CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
413  size_t offset = structureNode->structureOffset;
414  size_t nextSet = bitSet->nextSetBit(offset);
415  if(nextSet==string::npos) return;
416  if(offset>=pvCopy->getNextFieldOffset()) return;
417  PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
418  PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
419  for(size_t i=0; i<pvCopyFields.size(); ++i) {
420  updateCopyFromBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
421  }
422 }
423 
424 PVCopy::PVCopy(
425  PVStructurePtr const &pvMaster)
426 : pvMaster(pvMaster)
427 {
428 }
429 
430 bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
431 {
432  PVStructurePtr pvMasterStructure = pvMaster;
433  size_t len = pvRequest->getPVFields().size();
434  bool entireMaster = false;
435  PVStructurePtr pvOptions;
436  if(len==0) {
437  entireMaster = true;
438  }
439  else {
440  // If "_" is in the request, but not in the master structure,
441  // then assume the top level PV structure is requested
442  PVStructurePtr masterFieldPtr = pvMaster->getSubField<PVStructure>("_");
443  PVStructurePtr requestFieldPtr = pvRequest->getSubField<PVStructure>("_");
444  if (!masterFieldPtr && requestFieldPtr) {
445  entireMaster = true;
446  pvOptions = requestFieldPtr->getSubField<PVStructure>("_options");
447  }
448  }
449  if(entireMaster) {
450  structure = pvMasterStructure->getStructure();
451  CopyNodePtr node(new CopyNode());
452  headNode = node;
453  node->options = pvOptions;
454  node->isStructure = false;
455  node->structureOffset = 0;
456  node->masterPVField = pvMasterStructure;
457  node->nfields = pvMasterStructure->getNumberFields();
458  return true;
459  }
460  structure = createStructure(pvMasterStructure,pvRequest);
461  if(!structure) return false;
462  cacheInitStructure = createPVStructure();
463  ignorechangeBitSet = BitSetPtr(new BitSet(cacheInitStructure->getNumberFields()));
464  headNode = createStructureNodes(
465  pvMaster,
466  pvRequest,
467  cacheInitStructure);
468  return true;
469 }
470 
471 
472 StructureConstPtr PVCopy::createStructure(
473  PVStructurePtr const &pvMaster,
474  PVStructurePtr const &pvFromRequest)
475 {
476  if(pvFromRequest->getStructure()->getNumberFields()==0) {
477  return pvMaster->getStructure();
478  }
479  PVFieldPtrArray const &pvFromRequestFields = pvFromRequest->getPVFields();
480  StringArray const &fromRequestFieldNames = pvFromRequest->getStructure()->getFieldNames();
481  size_t length = pvFromRequestFields.size();
482  if(length==0) return NULLStructure;
483  FieldConstPtrArray fields; fields.reserve(length);
484  StringArray fieldNames; fieldNames.reserve(length);
485  for(size_t i=0; i<length; ++i) {
486  string const &fieldName = fromRequestFieldNames[i];
487  PVFieldPtr pvMasterField = pvMaster->getSubField(fieldName);
488  if(!pvMasterField) continue;
489  FieldConstPtr field = pvMasterField->getField();
490  if(field->getType()==epics::pvData::structure) {
491  PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
492  pvFromRequestFields[i]);
493  if(pvRequestStructure->getNumberFields()>0) {
494  StringArray const &names = pvRequestStructure->getStructure()->
495  getFieldNames();
496  size_t num = names.size();
497  if(num>0 && names[0].compare("_options")==0) --num;
498  if(num>0) {
499  if(pvMasterField->getField()->getType()!=epics::pvData::structure) continue;
500  fieldNames.push_back(fieldName);
501  fields.push_back(createStructure(
502  static_pointer_cast<PVStructure>(pvMasterField),
503  pvRequestStructure));
504  continue;
505  }
506  }
507  }
508  fieldNames.push_back(fieldName);
509  fields.push_back(field);
510  }
511  size_t numsubfields = fields.size();
512  if(numsubfields==0) {
513  std::stringstream ss;
514  ss << pvFromRequest << "\n";
515  string val("no fields from the following request were found\n");
516  val += ss.str();
517  throw std::invalid_argument(val);
518  }
519  return getFieldCreate()->createStructure(fieldNames, fields);
520 }
521 
522 CopyNodePtr PVCopy::createStructureNodes(
523  PVStructurePtr const &pvMasterStructure,
524  PVStructurePtr const &pvFromRequest,
525  PVStructurePtr const &pvFromCopy)
526 {
527  PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
528  PVStructurePtr pvOptions = pvFromRequest->getSubField<PVStructure>("_options");
529  size_t number = copyPVFields.size();
530  CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
531  nodes->reserve(number);
532  for(size_t i=0; i<number; i++) {
533  PVFieldPtr copyPVField = copyPVFields[i];
534  string fieldName = copyPVField->getFieldName();
535  PVStructurePtr requestPVStructure =
536  pvFromRequest->getSubField<PVStructure>(fieldName);
537  PVStructurePtr pvSubFieldOptions =
538  requestPVStructure->getSubField<PVStructure>("_options");
539  PVFieldPtr pvMasterField = pvMasterStructure->getSubField(fieldName);
540  if(!pvMasterField) {
541  throw std::logic_error("PVCopy::createStructureNodes did not find field in master");
542  }
543  size_t numberRequest = requestPVStructure->getPVFields().size();
544  bool haveOptions = false;
545  if(pvSubFieldOptions) {
546  numberRequest--;
547  haveOptions = true;
548  }
549  if(numberRequest>0) {
550  Type copyType = copyPVField->getField()->getType();
551  if(copyType==epics::pvData::structure) {
552  nodes->push_back(createStructureNodes(
553  static_pointer_cast<PVStructure>(pvMasterField),
554  requestPVStructure,
555  static_pointer_cast<PVStructure>(copyPVField)));
556  continue;
557  }
558  if(copyType==epics::pvData::union_) {
559  if(numberRequest!=1) {
560  std::stringstream ss;
561  ss << pvFromRequest << "\n";
562  string val("In the following request a union field has more than one subfield in\n");
563  val += ss.str();
564  throw std::invalid_argument(val);
565  }
566  PVUnionPtr pvUnion = static_pointer_cast<PVUnion>(pvMasterField);
567  std::string selectedName = pvUnion->getSelectedFieldName();
568  PVFieldPtrArray const & pvFields = requestPVStructure->getPVFields();
569  size_t len = pvFields.size();
570  if(len>2 || (haveOptions && len!=2)) {
571  std::stringstream ss;
572  ss << pvFromRequest << "\n";
573  string val("PVCopy logic error: pvRequest is\n");
574  val += ss.str();
575  throw std::logic_error(val);
576  }
577  size_t indRequestValue = 0;
578  if((pvFields[0]->getFieldName().compare("_options"))==0) indRequestValue = 1;
579  PVFieldPtr pvRequestValue = pvFields[indRequestValue];
580  if(pvRequestValue) {
581  string requestName = pvRequestValue->getFieldName();
582  if(requestName.compare(selectedName)!=0) {
583  std::stringstream ss;
584  ss << pvFromCopy << "\n";
585  string requestName = pvRequestValue->getFieldName();
586  string val("field ");
587  val += requestName + " does not match union type in\n";
588  val += ss.str();
589  throw std::invalid_argument(val);
590  }
591  }
592  } else {
593  std::stringstream ss;
594  ss << pvFromCopy << "\n";
595  string val("requested a subfield of field ");
596  val += fieldName + " which does not have type structure in\n";
597  val += ss.str();
598  throw std::invalid_argument(val);
599  }
600  }
601  CopyNodePtr node(new CopyNode());
602  node->options = pvSubFieldOptions;
603  node->isStructure = false;
604  node->masterPVField = pvMasterField;
605  node->nfields = copyPVField->getNumberFields();
606  node->structureOffset = copyPVField->getFieldOffset();
607  nodes->push_back(node);
608  }
609  CopyStructureNodePtr structureNode(new CopyStructureNode());
610  structureNode->masterPVField = pvMasterStructure;
611  structureNode->isStructure = true;
612  structureNode->nodes = nodes;
613  structureNode->structureOffset = pvFromCopy->getFieldOffset();
614  structureNode->nfields = pvFromCopy->getNumberFields();
615  structureNode->options = pvOptions;
616  return structureNode;
617 }
618 
619 void PVCopy::initPlugin(
620  CopyNodePtr const & node,
621  PVStructurePtr const & pvOptions,
622  PVFieldPtr const & pvMasterField)
623 {
624  PVFieldPtrArray const & pvFields = pvOptions->getPVFields();
625  size_t num = pvFields.size();
626  vector<PVFilterPtr> pvFilters(num);
627  size_t numfilter = 0;
628  for(size_t i=0; i<num; ++i) {
629  PVStringPtr pvOption = static_pointer_cast<PVString>(pvFields[i]);
630  string name = pvOption->getFieldName();
631  string value = pvOption->get();
632  PVPluginPtr pvPlugin = PVPluginRegistry::find(name);
633  if(!pvPlugin) {
634  if(name.compare("ignore")==0) setIgnore(node);
635  continue;
636  }
637  pvFilters[numfilter] = pvPlugin->create(value,shared_from_this(),pvMasterField);
638  if(pvFilters[numfilter]) ++numfilter;
639  }
640  if(numfilter==0) return;
641  node->pvFilters.resize(numfilter);
642  for(size_t i=0; i<numfilter; ++i) node->pvFilters[i] = pvFilters[i];
643 }
644 
645 void PVCopy::traverseMasterInitPlugin()
646 {
647  traverseMasterInitPlugin(headNode);
648 }
649 
650 void PVCopy::traverseMasterInitPlugin(CopyNodePtr const & node)
651 {
652  PVFieldPtr pvField = node->masterPVField;
653  PVStructurePtr pvOptions = node->options;
654  if(pvOptions) initPlugin(node,pvOptions,pvField);
655  if(!node->isStructure) return;
656  CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
657  CopyNodePtrArrayPtr nodes = structureNode->nodes;
658  for(size_t i=0; i< nodes->size(); i++) {
659  traverseMasterInitPlugin((*nodes)[i]);
660  }
661 }
662 
663 CopyNodePtr PVCopy::getCopyOffset(
664  CopyStructureNodePtr const &structureNode,
665  PVFieldPtr const &masterPVField)
666 {
667  size_t offset = masterPVField->getFieldOffset();
668  CopyNodePtrArrayPtr nodes = structureNode->nodes;
669  for(size_t i=0; i< nodes->size(); i++) {
670  CopyNodePtr node = (*nodes)[i];
671  if(!node->isStructure) {
672  size_t off = node->masterPVField->getFieldOffset();
673  size_t nextOffset = node->masterPVField->getNextFieldOffset();
674  if(offset>= off && offset<nextOffset) return node;
675  } else {
676  CopyStructureNodePtr subNode =
677  static_pointer_cast<CopyStructureNode>(node);
678  CopyNodePtr node =
679  getCopyOffset(subNode,masterPVField);
680  if(node) return node;
681  }
682  }
683  return NULLCopyNode;
684 }
685 
686 
687 
688 bool PVCopy::checkIgnore(
689  PVStructurePtr const & copyPVStructure,
690  BitSetPtr const & bitSet)
691 {
692  if(!ignorechangeBitSet) {
693  return (bitSet->nextSetBit(0)<0) ? false : true;
694  }
695  int32 numFields = copyPVStructure->getNumberFields();
696  BitSet temp(numFields);
697  temp = *bitSet;
698  int32 ind = 0;
699  while(true) {
700  ind = ignorechangeBitSet->nextSetBit(ind);
701  if(ind<0) break;
702  temp.clear(ind);
703  ind++;
704  if(ind>=numFields) break;
705  }
706  return (temp.nextSetBit(0)<0) ? false : true;
707 }
708 
709 void PVCopy::setIgnore(CopyNodePtr const &node) {
710  ignorechangeBitSet->set(node->structureOffset);
711  if(node->isStructure) {
712  CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
713  CopyNodePtrArrayPtr nodes = structureNode->nodes;
714  for(size_t i=0; i<nodes->size(); ++i) {
715  CopyNodePtr node = (*nodes)[i];
716  setIgnore(node); }
717  } else {
718  size_t num = node->masterPVField->getNumberFields();
719  if(num>1) {
720  for(size_t i=1; i<num; ++i) {
721  ignorechangeBitSet->set(node->structureOffset+i);
722  }
723  }
724  }
725 }
726 
727 
728 CopyNodePtr PVCopy::getMasterNode(
729  CopyStructureNodePtr const &structureNode,
730  std::size_t structureOffset)
731 {
732  CopyNodePtrArrayPtr nodes = structureNode->nodes;
733  for(size_t i=0; i<nodes->size(); ++i) {
734  CopyNodePtr node = (*nodes)[i];
735  if(structureOffset>=(node->structureOffset + node->nfields)) continue;
736  if(!node->isStructure) return node;
737  CopyStructureNodePtr subNode =
738  static_pointer_cast<CopyStructureNode>(node);
739  return getMasterNode(subNode,structureOffset);
740  }
741  return NULLCopyNode;
742 }
743 
744 void PVCopy::dump(string *builder,CopyNodePtr const &node,int indentLevel)
745 {
746  newLine(builder,indentLevel);
747  std::stringstream ss;
748  ss << (node->isStructure ? "structureNode" : "node");
749  ss << " structureOffset " << node->structureOffset;
750  ss << " nfields " << node->nfields;
751  *builder += ss.str();
752  PVStructurePtr options = node->options;
753  if(options) {
754  newLine(builder,indentLevel +1);
755  *builder += options->getFieldName();
756  PVFieldPtrArray pvFields = options->getPVFields();
757  for(size_t i=0; i< pvFields.size() ; ++i) {
758  PVStringPtr pvString = static_pointer_cast<PVString>(pvFields[i]);
759  newLine(builder,indentLevel +2);
760  *builder += pvString->getFieldName() + " " + pvString->get();
761  }
762  }
763  string name = node->masterPVField->getFullName();
764  newLine(builder,indentLevel +1);
765  *builder += "masterField " + name;
766  if(node->pvFilters.size()>0) {
767  newLine(builder,indentLevel +2);
768  *builder += "filters:";
769  for(size_t i=0; i< node->pvFilters.size(); ++i) {
770  PVFilterPtr pvFilter = node->pvFilters[i];
771  *builder += " " + pvFilter->getName();
772  }
773  }
774  if(!node->isStructure) return;
775  CopyStructureNodePtr structureNode =
776  static_pointer_cast<CopyStructureNode>(node);
777  CopyNodePtrArrayPtr nodes = structureNode->nodes;
778  for(size_t i=0; i<nodes->size(); ++i) {
779  CopyNodePtr node = (*nodes)[i];
780  if(!node) {
781  newLine(builder,indentLevel +1);
782  ss.str("");
783  ss << "node[" << i << "] is null";
784  *builder += ss.str();
785  continue;
786  }
787  dump(builder,node,indentLevel+1);
788  }
789 }
790 
791 
792 }}
std::tr1::shared_ptr< CopyStructureNode > CopyStructureNodePtr
std::tr1::shared_ptr< CopyNode > CopyNodePtr
std::tr1::shared_ptr< PVPlugin > PVPluginPtr
Definition: pvPlugin.h:28
std::tr1::shared_ptr< PVFilter > PVFilterPtr
Definition: pvPlugin.h:29
std::tr1::shared_ptr< PVCopy > PVCopyPtr
Definition: pvPlugin.h:25
Support for subset of fields in a pvStructure.
std::vector< CopyNodePtr > CopyNodePtrArray
Definition: pvCopy.cpp:66
std::tr1::shared_ptr< PVCopyTraverseMasterCallback > PVCopyTraverseMasterCallbackPtr
std::tr1::shared_ptr< CopyNodePtrArray > CopyNodePtrArrayPtr
Definition: pvCopy.cpp:67