This is Unofficial EPICS BASE Doxygen Site
pvalink_link.cpp
Go to the documentation of this file.
1 #include <pv/reftrack.h>
2 #include <alarm.h>
3 
4 #include "pvalink.h"
5 
6 namespace pvalink {
7 
9  :alive(true)
10  ,plink(0)
11  ,used_scratch(false)
12  ,used_queue(false)
13 {
14  REFTRACE_INCREMENT(num_instances);
15 
18  snap_time.nsec = 0;
19 
20  //TODO: valgrind tells me these aren't initialized by Base, but probably should be.
21  parseDepth = 0;
22  parent = 0;
23 }
24 
26 {
27  alive = false;
28 
29  if(lchan) { // may be NULL if parsing fails
30  Guard G(lchan->lock);
31 
32  lchan->links.erase(this);
33  lchan->links_changed = true;
34 
35  bool new_debug = false;
36  for(pvaLinkChannel::links_t::const_iterator it(lchan->links.begin()), end(lchan->links.end())
37  ; it!=end; ++it)
38  {
39  const pvaLink *pval = *it;
40  if(pval->debug) {
41  new_debug = true;
42  break;
43  }
44  }
45 
46  lchan->debug = new_debug;
47  }
48 
49  REFTRACE_DECREMENT(num_instances);
50 }
51 
52 static
53 pvd::StructureConstPtr monitorRequestType = pvd::getFieldCreate()->createFieldBuilder()
54  ->addNestedStructure("field")
55  ->endNested()
56  ->addNestedStructure("record")
57  ->addNestedStructure("_options")
58  ->add("pipeline", pvd::pvBoolean)
59  ->add("atomic", pvd::pvBoolean)
60  ->add("queueSize", pvd::pvUInt)
61  ->endNested()
62  ->endNested()
63  ->createStructure();
64 
66 {
67  pvd::PVStructurePtr ret(pvd::getPVDataCreate()->createPVStructure(monitorRequestType));
68  ret->getSubFieldT<pvd::PVBoolean>("record._options.pipeline")->put(pipeline);
69  ret->getSubFieldT<pvd::PVBoolean>("record._options.atomic")->put(true);
70  ret->getSubFieldT<pvd::PVUInt>("record._options.queueSize")->put(queueSize);
71  return ret;
72 }
73 
74 // caller must lock lchan->lock
75 bool pvaLink::valid() const
76 {
77  return lchan->connected_latched && lchan->op_mon.root;
78 }
79 
80 // caller must lock lchan->lock
81 pvd::PVField::const_shared_pointer pvaLink::getSubField(const char *name)
82 {
83  pvd::PVField::const_shared_pointer ret;
84  if(valid()) {
85  if(fieldName.empty()) {
86  // we access the top level struct
87  ret = lchan->op_mon.root->getSubField(name);
88 
89  } else {
90  // we access a sub-struct
91  ret = lchan->op_mon.root->getSubField(fieldName);
92  if(ret->getField()->getType()!=pvd::structure) {
93  // addressed sub-field isn't a sub-structure
94  if(strcmp(name, "value")!=0) {
95  // unless we are trying to fetch the "value", we fail here
96  ret.reset();
97  }
98  } else {
99  ret = static_cast<const pvd::PVStructure*>(ret.get())->getSubField(name);
100  }
101  }
102  }
103  return ret;
104 }
105 
106 // call with channel lock held
108 {
109  DEBUG(this,<<plink->precord->name<<" disconnect");
110  // TODO: option to remain queue'd while disconnected
111 
112  used_queue = used_scratch = false;
113 }
114 
116 {
117  DEBUG(this,<<plink->precord->name<<" type change");
118 
119  assert(lchan->connected_latched && !!lchan->op_mon.root); // we should only be called when connected
120 
121  fld_value = getSubField("value");
122  fld_seconds = std::tr1::dynamic_pointer_cast<const pvd::PVScalar>(getSubField("timeStamp.secondsPastEpoch"));
123  fld_nanoseconds = std::tr1::dynamic_pointer_cast<const pvd::PVScalar>(getSubField("timeStamp.nanoseconds"));
128 
130 
131  // build mask of all "changed" bits associated with our .value
132  // CP/CPP input links will process this link only for updates where
133  // the changed mask and proc_changed share at least one set bit.
134  if(fld_value) {
135  // bit for this field
136  proc_changed.set(fld_value->getFieldOffset());
137 
138  // bits of all parent fields
139  for(const pvd::PVStructure* parent = fld_value->getParent(); parent; parent = parent->getParent()) {
140  proc_changed.set(parent->getFieldOffset());
141  }
142 
143  if(fld_value->getField()->getType()==pvd::structure)
144  {
145  // bits of all child fields
146  const pvd::PVStructure *val = static_cast<const pvd::PVStructure*>(fld_value.get());
147  for(size_t i=val->getFieldOffset(), N=val->getNextFieldOffset(); i<N; i++)
148  proc_changed.set(i);
149  }
150  }
151 }
152 
153 } // namespace pvalink
PVScalar is the base class for each scalar field.
Definition: pvData.h:272
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
std::tr1::shared_ptr< detail::SharedPut > put
BitSet & clear(uint32 bitIndex)
Definition: bitSet.cpp:112
#define true
Definition: flexdef.h:84
int i
Definition: scan.c:967
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
std::size_t getFieldOffset() const
Definition: PVField.cpp:44
epicsUInt32 secPastEpoch
seconds since 0000 Jan 1, 1990
Definition: epicsTime.h:34
Data interface for a structure,.
Definition: pvData.h:712
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
Class that holds the data for each possible scalar type.
Definition: pvData.h:54
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:808
BitSet & set(uint32 bitIndex)
Definition: bitSet.cpp:103
#define INVALID_ALARM
Definition: alarm.h:53
#define false
Definition: flexdef.h:85
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
Definition: pvData.h:1648
epicsUInt32 nsec
nanoseconds within second
Definition: epicsTime.h:35
std::size_t getNextFieldOffset() const
Definition: PVField.cpp:50