This is Unofficial EPICS BASE Doxygen Site
epics::pvData::PVRequestMapper Class Reference

#include "createRequest.h"

Public Types

enum  mode_t { Mask, Slice }
 

Public Member Functions

 PVRequestMapper ()
 
 PVRequestMapper (const PVStructure &base, const PVStructure &pvRequest, mode_t mode=Mask)
 
void reset ()
 return to state of default ctor More...
 
const StructureConstPtrbase () const
 
const StructureConstPtrrequested () const
 
const BitSetrequestedMask () const
 
PVStructurePtr buildRequested () const
 
PVStructurePtr buildBase () const
 
void compute (const PVStructure &base, const PVStructure &pvRequest, mode_t mode=Mask)
 
const std::string & warnings () const
 After compute(), check if !warnings().empty() More...
 
void copyBaseToRequested (const PVStructure &base, const BitSet &baseMask, PVStructure &request, BitSet &requestMask) const
 
void copyBaseFromRequested (PVStructure &base, BitSet &baseMask, const PVStructure &request, const BitSet &requestMask) const
 
void maskBaseToRequested (const BitSet &baseMask, BitSet &requestMask) const
 
void maskBaseFromRequested (BitSet &baseMask, const BitSet &requestMask) const
 
void swap (PVRequestMapper &other)
 Exchange contents of two mappers. O(0) and never throws. More...
 

Detailed Description

Helper for implementations of epics::pvAccess::ChannelProvider in interpreting the 'field' substructure of a pvRequest. Copies between an internal (base) Structure, and a client/user visible (requested) Structure.

Note
PVRequestMapper is not re-entrant. It is copyable and swap()able.

Definition at line 74 of file createRequest.h.

Member Enumeration Documentation

Enumerator
Mask 

Masking mode.

   Requested Structure is identical to Base.
   The 'field' substructure of the provided pvRequest is used to construct a BitSet
   where the bits corresponding to the "selected" fields are set.  This mask can be
   access via. requestedMask().  The copy* and mask* methods operate only
   on "selected" fields.
Slice 

Slice mode

   The Requested Structure is a strict sub-set of the Base Structure containing
   those fields "selected" by the 'field' substructure of the provided pvRequest.

Definition at line 76 of file createRequest.h.

Constructor & Destructor Documentation

epics::pvData::PVRequestMapper::PVRequestMapper ( )

Definition at line 26 of file requestmapper.cpp.

26 {}
epics::pvData::PVRequestMapper::PVRequestMapper ( const PVStructure base,
const PVStructure pvRequest,
mode_t  mode = Mask 
)
See also
compute()

Definition at line 28 of file requestmapper.cpp.

31 {
32  compute(base, pvRequest, mode);
33 }
void compute(const PVStructure &base, const PVStructure &pvRequest, mode_t mode=Mask)
const StructureConstPtr & base() const

Member Function Documentation

const StructureConstPtr& epics::pvData::PVRequestMapper::base ( ) const
inline
Returns
the Structure of the PVStructure previously passed to compute(). NULL if never computed()'d

Definition at line 104 of file createRequest.h.

104 { return typeBase; }
PVStructurePtr epics::pvData::PVRequestMapper::buildBase ( ) const
Returns
A new instance of the base() Structure

Definition at line 42 of file requestmapper.cpp.

43 {
44  if(!typeBase)
45  THROW_EXCEPTION2(std::logic_error, "No mapping compute()d");
46  return typeBase->build();
47 }
#define THROW_EXCEPTION2(TYPE, MSG)
PVStructurePtr epics::pvData::PVRequestMapper::buildRequested ( ) const
Returns
A new instance of the requested() Structure

Definition at line 35 of file requestmapper.cpp.

36 {
37  if(!typeRequested)
38  THROW_EXCEPTION2(std::logic_error, "No mapping compute()d");
39  return typeRequested->build();
40 }
#define THROW_EXCEPTION2(TYPE, MSG)
void epics::pvData::PVRequestMapper::compute ( const PVStructure base,
const PVStructure pvRequest,
mode_t  mode = Mask 
)

(re)compute the selected subset of provided base structure.

Parameters
baseA full base structure. Must be "top level" (field offset zero).
pvRequestThe user/client provided request modifier
modeControl how the mapping is constructed.
See also
mode_t for a description of mapping modes.
Postcondition
Updates warnings()
Exceptions
std::runtime_errorFor errors involving invalid pvRequest
std::logic_errorif the provided base is not a "top level" PVStructure.

Definition at line 49 of file requestmapper.cpp.

52 {
53  if(base.getFieldOffset()!=0)
54  THROW_EXCEPTION2(std::logic_error, "Mapper must be used with top level PVStructure");
55 
56  bool ok = true;
57 
58  // we want to be transactional, which requires a second copy of everything.
59  PVRequestMapper temp;
60 
61  // whether to preserve IDs of partial structures.
62  bool keepids = false;
63  PVScalar::const_shared_pointer pbp(pvRequest.getSubField<PVScalar>("record._options.keepIDs"));
64  try {
65  if(pbp) keepids = pbp->getAs<boolean>();
66  }catch(std::runtime_error& e){
67  std::ostringstream msg;
68  msg<<"Can't parse keepIDs : '"<<e.what()<<"' ";
69  temp.messages+=msg.str();
70  }
71 
72  PVStructure::const_shared_pointer fields(pvRequest.getSubField<PVStructure>("field"));
73  if(!fields || fields->getPVFields().empty()) {
74  // not selection, or empty selection, treated as select all
75  temp.typeBase = temp.typeRequested = base.getStructure();
76 
77  for(size_t i=1, N=base.getNextFieldOffset(); i<N; i++)
78  temp.maskRequested.set(i);
79 
80  } else {
81  FieldBuilderPtr builder(getFieldCreate()->createFieldBuilder());
82 
83  if(keepids)
84  builder = builder->setId(base.getStructure()->getID());
85 
86  ok &= temp._compute(base, *fields, builder, keepids, 0); // fills in builder
87 
88  temp.typeBase = base.getStructure();
89  temp.typeRequested = builder->createStructure();
90  // possible that typeBase==typeRequested if all fields explicitly selected
91  }
92 
93  if(mode==Mask) {
94  // short circuit use of masked Structure, but keep maskRequested
95  temp.typeRequested = temp.typeBase;
96  }
97 
98  {
99  PVStructurePtr proto(temp.typeRequested->build());
100 
101  // base -> request may be sparce mapping
102  temp.base2req.resize(base.getNextFieldOffset());
103  // request -> base is dense mapping
104  temp.req2base.resize(proto->getNextFieldOffset());
105 
106  // special handling for whole structure mapping. in part because getSubField(0) isn't allowed
107  temp.base2req[0] = Mapping(0, false);
108  temp.req2base[0] = Mapping(0, false);
109 
110  // Iterate prototype of requested to map with base field offsets.
111  // which is handled as a special case below.
112  // We also don't try to prevent redundant copies if both leaf and compress bits are set.
113  for(size_t r=1, N=proto->getNextFieldOffset(); r<N; r++) {
114  PVField::const_shared_pointer fld_req(proto->getSubFieldT(r)),
115  fld_base(base.getSubFieldT(fld_req->getFullName()));
116  const size_t b = fld_base->getFieldOffset();
117 
118  if(!temp.requestedMask().get(b))
119  continue;
120 
121  bool leaf = fld_base->getField()->getType()!=structure;
122 
123  // initialize mapping when our bit is set
124  temp.base2req[b] = Mapping(r, leaf);
125  temp.req2base[r] = Mapping(b, leaf);
126 
127  // add ourself to all "compress" bit mappings of enclosing structures
128  for(const PVStructure *parent = fld_req->getParent(); parent; parent = parent->getParent()) {
129  temp.req2base[parent->getFieldOffset()].tomask .set(b);
130  temp.req2base[parent->getFieldOffset()].frommask.set(r);
131  }
132 
133  for(const PVStructure *parent = fld_base->getParent(); parent; parent = parent->getParent()) {
134  temp.base2req[parent->getFieldOffset()].tomask .set(r);
135  temp.base2req[parent->getFieldOffset()].frommask.set(b);
136  }
137  }
138  }
139 
140  temp.maskRequested.set(0);
141 
142  if(temp.maskRequested.nextSetBit(1)==-1) {
143  ok = false;
144  temp.messages+="Empty field selection";
145  }
146 
147  if(!ok)
148  throw std::runtime_error(temp.messages);
149 
150  swap(temp);
151 }
#define THROW_EXCEPTION2(TYPE, MSG)
int i
Definition: scan.c:967
void swap(PVRequestMapper &other)
Exchange contents of two mappers. O(0) and never throws.
std::tr1::shared_ptr< FieldBuilder > FieldBuilderPtr
const StructureConstPtr & base() const
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
void epics::pvData::PVRequestMapper::copyBaseFromRequested ( PVStructure base,
BitSet baseMask,
const PVStructure request,
const BitSet requestMask 
) const

Copy field values into Base structure from Requested structure

Parameters
baseAn instance of the base Structure. Field values are copied into it. Need not be the same instance passed to compute().
baseMaskA bit mask indicating which base fields were copied. BitSet::clear() is not called.
requestAn instance of the requested() Structure. Field values are copied from it.
requestMaskA bit mask selecting those requested fields to copy.

Definition at line 235 of file requestmapper.cpp.

240  {
241  assert(base.getStructure()==typeBase);
242  assert(request.getStructure()==typeRequested);
243  _map(request, requestMask, base, baseMask, true);
244 }
std::string request
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
const StructureConstPtr & base() const
void epics::pvData::PVRequestMapper::copyBaseToRequested ( const PVStructure base,
const BitSet baseMask,
PVStructure request,
BitSet requestMask 
) const

Copy field values from Base structure into Requested structure

Parameters
baseAn instance of the base Structure. Field values are copied from it. Need not be the same instance passed to compute().
baseMaskA bit mask selecting those base fields to copy.
requestAn instance of the requested() Structure. Field values are copied to it.
requestMaskA bit mask indicating which requested fields were copied. BitSet::clear() is not called.

Definition at line 224 of file requestmapper.cpp.

229  {
230  assert(base.getStructure()==typeBase);
231  assert(request.getStructure()==typeRequested);
232  _map(base, baseMask, request, requestMask, false);
233 }
std::string request
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
const StructureConstPtr & base() const
void epics::pvData::PVRequestMapper::maskBaseFromRequested ( BitSet baseMask,
const BitSet requestMask 
) const
inline

Translate requested bit mask into base bit mask. BitSet::clear() is not called.

Definition at line 187 of file createRequest.h.

191  { _mapMask(requestMask, baseMask, true); }
void epics::pvData::PVRequestMapper::maskBaseToRequested ( const BitSet baseMask,
BitSet requestMask 
) const
inline

Translate Base bit mask into requested bit mask. BitSet::clear() is not called.

Definition at line 179 of file createRequest.h.

183  { _mapMask(baseMask, requestMask, false); }
const StructureConstPtr& epics::pvData::PVRequestMapper::requested ( ) const
inline
Returns
the Structure which is the selected sub-set of the base Structure. NULL if never computed()'d

Definition at line 106 of file createRequest.h.

106 { return typeRequested; }
const BitSet& epics::pvData::PVRequestMapper::requestedMask ( ) const
inline

A mask of all fields in the base structure which are also in the requested structure, and any parent/structure "compress" bits. eg. bit 0 is always set.

PVRequestMapper mapper(...);
...
BitSet changed = ...; // a base changed mask
bool wouldcopy = changed.logical_and(mapper.requestedMask());
// wouldcopy==false means that copyBaseToRequested(..., changed, ...) would be a no-op

eg. allows early detection of empty monitor updates.

Definition at line 121 of file createRequest.h.

121 { return maskRequested; }
void epics::pvData::PVRequestMapper::reset ( )

return to state of default ctor

Definition at line 317 of file requestmapper.cpp.

318 {
319  typeBase.reset();
320  typeRequested.reset();
321  maskRequested.clear();
322  base2req.clear();
323  req2base.clear();
324  messages.clear();
325  scratch.clear(); // paranoia
326 }
BitSet & clear(uint32 bitIndex)
Definition: bitSet.cpp:112
void epics::pvData::PVRequestMapper::swap ( PVRequestMapper other)

Exchange contents of two mappers. O(0) and never throws.

Definition at line 306 of file requestmapper.cpp.

307 {
308  typeBase.swap(other.typeBase);
309  typeRequested.swap(other.typeRequested);
310  maskRequested.swap(other.maskRequested);
311  base2req.swap(other.base2req);
312  req2base.swap(other.req2base);
313  messages.swap(other.messages);
314  scratch.swap(other.scratch); // paranoia
315 }
void swap(BitSet &set)
Swap contents.
Definition: bitSet.cpp:277
const std::string& epics::pvData::PVRequestMapper::warnings ( ) const
inline

After compute(), check if !warnings().empty()

Definition at line 143 of file createRequest.h.

143 { return messages; }

The documentation for this class was generated from the following files: