This product is made available subject to acceptance of the EPICS open source license.
As pvDataCPP progressed PVField and derived classes accumulated more and more member functions. These member functions have nothing to do with the primary primary purpose for pvData:
pvData (Process Variable Data) defines and implements an efficient way to store, access, and communicate memory resident data structures.This statement appears as the first sentence of pvDataJava.html. A few sentences later the document makes it clear that communication includes efficient network communication. Thus pvData provides an interface for network accessible structured data. The problem of adding member functions that have nothing to do with the primary purpose started with the Java API. It already had extra methods that solved problems that should have had a different solution. This document removes the extra methods so that when new problems arise in the future the solution will not involve adding new member functions to the introspection and data API.
The introspection and data API for pvData should only encapsulate methods that support the primary purpose stated above. The interfaces for C++ and Java should be similar so that someone who understands the interface in one of the languages and knows both languages will quickly understand the interface of the other language.
There is another problem with the existing API. There are methods that allow the "structure" to change after an pvData object is created. An example is PVField::renameField(std::string newName). Such methods should not exist.
There are methods regarding immutability: setImmutable, isImmutablei, setCapacityMutable, and isCapacityMutable. Should they exists? For now lets assume no.
One last issue is the interface for array data. This document proposes a simplified version of what currently exists. It requires that the implementation always provides storage for the complete raw array. The existing APIs allow the implementation to provide the data in "chunks". Giving up this requirement simplifies the array interfaces. The existing C++ implementation of PVValueArray has serious problems. The shared_vector that is implemented in pvDataCP-md provides the solution to fixing the problems. This document describes an API that is very similar to the new Java API except that raw arrays are replaced by shared_vector.
This document will first describe changes to the existing Java interfaces and then the corresponding C++ API.
The following shows which methods will be removed from the existing interfaces and what will be added. The methods to be removed are in red and methods to add are in blue Also the removed methods are at the end with a comment above. The new methods also have a comment.
interface Field extends Serializable {
std::string getId();
Type getType();
// following will be removed
void toString(StringBuilder buf);
void toString(StringBuilder buf,int indentLevel);
std::string toString();
}
// new interface
interface FieldTostd::string {
std::string toString(Field field);
}
interface Scalar extends Field {
ScalarType getScalarType();
}
interface ScalarArray extends Field {
ScalarType getElementType();
}
interface Structure extends Field {
Field getField(std::string fieldName);
int getFieldIndex(std::string fieldName);
Field[] getFields();
Field getField(int fieldIndex);
std::string[] getFieldNames();
std::string getFieldName(int fieldIndex)
}
interface StructureArray extends Field {
Structure getStructure();
}
interface FieldCreate {
Scalar createScalar(ScalarType scalarType);
ScalarArray createScalarArray(ScalarType elementType);
StructureArray createStructureArray(Structure elementStructure);
Structure createStructure(std::string[] fieldNames, Field[] field);
Structure createStructure(std::string id,std::string[] fieldNames, Field[] field);
Structure createStructure(Structure structToClone);
Field deserialize(ByteBuffer buffer, DeserializableControl control);
// following will be removed
Structure appendField(Structure structure,std::string fieldName, Field field);
Structure appendFields(Structure structure,std::string[] fieldNames, Field[] fields);
}
interface PVField extends Requester, Serializable {
std::string getFieldName();
void setRequester(Requester requester);
int getFieldOffset();
int getNextFieldOffset();
int getNumberFields();
Field getField();
PVStructure getParent();
void postPut();
void setPostHandler(PostHandler postHandler);
// following will be removed
PVAuxInfo getPVAuxInfo();
boolean isImmutable();
void setImmutable();
void renameField(std::string newName);
void toString(StringBuilder buf);
void toString(StringBuilder buf,int indentLevel);
std::string toString();
}
// The following is a new interface
interface PVFieldTostd::string {
std::string toString(PVField pvField);
void setMaxInitialArrayElements(int num);
void setMaxFinalArrayElements(int num);
int getMaxInitialArrayElements();
int getMaxFinalArrayElements();
}
interface PVScalar extends PVField{
Scalar getScalar();
}
interface PVDouble extends PVScalar{
double get();
void put(double value);
}
// also PVBoolean, PVByte, PVShort, PVInt, PVLong, PVFloat, and PVString
interface PVArray extends PVField, SerializableArray {
int getLength();
void setLength(int length);
int getCapacity();
void setCapacity(int length);
// following will be removed
boolean isCapacityMutable();
void setCapacityMutable(boolean isMutable);
}
interface PVScalarArray extends PVArray {
ScalarArray getScalarArray();
}
//following will be removed
public class DoubleArrayData {
public double[] data;
public int offset;
}
interface PVDoubleArray extends PVArray {
// following are new
double[] get();
void swap(double[] value);
//following will be removed
int get(int offset, int len, DoubleArrayData data);
int put(int offset,int len, double[] from, int fromOffset);
void shareData(double[] from);
}
// also PVBooleanArray, ..., PVStringArray
interface PVStructure extends PVField , BitSetSerializable{
Structure getStructure();
PVField[] getPVFields();
PVField getSubField(std::string fieldName);
PVField getSubField(int fieldOffset);
// The following are convenience methods
PVBoolean getBooleanField(std::string fieldName);
PVByte getByteField(std::string fieldName);
PVShort getShortField(std::string fieldName);
PVInt getIntField(std::string fieldName);
PVLong getLongField(std::string fieldName);
PVFloat getFloatField(std::string fieldName);
PVDouble getDoubleField(std::string fieldName);
PVString getStringField(std::string fieldName);
PVScalarArray getScalarArrayField(std::string fieldName);
PVStructureArray getStructureArrayField(std::string fieldName);
PVStructure getStructureField(std::string fieldName);
PVArray getArrayField(std::string fieldName,ScalarType elementType);
// following will be removed
void appendPVField(std::string fieldName,PVField pvField);
void appendPVFields(std::string[] fieldNames,PVField[] pvFields);
void removePVField(std::string fieldName);
void replacePVField(PVField oldPVField,PVField newPVField);
std::string getExtendsStructureName();
boolean putExtendsStructureName(std::string extendsStructureName);
public boolean checkValid();
}
//following will be removed
public class StructureArrayData {
public PVStructure[] data;
public int offset;
}
interface PVStructureArray extends PVArray{
StructureArray getStructureArray();
// following are new
PVStructure[] get();
void swap(PVStructure[] value);
// following will be removed
int get(int offset, int length, StructureArrayData data);
int put(int offset,int length, PVStructure[] from, int fromOffset);
void shareData(PVStructure[] from);
}
public interface PVDataCreate {
PVField createPVField(Field field);
PVField createPVField(PVField fieldToClone);
PVScalar createPVScalar(Scalar scalar);
PVScalar createPVScalar(ScalarType fieldType);
PVScalar createPVScalar(PVScalar scalarToClone);
PVScalarArray createPVScalarArray(ScalarArray array);
PVScalarArray createPVScalarArray(ScalarType elementType);
PVScalarArray createPVScalarArray(PVScalarArray arrayToClone;
PVStructureArray createPVStructureArray(StructureArray structureArray);
PVStructure createPVStructure(Structure structure);
PVStructure createPVStructure(std::string[] fieldNames,Field[] fields);
PVStructure createPVStructure(PVStructure structToClone);
// following will be removed
PVField[] flattenPVStructure(PVStructure pvStructure);
}
In addition to toString this has methods to limit the number of array element to display. The existing Java implementation of toString displayed all elements. For large arrays this is not desirable. The new methods provide a way for the client to limit the number of elements. The default might be set to something like display up to 10 elements with 5 from the beginning and 5 from the end.
For C++ this can be a replacement for dumpValue.
The old get and put are replaced by two new and simpler methods:
The method setCapacity will always create a new raw array and copy old data from the old to the new array. This is not true now since the implementation does not create a new array if the old capacity is equal to the requested capacity.
The C++ class definitions are similar to the Java definitions with two main exceptions:
class Field :
virtual public Serializable,
public std::tr1::enable_shared_from_this<Field>
{
public:
POINTER_DEFINITIONS(Field);
virtual ~Field();
Type getType() const{return m_type;}
virtual std::string getID() const = 0;
// following will be removed
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
...
};
// new function
std::ostream &toString(Field::const_reference field, std::ostream& o);
class Scalar : public Field{
public:
POINTER_DEFINITIONS(Scalar);
virtual ~Scalar();
typedef Scalar& reference;
typedef const Scalar& const_reference;
ScalarType getScalarType() const {return scalarType;}
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
// following will be removed
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
...
};
class ScalarArray : public Field{
public:
POINTER_DEFINITIONS(ScalarArray);
typedef ScalarArray& reference;
typedef const ScalarArray& const_reference;
ScalarArray(ScalarType scalarType);
ScalarType getElementType() const {return elementType;}
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
// following will be removed
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
...
};
class Structure : public Field {
public:
POINTER_DEFINITIONS(Structure);
typedef Structure& reference;
typedef const Structure& const_reference;
std::size_t getNumberFields() const {return numberFields;}
FieldConstPtr getField(std::string const & fieldName) const;
FieldConstPtr getField(std::size_t index) const;
std::size_t getFieldIndex(std::string const &fieldName) const;
FieldConstPtrArray const & getFields() const {return fields;}
StringArray const & getFieldNames() const;
std::string getFieldName(std::size_t fieldIndex);
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
// following will be removed
void renameField(std::size_t fieldIndex,std::string const &newName);
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual std::string getID() const;
...
};
class StructureArray : public Field{
public:
POINTER_DEFINITIONS(StructureArray);
typedef StructureArray& reference;
typedef const StructureArray& const_reference;
StructureConstPtr getStructure() const {return pstructure;}
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
// following will be removed
virtual void toString(StringBuilder buf,int indentLevel=0) const;
virtual std::string getID() const;
...
};
class FieldCreate {
public:
static FieldCreatePtr getFieldCreate();
ScalarConstPtr createScalar(ScalarType scalarType) const
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
StructureConstPtr createStructure (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
StructureConstPtr createStructure (
std::string const &id,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
// following will be removed
StructureConstPtr appendField(
StructureConstPtr const & structure,
std::string const &fieldName, FieldConstPtr const & field) const;
StructureConstPtr appendFields(
StructureConstPtr const & structure,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
...
};
extern FieldCreatePtr getFieldCreate();
class PVField
: virtual public Serializable,
public std::tr1::enable_shared_from_this<PVField>
{
public:
POINTER_DEFINITIONS(PVField);
virtual ~PVField();
inline const std::string &getFieldName() const ;
virtual void setRequester(RequesterPtr const &prequester);
std::size_t getFieldOffset() const;
std::size_t getNextFieldOffset() const;
std::size_t getNumberFields() const;
const FieldConstPtr & getField() const ;
PVStructure * getParent() const
void postPut() ;
void setPostHandler(PostHandlerPtr const &postHandler);
// following will be removed
virtual void message(std::string message,MessageType messageType);
void replacePVField(const PVFieldPtr& newPVField);
std::string getFullName() const;
virtual bool equals(PVField &pv);
PVAuxInfoPtr & getPVAuxInfo()
bool isImmutable() const;
virtual void setImmutable();
void replacePVField(const PVFieldPtr& newPVField);
void renameField(std::string const &newName);
virtual void toString(StringBuilder buf) ;
virtual void toString(StringBuilder buf,int indentLevel);
std::ostream& dumpValue(std::ostream& o) const;
...
};
// The following is a new class
class PVFieldTostd::string {
std::string toString(const PVFieldPtr &pvField);
void setMaxInitialArrayElements(size_t num);
void setMaxFinalArrayElements(size_t num);
size_t getMaxInitialArrayElements();
size_t getMaxFinalArrayElements();
...
}
class PVScalar : public PVField {
public:
POINTER_DEFINITIONS(PVScalar);
virtual ~PVScalar();
typedef PVScalar &reference;
typedef const PVScalar& const_reference;
const ScalarConstPtr getScalar() const ;
...
}
template<typename T>
class PVScalarValue : public PVScalar {
public:
POINTER_DEFINITIONS(PVScalarValue);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
virtual ~PVScalarValue() {}
virtual T get() const = 0;
virtual void put(T value) = 0;
// following will be removed
std::ostream& dumpValue(std::ostream& o)
void operator>>=(T& value) const;
void operator<<=(T value);
...
}
// PVString is special case, since it implements SerializableArray
class PVString : public PVScalarValue<std::string>, SerializableArray {
public:
virtual ~PVString() {}
...
}
class PVArray : public PVField, public SerializableArray {
public:
POINTER_DEFINITIONS(PVArray);
virtual ~PVArray();
std::size_t getLength() const;
virtual void setLength(std::size_t length);
std::size_t getCapacity() const;
virtual void setCapacity(std::size_t capacity) = 0;
// following will be removed
virtual void setImmutable();
bool isCapacityMutable() const;
void setCapacityMutable(bool isMutable);
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
...
};
class PVScalarArray : public PVArray {
public:
POINTER_DEFINITIONS(PVScalarArray);
virtual ~PVScalarArray();
typedef PVScalarArray &reference;
typedef const PVScalarArray& const_reference;
const ScalarArrayConstPtr getScalarArray() const ;
// following will be removed
virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
...
}
// following will be removed
template<typename T>
class PVArrayData {
private:
std::vector<T> init;
public:
POINTER_DEFINITIONS(PVArrayData);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
std::vector<T> & data;
std::size_t offset;
PVArrayData()
: data(init)
{}
};
template<typename T>
class PVValueArray : public PVScalarArray {
public:
POINTER_DEFINITIONS(PVValueArray);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
// following are new typeDefs
typedef shared_vector<T> svector;
typedef shared_vector<const T> const_svector;
virtual ~PVValueArray() {}
// following are added
svector get();
void swap(svector& value);
// following are removed
typedef PVValueArray & reference;
typedef const PVValueArray & const_reference;
typedef PVArrayData<T> ArrayDataType;
typedef std::vector<T> vector;
typedef const std::vector<T> const_vector;
typedef std::tr1::shared_ptr<vector> shared_vector;
virtual std::size_t get(
std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
virtual std::size_t put(std::size_t offset,
std::size_t length, const_pointer from, std::size_t fromOffset) = 0;
virtual std::size_t put(std::size_t offset,
std::size_t length, const_vector &from, std::size_t fromOffset);
virtual void shareData(
shared_vector const & value,
std::size_t capacity,
std::size_t length) = 0;
virtual pointer get() = 0;
virtual pointer get() const = 0;
virtual vector const & getVector() = 0;
virtual shared_vector const & getSharedVector() = 0;
std::ostream& dumpValue(std::ostream& o) const;
std::ostream& dumpValue(std::ostream& o, size_t index) const;
...
};
typedef PVValueArray<uint8> PVBooleanArray;
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
...
typedef PVValueArray<std::string> PVStringArray;
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
class PVStructure : public PVField,public BitSetSerializable {
public:
POINTER_DEFINITIONS(PVStructure);
virtual ~PVStructure();
typedef PVStructure & reference;
typedef const PVStructure & const_reference;
StructureConstPtr getStructure() const;
const PVFieldPtrArray & getPVFields() const;
PVFieldPtr getSubField(std::string const &fieldName) const;
PVFieldPtr getSubField(std::size_t fieldOffset) const;
PVBooleanPtr getBooleanField(std::string const &fieldName) ;
PVBytePtr getByteField(std::string const &fieldName) ;
PVShortPtr getShortField(std::string const &fieldName) ;
PVIntPtr getIntField(std::string const &fieldName) ;
PVLongPtr getLongField(std::string const &fieldName) ;
PVUBytePtr getUByteField(std::string const &fieldName) ;
PVUShortPtr getUShortField(std::string const &fieldName) ;
PVUIntPtr getUIntField(std::string const &fieldName) ;
PVULongPtr getULongField(std::string const &fieldName) ;
PVFloatPtr getFloatField(std::string const &fieldName) ;
PVDoublePtr getDoubleField(std::string const &fieldName) ;
PVStringPtr getStringField(std::string const &fieldName) ;
PVStructurePtr getStructureField(std::string const &fieldName) ;
PVScalarArrayPtr getScalarArrayField(
std::string const &fieldName,ScalarType elementType) ;
PVStructureArrayPtr getStructureArrayField(std::string const &fieldName) ;
virtual void serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
virtual void deserialize(
ByteBuffer *pbuffer,DeserializableControl *pflusher);
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher,BitSet *pbitSet) const;
virtual void deserialize(ByteBuffer *pbuffer,
DeserializableControl*pflusher,BitSet *pbitSet);
PVStructure(StructureConstPtr const & structure);
PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);
// following are removed
void appendPVField(
std::string const &fieldName,
PVFieldPtr const & pvField);
void appendPVFields(
StringArray const & fieldNames,
PVFieldPtrArray const & pvFields);
void removePVField(std::string const &fieldName);
virtual void setImmutable();
std::string getExtendsStructureName() const;
bool putExtendsStructureName(
std::string const &extendsStructureName);
};
// following will be removed
typedef PVArrayData<PVStructurePtr> StructureArrayData;
class PVStructureArray : public PVArray
{
public:
POINTER_DEFINITIONS(PVStructureArray);
typedef PVStructurePtr value_type;
typedef PVStructurePtr* pointer;
typedef const PVStructurePtr* const_pointer;
// following are new typeDefs
typedef shared_vector<PVStructurePtr> svector;
typedef shared_vector<const PVStructurePtr> const_svector;
virtual ~PVStructureArray() {}
virtual void setCapacity(size_t capacity);
virtual void setLength(std::size_t length);
virtual StructureArrayConstPtr getStructureArray() const ;
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const;
virtual void deserialize(ByteBuffer *buffer,
virtual void serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
// following are new
svector get();
void swap(svector & value);
// following are removed
typedef PVArrayData<PVStructurePtr> ArrayDataType;
typedef std::vector<PVStructurePtr> vector;
typedef const std::vector<PVStructurePtr> const_vector;
typedef std::tr1::shared_ptr<vector> shared_vector;
typedef PVStructureArray &reference;
typedef const PVStructureArray& const_reference;
virtual std::size_t append(std::size_t number);
virtual bool remove(std::size_t offset,std::size_t number);
virtual void compress();
virtual std::size_t get(std::size_t offset, std::size_t length,
StructureArrayData &data);
virtual std::size_t put(std::size_t offset,std::size_t length,
const_vector const & from, std::size_t fromOffset);
virtual void shareData(
shared_vector const & value,
std::size_t capacity,
std::size_t length);
virtual pointer get() { return &((*value.get())[0]); }
virtual pointer get() const { return &((*value.get())[0]); }
virtual vector const & getVector() {return *value;}
virtual shared_vector const & getSharedVector() {return value;}
...
};
class PVDataCreate {
public:
static PVDataCreatePtr getPVDataCreate();
PVFieldPtr createPVField(FieldConstPtr const & field);
PVFieldPtr createPVField(PVFieldPtr const & fieldToClone);
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
PVScalarPtr createPVScalar(ScalarType scalarType);
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
PVStructurePtr createPVStructure(StructureConstPtr const & structure);
PVStructurePtr createPVStructure(
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
...
};
extern PVDataCreatePtr getPVDataCreate();