From a0de4f126ff836b573ddacc7b537f8f7dc1ffab4 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Thu, 7 Feb 2013 22:52:16 +0100 Subject: [PATCH 1/9] operator<< for all PVField, indent and array_at manipulator --- pvDataApp/factory/PVArray.cpp | 5 ++ pvDataApp/factory/PVField.cpp | 35 ++++++++--- pvDataApp/factory/PVStructure.cpp | 27 ++++++++ pvDataApp/factory/PVStructureArray.cpp | 23 +++++++ pvDataApp/pv/pvData.h | 86 ++++++++++++++++++++++++-- 5 files changed, 161 insertions(+), 15 deletions(-) diff --git a/pvDataApp/factory/PVArray.cpp b/pvDataApp/factory/PVArray.cpp index cba18ff..89dd863 100644 --- a/pvDataApp/factory/PVArray.cpp +++ b/pvDataApp/factory/PVArray.cpp @@ -97,4 +97,9 @@ PVArray::~PVArray() pImpl->capacity = capacity; } +std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array) +{ + return array.dumpValue(manip.stream, manip.index); +} + }} diff --git a/pvDataApp/factory/PVField.cpp b/pvDataApp/factory/PVField.cpp index da8575e..e4574d9 100644 --- a/pvDataApp/factory/PVField.cpp +++ b/pvDataApp/factory/PVField.cpp @@ -194,17 +194,34 @@ void PVField::toString(StringBuilder buf,int indentLevel) if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel); } -std::ostream& PVField::dumpValue(std::ostream& o) const +std::ostream& operator<<(std::ostream& o, const PVField& f) { - // default implementation - // each PVField class should implement it to avoid switch statement - // and string reallocation - String tmp; - convert->getString(&tmp,this,0); - return o << tmp; -} + std::ostream& ro = f.dumpValue(o); + // TODO I do not want to call getPVAuxInfo() since it lazily creates a new instance of it + //if (f.pvAuxInfo.get()!=NULL) ro << *(f.pvAuxInfo.get()); + return ro; +}; -std::ostream& operator<<(std::ostream& o, const PVField& f) { return f.dumpValue(o); }; +namespace format +{ + std::ostream& operator<<(std::ostream& os, indent_level const& indent) + { + indent_value(os) = indent.level; + return os; + } + + std::ostream& operator<<(std::ostream& os, indent const&) + { + long il = indent_value(os); + std::size_t spaces = static_cast(il) * 4; + return os << std::string(spaces, ' '); + } + + array_at_internal operator<<(std::ostream& str, array_at const& manip) + { + return array_at_internal(manip.index, str); + } +}; void PVField::computeOffset(const PVField * pvField) { const PVStructure * pvTop = pvField->getParent(); diff --git a/pvDataApp/factory/PVStructure.cpp b/pvDataApp/factory/PVStructure.cpp index dc25165..850f6be 100644 --- a/pvDataApp/factory/PVStructure.cpp +++ b/pvDataApp/factory/PVStructure.cpp @@ -702,4 +702,31 @@ static PVFieldPtr findSubField( return PVFieldPtr(); } +std::ostream& PVStructure::dumpValue(std::ostream& o) const +{ + o << format::indent() << getStructure()->getID() << ' ' << getFieldName(); + String extendsName = getExtendsStructureName(); + if(extendsName.length()>0) { + o << " extends " << extendsName; + } + o << std::endl; + { + format::indent_scope s(o); + + PVFieldPtrArray const & fieldsData = getPVFields(); + if (fieldsData.size() != 0) { + size_t length = getStructure()->getNumberFields(); + for(size_t i=0; igetField()->getType(); + if (type == scalar || type == scalarArray) + o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl; + else + o << *(fieldField.get()); + } + } + } + return o; +} + }} diff --git a/pvDataApp/factory/PVStructureArray.cpp b/pvDataApp/factory/PVStructureArray.cpp index fa941ef..b6cba3f 100644 --- a/pvDataApp/factory/PVStructureArray.cpp +++ b/pvDataApp/factory/PVStructureArray.cpp @@ -250,4 +250,27 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer, } } +std::ostream& PVStructureArray::dumpValue(std::ostream& o) const +{ + o << format::indent() << getStructureArray()->getID() << ' ' << getFieldName() << std::endl; + size_t length = getLength(); + if (length > 0) + { + format::indent_scope s(o); + + for (size_t i = 0; i < length; i++) + dumpValue(o, i); + } + + return o; +} + +std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const +{ + PVStructurePtrArray pvArray = *value.get(); + PVStructurePtr pvStructure = pvArray[index]; + return o << *(pvStructure.get()); + return o; +} + }} diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index b04d737..364ee32 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -14,10 +14,74 @@ #include #include #include +#include +#include #include #include namespace epics { namespace pvData { + +namespace format { + +struct indent_level +{ + long level; + + indent_level(long l) : level(l) {} +}; + +inline long& indent_value(std::ios_base& ios) +{ + static int indent_index = std::ios_base::xalloc(); + return ios.iword(indent_index); +} + +std::ostream& operator<<(std::ostream& os, indent_level const& indent); +struct indent_scope +{ + long saved_level; + std::ios_base& stream; + + indent_scope(std::ios_base& ios) : + stream(ios) + { + long& l = indent_value(ios); + saved_level = l; + l = saved_level + 1; + } + + ~indent_scope() + { + indent_value(stream) = saved_level; + } +}; + +struct indent +{ +}; + +std::ostream& operator<<(std::ostream& os, indent const&); + +struct array_at +{ + std::size_t index; + + array_at(std::size_t ix) : index(ix) {} +}; + +struct array_at_internal +{ + std::size_t index; + std::ostream& stream; + + array_at_internal(std::size_t ix, std::ostream& str) : index(ix), stream(str) {} +}; + +array_at_internal operator<<(std::ostream& str, array_at const& manip); + +}; + + class PVAuxInfo; class PostHandler; @@ -277,7 +341,7 @@ public: * @param o output stream. * @return The output stream. */ - virtual std::ostream& dumpValue(std::ostream& o) const; + virtual std::ostream& dumpValue(std::ostream& o) const = 0; protected: PVField::shared_pointer getPtrSelf() @@ -453,6 +517,9 @@ public: * @param The capacity. */ virtual void setCapacity(std::size_t capacity) = 0; + + virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0; + protected: PVArray(FieldConstPtr const & field); void setCapacityLength(std::size_t capacity,std::size_t length); @@ -461,6 +528,8 @@ private: friend class PVDataCreate; }; +std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array); + /** * Class provided by caller of get */ @@ -505,8 +574,6 @@ public: */ const ScalarArrayConstPtr getScalarArray() const ; - virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0; - protected: PVScalarArray(ScalarArrayConstPtr const & scalarArray); private: @@ -608,6 +675,10 @@ public: virtual pointer get() const { return &((*value.get())[0]); } virtual vector const & getVector() {return *value;} virtual shared_vector const & getSharedVector() {return value;} + + virtual std::ostream& dumpValue(std::ostream& o) const; + virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; + protected: PVStructureArray(StructureArrayConstPtr const & structureArray); private: @@ -816,6 +887,9 @@ public: * @param pvFields The array of fields for the structure. */ PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields); + + virtual std::ostream& dumpValue(std::ostream& o) const; + private: void fixParentStructure(); static PVFieldPtr nullPVField; @@ -896,7 +970,7 @@ public: std::ostream& dumpValue(std::ostream& o) const { - o << "["; + o << '['; std::size_t len = getLength(); bool first = true; for (std::size_t i = 0; i < len; i++) @@ -904,10 +978,10 @@ public: if (first) first = false; else - o << ","; + o << ','; dumpValue(o, i); } - return o << "]"; + return o << ']'; } std::ostream& dumpValue(std::ostream& o, size_t index) const From c4f6132aca65bce357e802a4010c005fdc8952c8 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Fri, 8 Feb 2013 22:45:04 +0100 Subject: [PATCH 2/9] added simple operators 'test', added <<= >>= operators to PVScalar --- pvDataApp/pv/pvData.h | 14 ++++++ testApp/pv/Makefile | 4 ++ testApp/pv/testOperators.cpp | 85 ++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 testApp/pv/testOperators.cpp diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index 364ee32..4f15742 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -423,6 +423,20 @@ public: return o << get(); } + // get operator + // double value; doubleField >>= value; + void operator>>=(T& value) const + { + value = get(); + } + + // put operator + // double value = 12.8; doubleField <<= value; + void operator<<=(T value) + { + put(value); + } + protected: PVScalarValue(ScalarConstPtr const & scalar) : PVScalar(scalar) {} diff --git a/testApp/pv/Makefile b/testApp/pv/Makefile index 7893a3e..558e4c0 100644 --- a/testApp/pv/Makefile +++ b/testApp/pv/Makefile @@ -42,6 +42,10 @@ PROD_HOST += testPVStructureArray testPVStructureArray_SRCS += testPVStructureArray.cpp testPVStructureArray_LIBS += pvData Com +PROD_HOST += testOperators +testOperators_SRCS += testOperators.cpp +testOperators_LIBS += pvData Com + include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE diff --git a/testApp/pv/testOperators.cpp b/testApp/pv/testOperators.cpp new file mode 100644 index 0000000..07e4a8c --- /dev/null +++ b/testApp/pv/testOperators.cpp @@ -0,0 +1,85 @@ +/* testOperators.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvData is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/* Author: Matej Sekoranja Date: 2013.02 */ + +#include + +#include +#include +#include + +#include + +using namespace epics::pvData; + +static PVDataCreatePtr pvDataCreate = getPVDataCreate(); +static StandardFieldPtr standardField = getStandardField(); +static StandardPVFieldPtr standardPVField = getStandardPVField(); + +int main(int, char*) +{ + PVStructurePtr pvStructure = standardPVField->scalar(pvDouble, + "alarm,timeStamp,display,control,valueAlarm"); + + const double testDV = 12.8; + + PVDoublePtr pvValue = pvStructure->getDoubleField("value"); + *pvValue <<= testDV; + + double dv; + *pvValue >>= dv; + assert(testDV == dv); + + + const std::string testSV = "test message"; + + PVStringPtr pvMessage = pvStructure->getStringField("alarm.message"); + *pvMessage <<= testSV; + + std::string sv; + *pvMessage >>= sv; + assert(testSV == sv); + + // + // to stream tests + // + + std::cout << *pvValue << std::endl; + std::cout << *pvMessage << std::endl; + std::cout << *pvStructure << std::endl; + + + StringArray choices; + choices.reserve(3); + choices.push_back("one"); + choices.push_back("two"); + choices.push_back("three"); + pvStructure = standardPVField->enumerated(choices, "alarm,timeStamp,valueAlarm"); + std::cout << *pvStructure << std::endl; + + + + pvStructure = standardPVField->scalarArray(pvBoolean,"alarm,timeStamp"); + std::cout << *pvStructure << std::endl; + + + StructureConstPtr structure = standardField->scalar(pvDouble, "alarm,timeStamp"); + pvStructure = standardPVField->structureArray(structure,"alarm,timeStamp"); + size_t num = 2; + PVStructurePtrArray pvStructures; + pvStructures.reserve(num); + for(size_t i=0; icreatePVStructure(structure)); + } + PVStructureArrayPtr pvStructureArray = pvStructure->getStructureArrayField("value"); + pvStructureArray->put(0, num, pvStructures, 0); + std::cout << *pvStructure << std::endl; + + return 0; +} + From 97b1848ba35c336920b73df13b31d7b925b2e7fa Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Mon, 11 Feb 2013 10:30:30 +0100 Subject: [PATCH 3/9] added array_at manip test --- testApp/pv/testOperators.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/testApp/pv/testOperators.cpp b/testApp/pv/testOperators.cpp index 07e4a8c..3cc3fb6 100644 --- a/testApp/pv/testOperators.cpp +++ b/testApp/pv/testOperators.cpp @@ -63,8 +63,14 @@ int main(int, char*) - pvStructure = standardPVField->scalarArray(pvBoolean,"alarm,timeStamp"); + pvStructure = standardPVField->scalarArray(pvDouble,"alarm,timeStamp"); std::cout << *pvStructure << std::endl; + + double values[] = { 1.1, 2.2, 3.3 }; + PVDoubleArrayPtr darray = std::tr1::dynamic_pointer_cast(pvStructure->getScalarArrayField("value", pvDouble)); + darray->put(0, 3, values, 0); + std::cout << *darray << std::endl; + std::cout << format::array_at(1) << *darray << std::endl; StructureConstPtr structure = standardField->scalar(pvDouble, "alarm,timeStamp"); From aa1a67d6c1ef2b877de9efde112cd3cc3e252978 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Wed, 13 Feb 2013 14:18:42 +0100 Subject: [PATCH 4/9] added micro-benchmark --- pvDataApp/Makefile | 9 +- pvDataApp/mb/mb.cpp | 301 +++++++++++++++++++++++++++++++++++++++ pvDataApp/mb/mb.h | 130 +++++++++++++++++ pvDataApp/mb/mb_stat.cpp | 50 +++++++ testApp/Makefile | 1 + testApp/mb/Makefile | 13 ++ testApp/mb/README | 49 +++++++ testApp/mb/mb_test.cpp | 17 +++ 8 files changed, 569 insertions(+), 1 deletion(-) create mode 100644 pvDataApp/mb/mb.cpp create mode 100644 pvDataApp/mb/mb.h create mode 100644 pvDataApp/mb/mb_stat.cpp create mode 100644 testApp/mb/Makefile create mode 100644 testApp/mb/README create mode 100644 testApp/mb/mb_test.cpp diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index 50c3f87..992c394 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -92,9 +92,16 @@ LIBSRCS += bitSetUtil.cpp SRC_DIRS += $(PVDATA)/monitor INC += monitor.h +SRC_DIRS += $(PVDATA)/mb +INC += mb.h +LIBSRCS += mb.cpp -LIBRARY=pvData +PROD_HOST += mb_stat +mb_stat_CXXFLAGS += -DPV_MB +mb_stat_SRCS += mb_stat.cpp +mb_stat_LIBS += pvData Com +LIBRARY = pvData pvData_LIBS += Com include $(TOP)/configure/RULES diff --git a/pvDataApp/mb/mb.cpp b/pvDataApp/mb/mb.cpp new file mode 100644 index 0000000..b443e78 --- /dev/null +++ b/pvDataApp/mb/mb.cpp @@ -0,0 +1,301 @@ +#include "mb.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#if defined(__APPLE__) +#include +uint64_t MBTime() +{ + return mach_absolute_time(); +} +#else +uint64_t MBTime() +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return static_cast(ts.tv_sec) * 1000000000 + static_cast(ts.tv_nsec); +} +#endif + + +void MBPointAdd(MBEntity &e, intptr_t id, uint8_t stage) +{ + // no copy and no MBPoint init solution + const std::size_t ix = ATOMIC_GET_AND_INCREMENT(e.pos); + MBPoint& p = e.points[ix]; + p.id = id; p.stage = stage; + p.time = MBTime(); +} + +void MBCSVExport(MBEntity &e, std::ostream &o) +{ + const std::size_t len = ATOMIC_GET(e.pos); + for (std::size_t i = 0; i < len; i++) + { + MBPoint& p = e.points[i]; + o << p.id << ',' << static_cast(p.stage) << ',' << p.time << std::endl; + } +} + +// NOTE: this method is not thread-safe +void MBCSVImport(MBEntity &e, std::istream &i) +{ + std::string line; + char c; + + e.points.resize(0); + size_t lc = 0; + while (getline(i,line)) + { + lc++; + std::istringstream is(line); + MBPoint p; + is >> p.id >> c; + uint32_t s; is >> s >> c; p.stage = s; + is >> p.time; + + if (is.good() || is.eof()) + e.points.push_back(p); + else + { + std::cerr << "failed to parse line " << lc << ": \"" << line << "\"" << std::endl; + } + } + e.pos = e.points.size(); +} + +void MBNormalize(MBEntity &e) +{ + std::map lastTime; + + const std::size_t len = ATOMIC_GET(e.pos); + for (std::size_t i = 0; i < len; i++) + { + MBPoint& p = e.points[i]; + if (p.stage == 0) + lastTime[p.id] = p.time; + + std::map::iterator last = lastTime.find(p.id); + if (last == lastTime.end()) + { + std::cerr << "no 0 stage for " << e.name << ", id = " << p.id << std::endl; + p.time = -1; // TODO error?! + } + else + { + uint64_t lt = last->second; + last->second = p.time; + p.time -= lt; + } + } +} + +struct MBStatistics +{ + std::size_t count; + uint64_t min; + uint64_t max; + uint64_t rms; + + MBStatistics() : + count(0), + min(-1), + max(0), + rms(0.0) + {} + + MBStatistics(uint64_t sample) : + count(1), + min(sample), + max(sample), + rms(sample*sample) + { + }; + + void addSample(uint64_t sample) + { + count++; + if (sample < min) min = sample; + if (sample > max) max = sample; + rms += sample*sample; + }; +}; + +typedef std::map StatsMapPerStage; + +void MBStats(MBEntity &e, std::ostream &o) +{ + MBNormalize(e); + + StatsMapPerStage stats; + + const std::size_t len = ATOMIC_GET(e.pos); + for (std::size_t i = 0; i < len; i++) + { + MBPoint& p = e.points[i]; + + // first stage is start time, skip + if (p.stage == 0) + continue; + + StatsMapPerStage::iterator s = stats.find(p.stage); + if (s == stats.end()) + stats[p.stage] = MBStatistics(p.time); + else + s->second.addSample(p.time); + } + + uint64_t smin = 0; + uint64_t smax = 0; + double srms = 0; + + for (StatsMapPerStage::iterator i = stats.begin(); + i != stats.end(); + i++) + { + smin += i->second.min; + smax += i->second.max; + double rrms = sqrt(i->second.rms/(double)i->second.count); + srms += rrms; + + o << "stage " << std::setw(4) << static_cast(i->first) + << ": min = " << std::setw(16) << i->second.min + << ", max = " << std::setw(16) << i->second.max + << ", rms = " << std::setw(16) << static_cast(rrms) << std::endl; + } + + o << std::string(82,'-') << std::endl; + + o << "stage " << std::setw(4) << "sum" + << ": min = " << std::setw(16) << smin + << ", max = " << std::setw(16) << smax + << ", rms = " << std::setw(16) << static_cast(srms) << std::endl; +} + +typedef std::vector EntitiesVector; + +static int nifty_counter; +static epicsMutex* MBMutex; + +// The counter is initialized at load-time, i.e., before any of the static objects are initialized. +MBMutexInitializer::MBMutexInitializer () +{ + if (0 == nifty_counter++) + { + // Initialize static members. + MBMutex = new epicsMutex(); + } +} + +MBMutexInitializer::~MBMutexInitializer () +{ + if (0 == --nifty_counter) + { + // Clean-up. + delete MBMutex; + } +} + +class MutexLock { +public: + + explicit MutexLock(epicsMutex &m) : + mutexPtr(m), + locked(true) + { + mutexPtr.lock(); + } + + ~MutexLock() + { + unlock(); + } + + void lock() + { + if (!locked) + { + mutexPtr.lock(); + locked = true; + } + } + void unlock() + { + if (locked) + { + mutexPtr.unlock(); + locked = false; + } + } + +private: + epicsMutex &mutexPtr; + bool locked; +}; + + +void MBEntityRegister(MBEntity *e) +{ + MutexLock lock(*MBMutex); + static EntitiesVector MBEntities; + + if (e) + { + MBEntities.push_back(e); + } + else + { + for(EntitiesVector::const_iterator i = MBEntities.begin(); + i != MBEntities.end(); + i++) + { + // skip empty entities + if ((*i)->pos) + { + char fileName[128]; + char* path = getenv("MB_OUTPUT_DIR"); + if (path == 0) path = const_cast("."); + snprintf(fileName, 128, "%s/mb_%s_%d.csv", path, (*i)->name.c_str(), getpid()); + std::ofstream out(fileName); + if (out.is_open()) + { + MBCSVExport(*(*i), out); + out.close(); + } + else + { + std::cerr << "failed to create a file " << fileName << ", skipping..." << std::endl; + } + } + } + } +} + +void MBAtExit() +{ + MBEntityRegister(0); +} + + +void MBInit() +{ + MutexLock lock(*MBMutex); + static bool inited = false; + if (!inited) + { + inited = true; + atexit(MBAtExit); + } +} + diff --git a/pvDataApp/mb/mb.h b/pvDataApp/mb/mb.h new file mode 100644 index 0000000..966e58f --- /dev/null +++ b/pvDataApp/mb/mb.h @@ -0,0 +1,130 @@ +#ifndef _MB_H_ +#define _MB_H_ + +#include +#include +#include + +#include + +#include + +#if EPICS_VERSION_INT >= VERSION_INT(3,15,0,0) +//#include +// epicsAtomic only support int and size_t type +// TODO fully fenced (not optimal) +#define ATOMIC_GET_AND_INCREMENT(VAR) __sync_fetch_and_add(&VAR, 1) +#define ATOMIC_SET_ZERO(VAR) __sync_fetch_and_and(&VAR, 0) +#define ATOMIC_GET(VAR) __sync_fetch_and_or(&VAR, 0) +#else +// try to get away with GCC internals, or build will simply fail +#define ATOMIC_GET_AND_INCREMENT(VAR) __sync_fetch_and_add(&VAR, 1) +#define ATOMIC_SET_ZERO(VAR) __sync_fetch_and_and(&VAR, 0) +#define ATOMIC_GET(VAR) __sync_fetch_and_or(&VAR, 0) +#endif + +static class MBMutexInitializer { + public: + MBMutexInitializer (); + ~MBMutexInitializer (); +} mbStaticMutexInitializer; // Note object here in the header. + +struct MBPoint +{ + intptr_t id; + uint8_t stage; + uint64_t time; + + MBPoint() {} + MBPoint(intptr_t _id, uint8_t _stage) : id(_id), stage(_stage) {} +}; + +struct MBEntity; + +extern void MBEntityRegister(MBEntity *e); + +typedef std::vector MBPointType; + +struct MBEntity +{ + std::string name; + MBPointType points; + volatile std::size_t pos; + volatile intptr_t auto_id; + + MBEntity(const std::string &name_, std::size_t size) : name(name_) + { + // init vector at the beginning + points.resize(size); + ATOMIC_SET_ZERO(pos); + ATOMIC_SET_ZERO(auto_id); + + MBEntityRegister(this); + } +}; + +extern uint64_t MBTime(); + +extern void MBPointAdd(MBEntity &e, intptr_t id, uint8_t stage); + +extern void MBCSVExport(MBEntity &e, std::ostream &o); +extern void MBCSVImport(MBEntity &e, std::istream &i); + +extern void MBStats(MBEntity &e, std::ostream &o); + +extern void MBNormalize(MBEntity &e); + + +extern void MBInit(); + +#if PV_MB + +#define MB_NAME(NAME) g_MB_##NAME + +#define MB_DECLARE(NAME, SIZE) MBEntity MB_NAME(NAME)(#NAME, SIZE) +#define MB_DECLARE_EXTERN(NAME) extern MBEntity MB_NAME(NAME) + +#define MB_POINT_ID(NAME, ID, STAGE) MBPointAdd(MB_NAME(NAME), ID, STAGE) + +#define MB_INC_AUTO_ID(NAME) ATOMIC_GET_AND_INCREMENT(MB_NAME(NAME).auto_id) +#define MB_POINT(NAME, STAGE) MBPointAdd(MB_NAME(NAME), MB_NAME(NAME).auto_id, STAGE) +#define MB_POINT_CONDITIONAL(NAME, STAGE, COND) if (COND) MBPointAdd(MB_NAME(NAME), MB_NAME(NAME).auto_id, STAGE) + +#define MB_NORMALIZE(NAME) MBNormalize(MB_NAME(NAME)) + +#define MB_STATS(NAME, STREAM) MBStats(MB_NAME(NAME), STREAM) + +#define MB_CSV_EXPORT(NAME, STREAM) MBCSVExport(MB_NAME(NAME), STREAM) +#define MB_CSV_IMPORT(NAME, STREAM) MBCSVImport(MB_NAME(NAME), STREAM) + +#define MB_PRINT(NAME, STREAM) MB_CSV_EXPORT(NAME, STREAM) + +#define MB_INIT MBInit() + + +#else + +#define MB_DECLARE(NAME, SIZE) +#define MB_DECLARE_EXTERN(NAME) + +#define MB_POINT_ID(NAME, ID, STAGE) + +#define MB_INC_AUTO_ID(NAME) +#define MB_POINT(NAME, STAGE) + +#define MB_POINT_CONDITIONAL(NAME, STAGE, COND) + +#define MB_NORMALIZE(NAME) + +#define MB_STATS(NAME, STREAM) + +#define MB_CSV_EXPORT(NAME, STREAM) +#define MB_CSV_IMPORT(NAME, STREAM) + +#define MB_PRINT(NAME, STREAM) + +#define MB_INIT + +#endif + +#endif diff --git a/pvDataApp/mb/mb_stat.cpp b/pvDataApp/mb/mb_stat.cpp new file mode 100644 index 0000000..e48fa8f --- /dev/null +++ b/pvDataApp/mb/mb_stat.cpp @@ -0,0 +1,50 @@ +#include +#include +#include "mb.h" +#include + +MB_DECLARE(e, 64000); + +// TODO command line options +int main(int argc, char** argv) +{ + // norm hack + bool normalizeOnly = false; + if (argc == 3 && strcmp(argv[2],"-n")==0) + { + argc = 2; + normalizeOnly = true; + } + + + if (argc != 2) + { + std::cerr << "usage: " << argv[0] << " " << std::endl; + return -1; + } + + char * fileName = argv[1]; + + std::ifstream in(fileName); + if (in.is_open()) + { + MB_CSV_IMPORT(e, in); + in.close(); + + if (normalizeOnly) + { + MB_NORMALIZE(e); + MB_PRINT(e, std::cout); + } + else + MB_STATS(e, std::cout); + } + else + { + std::cerr << "failed to open a file " << fileName << ", skipping..." << std::endl; + return -1; + } + + return 0; +} + diff --git a/testApp/Makefile b/testApp/Makefile index 2cb742e..f0afab6 100644 --- a/testApp/Makefile +++ b/testApp/Makefile @@ -5,5 +5,6 @@ DIRS += pv DIRS += property DIRS += monitor DIRS += capi +DIRS += mb include $(TOP)/configure/RULES_DIRS diff --git a/testApp/mb/Makefile b/testApp/mb/Makefile new file mode 100644 index 0000000..6fa2849 --- /dev/null +++ b/testApp/mb/Makefile @@ -0,0 +1,13 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG + +PROD_HOST += mb_test +mb_test_CXXFLAGS += -DPV_MB +mb_test_SRCS += mb_test.cpp +mb_test_LIBS += pvData Com + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/testApp/mb/README b/testApp/mb/README new file mode 100644 index 0000000..16586e9 --- /dev/null +++ b/testApp/mb/README @@ -0,0 +1,49 @@ +channelGet +0 - client channelGet->get() +1 - client channelGet->serialize (start) +2 - client channelGet->serialize (end) +3 - server channelGet->deserialize request (start) +4 - server channelGet->deserialize request (end) +5 - server channelGet->getDone() +6 - server channelGet->serialize response (start) +7 - server channelGet->serialize response (end) +8 - client channelGet->deserialize (start) +9 - client channelGet->deserialize (end), just before channelGet->getDone() is called + + + +MB_DECLARE_EXPORT(channelGet); + +# 10000 - max size +MB_DECLARE(channelGet, 10000); + +# in main() to install atexit() hook +MB_INIT; + +MB_INC_AUTO_ID(channelGet); +MB_POINT(channelGet, 0); +MB_POINT(channelGet, 1); +MB_POINT(channelGet, 2); + +MB_INC_AUTO_ID(channelGet); +MB_POINT(channelGet, 3); +MB_POINT(channelGet, 4); +MB_POINT(channelGet, 5); +MB_POINT(channelGet, 6); +MB_POINT(channelGet, 7); + +MB_POINT(channelGet, 8); +MB_POINT(channelGet, 9); + + +---- + + +cat mb* | sort < mb.csv +mb_stat mb.csv + + +mb_stat mb.csv -n | grep ,2, | cut -d , -f 3 | gnuplot -p -e "plot '-'" + + +--- diff --git a/testApp/mb/mb_test.cpp b/testApp/mb/mb_test.cpp new file mode 100644 index 0000000..64ab697 --- /dev/null +++ b/testApp/mb/mb_test.cpp @@ -0,0 +1,17 @@ +#include +#include + +MB_DECLARE_EXTERN(test); +MB_DECLARE(test, 1000); + +int main() +{ + MB_INIT; + + for (int i = 0; i < 10; i++) + for (int j = 0; j < 100; j++) + MB_POINT_ID(test, i, j); + + return 0; +} + From 246825d6728b37170741dcfbdc451b32e278741f Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Wed, 13 Feb 2013 14:29:38 +0100 Subject: [PATCH 5/9] base 3.14 fix --- pvDataApp/mb/mb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvDataApp/mb/mb.h b/pvDataApp/mb/mb.h index 966e58f..2e16f9b 100644 --- a/pvDataApp/mb/mb.h +++ b/pvDataApp/mb/mb.h @@ -9,7 +9,7 @@ #include -#if EPICS_VERSION_INT >= VERSION_INT(3,15,0,0) +#if 0 //(EPICS_VERSION_INT >= VERSION_INT(3,15,0,0)) //#include // epicsAtomic only support int and size_t type // TODO fully fenced (not optimal) From 675243061d77629e8efc69f04bd8b5e1a2275df1 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Sat, 16 Feb 2013 12:50:36 +0100 Subject: [PATCH 6/9] -Wextra compiler warnings fixed --- pvDataApp/factory/Convert.cpp | 2 +- pvDataApp/factory/FieldCreateFactory.cpp | 16 +++++----- pvDataApp/factory/PVDataCreateFactory.cpp | 30 +++++++++--------- pvDataApp/factory/PVStructureArray.cpp | 12 +++---- pvDataApp/misc/bitSet.cpp | 2 +- pvDataApp/misc/serializeHelper.cpp | 8 ++--- pvDataApp/misc/status.cpp | 2 +- testApp/misc/testBaseException.cpp | 4 +-- testApp/misc/testMessageQueue.cpp | 2 +- testApp/misc/testSerialization.cpp | 38 ++++++++++++----------- testApp/monitor/testMonitor.cpp | 4 +-- testApp/property/testProperty.cpp | 12 +++---- testApp/pv/testPVData.cpp | 6 ++-- testApp/pv/testStandardField.cpp | 2 +- testApp/pv/testStandardPVField.cpp | 2 +- 15 files changed, 72 insertions(+), 70 deletions(-) diff --git a/pvDataApp/factory/Convert.cpp b/pvDataApp/factory/Convert.cpp index e24c5b6..40aa52a 100644 --- a/pvDataApp/factory/Convert.cpp +++ b/pvDataApp/factory/Convert.cpp @@ -2721,7 +2721,7 @@ void convertStructure(StringBuilder buffer,PVStructure const *data,int indentLev } } -void convertArray(StringBuilder buffer,PVScalarArray const * xxx,int indentLevel) +void convertArray(StringBuilder buffer,PVScalarArray const * xxx,int /*indentLevel*/) { PVScalarArray *pv = const_cast(xxx); ScalarArrayConstPtr array = pv->getScalarArray(); diff --git a/pvDataApp/factory/FieldCreateFactory.cpp b/pvDataApp/factory/FieldCreateFactory.cpp index 108b12f..c3eee33 100644 --- a/pvDataApp/factory/FieldCreateFactory.cpp +++ b/pvDataApp/factory/FieldCreateFactory.cpp @@ -39,7 +39,7 @@ Field::~Field() { } -void Field::toString(StringBuilder buffer,int indentLevel) const{ +void Field::toString(StringBuilder /*buffer*/,int /*indentLevel*/) const{ } @@ -54,7 +54,7 @@ struct ScalarArrayHashFunction { }; struct StructureHashFunction { - size_t operator() (const Structure& structure) const { return 0; } + size_t operator() (const Structure& /*structure*/) const { return 0; } // TODO // final int PRIME = 31; // return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields); @@ -70,7 +70,7 @@ Scalar::Scalar(ScalarType scalarType) Scalar::~Scalar(){} -void Scalar::toString(StringBuilder buffer,int indentLevel) const{ +void Scalar::toString(StringBuilder buffer,int /*indentLevel*/) const{ *buffer += getID(); } @@ -119,7 +119,7 @@ void Scalar::serialize(ByteBuffer *buffer, SerializableControl *control) const { buffer->putByte(getTypeCodeLUT()); } -void Scalar::deserialize(ByteBuffer *buffer, DeserializableControl *control) { +void Scalar::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) { // must be done via FieldCreate throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } @@ -213,7 +213,7 @@ String ScalarArray::getID() const return getIDScalarArrayLUT(); } -void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{ +void ScalarArray::toString(StringBuilder buffer,int /*indentLevel*/) const{ *buffer += getID(); } @@ -222,7 +222,7 @@ void ScalarArray::serialize(ByteBuffer *buffer, SerializableControl *control) co buffer->putByte(0x10 | getTypeCodeLUT()); } -void ScalarArray::deserialize(ByteBuffer *buffer, DeserializableControl *control) { +void ScalarArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) { throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } @@ -252,7 +252,7 @@ void StructureArray::serialize(ByteBuffer *buffer, SerializableControl *control) control->cachedSerialize(pstructure, buffer); } -void StructureArray::deserialize(ByteBuffer *buffer, DeserializableControl *control) { +void StructureArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) { throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } @@ -357,7 +357,7 @@ void Structure::serialize(ByteBuffer *buffer, SerializableControl *control) cons serializeStructureField(this, buffer, control); } -void Structure::deserialize(ByteBuffer *buffer, DeserializableControl *control) { +void Structure::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) { throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead"); } diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index 95de04f..f18dfbe 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -147,9 +147,9 @@ void BasePVString::serialize(ByteBuffer *pbuffer, { // check bounds const size_t length = /*(value == null) ? 0 :*/ value.length(); - if (offset < 0) offset = 0; - else if (offset > length) offset = length; - if (count < 0) count = length; + /*if (offset < 0) offset = 0; + else*/ if (offset > length) offset = length; + //if (count < 0) count = length; const size_t maxCount = length - offset; if (count > maxCount) @@ -271,7 +271,7 @@ size_t DefaultPVArray::get(size_t offset, size_t len, PVArrayData &data) size_t length = this->getLength(); if(offset+len > length) { n = length-offset; - if(n<0) n = 0; + //if(n<0) n = 0; } data.data = *value.get(); data.offset = offset; @@ -331,8 +331,8 @@ template void DefaultPVArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { size_t size = SerializeHelper::readSize(pbuffer, pcontrol); - // if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); } - if(size>=0) { + // alignment if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); } + //if(size>=0) { // prepare array, if necessary if(size>this->getCapacity()) this->setCapacity(size); // set new length @@ -356,7 +356,7 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, } // inform about the change? PVField::postPut(); - } + //} // TODO null arrays (size == -1) not supported } @@ -367,10 +367,10 @@ void DefaultPVArray::serialize(ByteBuffer *pbuffer, size_t length = this->getLength(); // check bounds - if(offset<0) + /*if(offset<0) offset = 0; - else if(offset>length) offset = length; - if(count<0) count = length; + else*/ if(offset>length) offset = length; + //if(count<0) count = length; size_t maxCount = length-offset; if(count>maxCount) count = maxCount; @@ -406,7 +406,7 @@ template<> void DefaultPVArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { size_t size = SerializeHelper::readSize(pbuffer, pcontrol); - if(size>=0) { + //if(size>=0) { // prepare array, if necessary if(size>getCapacity()) setCapacity(size); // set new length @@ -419,7 +419,7 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, } // inform about the change? postPut(); - } + //} // TODO null arrays (size == -1) not supported } @@ -429,10 +429,10 @@ void DefaultPVArray::serialize(ByteBuffer *pbuffer, size_t length = getLength(); // check bounds - if(offset<0) + /*if(offset<0) offset = 0; - else if(offset>length) offset = length; - if(count<0) count = length; + else*/ if(offset>length) offset = length; + //if(count<0) count = length; size_t maxCount = length-offset; if(count>maxCount) count = maxCount; diff --git a/pvDataApp/factory/PVStructureArray.cpp b/pvDataApp/factory/PVStructureArray.cpp index b6cba3f..d08b6a4 100644 --- a/pvDataApp/factory/PVStructureArray.cpp +++ b/pvDataApp/factory/PVStructureArray.cpp @@ -133,7 +133,7 @@ size_t PVStructureArray::get( size_t length = getLength(); if(offset+len > length) { n = length - offset; - if(n<0) n = 0; + //if(n<0) n = 0; } data.data = *value.get(); data.offset = offset; @@ -197,7 +197,7 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer, void PVStructureArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { size_t size = SerializeHelper::readSize(pbuffer, pcontrol); - if(size>=0) { + //if(size>=0) { // prepare array, if necessary if(size>getCapacity()) setCapacity(size); setLength(size); @@ -217,7 +217,7 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer, } } postPut(); - } + //} } void PVStructureArray::serialize(ByteBuffer *pbuffer, @@ -226,10 +226,10 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer, size_t length = getLength(); // check bounds - if(offset<0) + /*if(offset<0) offset = 0; - else if(offset>length) offset = length; - if(count<0) count = length; + else*/ if(offset>length) offset = length; + //if(count<0) count = length; size_t maxCount = length-offset; if(count>maxCount) count = maxCount; diff --git a/pvDataApp/misc/bitSet.cpp b/pvDataApp/misc/bitSet.cpp index 4576ddb..bccb391 100644 --- a/pvDataApp/misc/bitSet.cpp +++ b/pvDataApp/misc/bitSet.cpp @@ -331,7 +331,7 @@ namespace epics { namespace pvData { return !(*this == set); } - void BitSet::toString(StringBuilder buffer, int indentLevel) const + void BitSet::toString(StringBuilder buffer, int /*indentLevel*/) const { *buffer += '{'; int32 i = nextSetBit(0); diff --git a/pvDataApp/misc/serializeHelper.cpp b/pvDataApp/misc/serializeHelper.cpp index d067765..75804ea 100644 --- a/pvDataApp/misc/serializeHelper.cpp +++ b/pvDataApp/misc/serializeHelper.cpp @@ -77,14 +77,14 @@ namespace epics { void SerializeHelper::serializeSubstring(const String& value, std::size_t offset, std::size_t count, ByteBuffer* buffer, SerializableControl* flusher) { - if(offset<0) + /*if(offset<0) offset = 0; - else if(offset>(std::size_t)value.length()) offset = value.length(); + else*/ if(offset>value.length()) offset = value.length(); - if(offset+count>(std::size_t)value.length()) count = value.length()-offset; + if(offset+count>value.length()) count = value.length()-offset; SerializeHelper::writeSize(count, buffer, flusher); - if (count<=0) return; + /*if (count<=0)*/ return; std::size_t i = 0; while(true) { std::size_t maxToWrite = min(count-i, buffer->getRemaining()); diff --git a/pvDataApp/misc/status.cpp b/pvDataApp/misc/status.cpp index 789b03b..2ddc4fe 100644 --- a/pvDataApp/misc/status.cpp +++ b/pvDataApp/misc/status.cpp @@ -117,7 +117,7 @@ String Status::toString() const return str; } -void Status::toString(StringBuilder buffer, int indentLevel) const +void Status::toString(StringBuilder buffer, int /*indentLevel*/) const { *buffer += "Status [type="; *buffer += StatusTypeName[m_statusType]; diff --git a/testApp/misc/testBaseException.cpp b/testApp/misc/testBaseException.cpp index cf9cd49..2a00995 100644 --- a/testApp/misc/testBaseException.cpp +++ b/testApp/misc/testBaseException.cpp @@ -27,11 +27,11 @@ struct Unroller }; template<> -void Unroller::unroll<0>(double d) { +void Unroller::unroll<0>(double /*d*/) { THROW_BASE_EXCEPTION("the root cause"); } -void internalTestBaseException(int unused = 0) +void internalTestBaseException(int /*unused*/ = 0) { try { // NOTE: 5, 4, 3, 2, 1 calls will be optimized and not shown diff --git a/testApp/misc/testMessageQueue.cpp b/testApp/misc/testMessageQueue.cpp index 67ce0a5..dac867b 100644 --- a/testApp/misc/testMessageQueue.cpp +++ b/testApp/misc/testMessageQueue.cpp @@ -30,7 +30,7 @@ using namespace epics::pvData; -static void testBasic(FILE * fd,FILE *auxfd ) { +static void testBasic(FILE * fd,FILE */*auxfd*/) { int queueSize = 3; StringArray messages; messages.reserve(5); diff --git a/testApp/misc/testSerialization.cpp b/testApp/misc/testSerialization.cpp index 41045f0..238bd7f 100644 --- a/testApp/misc/testSerialization.cpp +++ b/testApp/misc/testSerialization.cpp @@ -24,22 +24,24 @@ #include -#define BYTE_MAX_VALUE 127 -#define BYTE_MIN_VALUE -128 -#define UBYTE_MAX_VALUE 255 -#define SHORT_MAX_VALUE 32767 -#define SHORT_MIN_VALUE -32768 -#define USHORT_MAX_VALUE 65535 -#define INT_MAX_VALUE 2147483647 -#define INT_MIN_VALUE (-INT_MAX_VALUE - 1) -#define UINT_MAX_VALUE 4294967295ULL -#define LONG_MAX_VALUE 9223372036854775807LL -#define LONG_MIN_VALUE (-LONG_MAX_VALUE - 1LL) -#define ULONG_MAX_VALUE 18446744073709549999ULL -#define FLOAT_MAX_VALUE 3.4028235E38 -#define FLOAT_MIN_VALUE 1.4E-45 -#define DOUBLE_MAX_VALUE 1.7976931348623157E308 -#define DOUBLE_MIN_VALUE 4.9E-324 +#include + +#define BYTE_MAX_VALUE std::numeric_limits::max() +#define BYTE_MIN_VALUE std::numeric_limits::min() +#define UBYTE_MAX_VALUE std::numeric_limits::max() +#define SHORT_MAX_VALUE std::numeric_limits::max() +#define SHORT_MIN_VALUE std::numeric_limits::min() +#define USHORT_MAX_VALUE std::numeric_limits::max() +#define INT_MAX_VALUE std::numeric_limits::max() +#define INT_MIN_VALUE std::numeric_limits::min() +#define UINT_MAX_VALUE std::numeric_limits::max() +#define LONG_MAX_VALUE std::numeric_limits::max() +#define LONG_MIN_VALUE std::numeric_limits::min() +#define ULONG_MAX_VALUE std::numeric_limits::max() +#define FLOAT_MAX_VALUE std::numeric_limits::max() +#define FLOAT_MIN_VALUE std::numeric_limits::min() +#define DOUBLE_MAX_VALUE std::numeric_limits::max() +#define DOUBLE_MIN_VALUE std::numeric_limits::min() using namespace epics::pvData; @@ -54,7 +56,7 @@ public: virtual void flushSerializeBuffer() { } - virtual void ensureBuffer(std::size_t size) { + virtual void ensureBuffer(std::size_t /*size*/) { } virtual void alignBuffer(std::size_t alignment) { @@ -76,7 +78,7 @@ public: class DeserializableControlImpl : public DeserializableControl, public NoDefaultMethods { public: - virtual void ensureData(size_t size) { + virtual void ensureData(size_t /*size*/) { } virtual void alignData(size_t alignment) { diff --git a/testApp/monitor/testMonitor.cpp b/testApp/monitor/testMonitor.cpp index f5adfa3..ce33e7a 100644 --- a/testApp/monitor/testMonitor.cpp +++ b/testApp/monitor/testMonitor.cpp @@ -50,7 +50,7 @@ public: printf("poll called\n"); return emptyElement; } - virtual void release(MonitorElementPtr const & monitorElement) + virtual void release(MonitorElementPtr const & /*monitorElement*/) { printf("release called\n"); } @@ -70,7 +70,7 @@ static void testMonitor() } -int main(int argc,char *argv[]) +int main(int, char **) { testMonitor(); return(0); diff --git a/testApp/property/testProperty.cpp b/testApp/property/testProperty.cpp index 23eb465..923276c 100644 --- a/testApp/property/testProperty.cpp +++ b/testApp/property/testProperty.cpp @@ -48,7 +48,7 @@ static String allProperties("alarm,timeStamp,display,control"); static PVStructurePtr doubleRecord; static PVStructurePtr enumeratedRecord; -static void createRecords(FILE * fd,FILE *auxfd) +static void createRecords(FILE * fd,FILE */*auxfd*/) { doubleRecord = standardPVField->scalar(pvDouble,allProperties); if(debug) { @@ -70,7 +70,7 @@ static void createRecords(FILE * fd,FILE *auxfd) } } -static void printRecords(FILE * fd,FILE *auxfd) +static void printRecords(FILE * fd,FILE */*auxfd*/) { fprintf(fd,"doubleRecord\n"); builder.clear(); @@ -82,7 +82,7 @@ static void printRecords(FILE * fd,FILE *auxfd) fprintf(fd,"%s\n",builder.c_str()); } -static void testAlarm(FILE * fd,FILE *auxfd) +static void testAlarm(FILE * fd,FILE */*auxfd*/) { if(debug) fprintf(fd,"testAlarm\n"); Alarm alarm; @@ -155,7 +155,7 @@ static void testTimeStamp(FILE * fd,FILE *auxfd) fprintf(fd,"testTimeStamp PASSED\n"); } -static void testControl(FILE * fd,FILE *auxfd) +static void testControl(FILE * fd,FILE */*auxfd*/) { if(debug) fprintf(fd,"testControl\n"); Control control; @@ -182,7 +182,7 @@ static void testControl(FILE * fd,FILE *auxfd) fprintf(fd,"testControl PASSED\n"); } -static void testDisplay(FILE * fd,FILE *auxfd) +static void testDisplay(FILE * fd,FILE */*auxfd*/) { if(debug) fprintf(fd,"testDisplay\n"); Display display; @@ -215,7 +215,7 @@ static void testDisplay(FILE * fd,FILE *auxfd) fprintf(fd,"testDisplay PASSED\n"); } -static void testEnumerated(FILE * fd,FILE *auxfd) +static void testEnumerated(FILE * fd,FILE */*auxfd*/) { if(debug) fprintf(fd,"testEnumerated\n"); PVEnumerated pvEnumerated; diff --git a/testApp/pv/testPVData.cpp b/testApp/pv/testPVData.cpp index bb60a2a..71654da 100644 --- a/testApp/pv/testPVData.cpp +++ b/testApp/pv/testPVData.cpp @@ -77,7 +77,7 @@ static void testCreatePVStructure(FILE * fd) fprintf(fd,"testCreatePVStructure PASSED\n"); } -static void testPVScalarCommon(FILE * fd,String fieldName,ScalarType stype) +static void testPVScalarCommon(FILE * fd,String /*fieldName*/,ScalarType stype) { PVScalarPtr pvScalar = pvDataCreate->createPVScalar(stype); if(stype==pvBoolean) { @@ -91,7 +91,7 @@ static void testPVScalarCommon(FILE * fd,String fieldName,ScalarType stype) } static void testPVScalarWithProperties( - FILE * fd,String fieldName,ScalarType stype) + FILE * fd,String /*fieldName*/,ScalarType stype) { PVStructurePtr pvStructure; bool hasValueAlarm = false; @@ -335,7 +335,7 @@ static void testPVScalar(FILE * fd) { } -static void testScalarArrayCommon(FILE * fd,String fieldName,ScalarType stype) +static void testScalarArrayCommon(FILE * fd,String /*fieldName*/,ScalarType stype) { PVStructurePtr pvStructure = standardPVField->scalarArray( stype,alarmTimeStamp); diff --git a/testApp/pv/testStandardField.cpp b/testApp/pv/testStandardField.cpp index efae647..661caa1 100644 --- a/testApp/pv/testStandardField.cpp +++ b/testApp/pv/testStandardField.cpp @@ -35,7 +35,7 @@ static void print(String name) if(debug) printf("\n%s\n%s\n",name.c_str(),builder.c_str()); } -int main(int argc,char *argv[]) +int main(int, char **) { StructureConstPtr doubleValue = standardField->scalar(pvDouble, "alarm,timeStamp,display,control,valueAlarm"); diff --git a/testApp/pv/testStandardPVField.cpp b/testApp/pv/testStandardPVField.cpp index 675cf15..7c19ccd 100644 --- a/testApp/pv/testStandardPVField.cpp +++ b/testApp/pv/testStandardPVField.cpp @@ -37,7 +37,7 @@ static void print(String name) if(debug) printf("\n%s\n%s\n",name.c_str(),builder.c_str()); } -int main(int argc,char *argv[]) +int main(int, char **) { PVStructurePtr pvStructure = standardPVField->scalar(pvDouble, "alarm,timeStamp,display,control,valueAlarm"); From 5e810c704fec31e338a385df5deddb5bf94293fc Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Thu, 21 Feb 2013 15:50:57 +0100 Subject: [PATCH 7/9] Missing library reference in Makefile --- testApp/misc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testApp/misc/Makefile b/testApp/misc/Makefile index 3b66c17..077f4eb 100644 --- a/testApp/misc/Makefile +++ b/testApp/misc/Makefile @@ -24,7 +24,7 @@ testByteBuffer_LIBS += pvData Com PROD_HOST += testBaseException testBaseException_SRCS += testBaseException.cpp -testBaseException_LIBS += pvData +testBaseException_LIBS += pvData Com PROD_HOST += testSerialization testSerialization_SRCS += testSerialization.cpp From 959117c39149faa675dd08b6feb89d03587ccc8e Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Fri, 22 Feb 2013 21:27:26 +0100 Subject: [PATCH 8/9] mb portability, still to be ported to boost atomic --- pvDataApp/mb/mb.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pvDataApp/mb/mb.cpp b/pvDataApp/mb/mb.cpp index b443e78..879a391 100644 --- a/pvDataApp/mb/mb.cpp +++ b/pvDataApp/mb/mb.cpp @@ -4,7 +4,7 @@ #include #include #include - +#include #include #include #include @@ -28,7 +28,11 @@ uint64_t MBTime() } #endif - +#ifdef vxWorks +#define GETPID() taskIdSelf() +#else +#define GETPID() getpid() +#endif void MBPointAdd(MBEntity &e, intptr_t id, uint8_t stage) { // no copy and no MBPoint init solution @@ -106,12 +110,12 @@ struct MBStatistics std::size_t count; uint64_t min; uint64_t max; - uint64_t rms; + double rms; MBStatistics() : count(0), - min(-1), - max(0), + min(std::numeric_limits::max()), + max(std::numeric_limits::min()), rms(0.0) {} @@ -263,10 +267,11 @@ void MBEntityRegister(MBEntity *e) // skip empty entities if ((*i)->pos) { - char fileName[128]; + char fileName[1024]; char* path = getenv("MB_OUTPUT_DIR"); if (path == 0) path = const_cast("."); - snprintf(fileName, 128, "%s/mb_%s_%d.csv", path, (*i)->name.c_str(), getpid()); + // NOTE: snprintf not used because of older VxWorks + sprintf(fileName, "%s/mb_%s_%d.csv", path, (*i)->name.c_str(), GETPID()); std::ofstream out(fileName); if (out.is_open()) { From 67afe84593bf0749c4b24320109d35afe578ed27 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Mon, 25 Feb 2013 10:29:34 +0100 Subject: [PATCH 9/9] mb moved to pvCommonCPP --- pvDataApp/Makefile | 9 -- pvDataApp/mb/mb.cpp | 306 --------------------------------------- pvDataApp/mb/mb.h | 130 ----------------- pvDataApp/mb/mb_stat.cpp | 50 ------- testApp/Makefile | 1 - testApp/mb/Makefile | 13 -- testApp/mb/README | 49 ------- testApp/mb/mb_test.cpp | 17 --- 8 files changed, 575 deletions(-) delete mode 100644 pvDataApp/mb/mb.cpp delete mode 100644 pvDataApp/mb/mb.h delete mode 100644 pvDataApp/mb/mb_stat.cpp delete mode 100644 testApp/mb/Makefile delete mode 100644 testApp/mb/README delete mode 100644 testApp/mb/mb_test.cpp diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index 992c394..0acf9b9 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -92,15 +92,6 @@ LIBSRCS += bitSetUtil.cpp SRC_DIRS += $(PVDATA)/monitor INC += monitor.h -SRC_DIRS += $(PVDATA)/mb -INC += mb.h -LIBSRCS += mb.cpp - -PROD_HOST += mb_stat -mb_stat_CXXFLAGS += -DPV_MB -mb_stat_SRCS += mb_stat.cpp -mb_stat_LIBS += pvData Com - LIBRARY = pvData pvData_LIBS += Com diff --git a/pvDataApp/mb/mb.cpp b/pvDataApp/mb/mb.cpp deleted file mode 100644 index 879a391..0000000 --- a/pvDataApp/mb/mb.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#include "mb.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#if defined(__APPLE__) -#include -uint64_t MBTime() -{ - return mach_absolute_time(); -} -#else -uint64_t MBTime() -{ - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - return static_cast(ts.tv_sec) * 1000000000 + static_cast(ts.tv_nsec); -} -#endif - -#ifdef vxWorks -#define GETPID() taskIdSelf() -#else -#define GETPID() getpid() -#endif -void MBPointAdd(MBEntity &e, intptr_t id, uint8_t stage) -{ - // no copy and no MBPoint init solution - const std::size_t ix = ATOMIC_GET_AND_INCREMENT(e.pos); - MBPoint& p = e.points[ix]; - p.id = id; p.stage = stage; - p.time = MBTime(); -} - -void MBCSVExport(MBEntity &e, std::ostream &o) -{ - const std::size_t len = ATOMIC_GET(e.pos); - for (std::size_t i = 0; i < len; i++) - { - MBPoint& p = e.points[i]; - o << p.id << ',' << static_cast(p.stage) << ',' << p.time << std::endl; - } -} - -// NOTE: this method is not thread-safe -void MBCSVImport(MBEntity &e, std::istream &i) -{ - std::string line; - char c; - - e.points.resize(0); - size_t lc = 0; - while (getline(i,line)) - { - lc++; - std::istringstream is(line); - MBPoint p; - is >> p.id >> c; - uint32_t s; is >> s >> c; p.stage = s; - is >> p.time; - - if (is.good() || is.eof()) - e.points.push_back(p); - else - { - std::cerr << "failed to parse line " << lc << ": \"" << line << "\"" << std::endl; - } - } - e.pos = e.points.size(); -} - -void MBNormalize(MBEntity &e) -{ - std::map lastTime; - - const std::size_t len = ATOMIC_GET(e.pos); - for (std::size_t i = 0; i < len; i++) - { - MBPoint& p = e.points[i]; - if (p.stage == 0) - lastTime[p.id] = p.time; - - std::map::iterator last = lastTime.find(p.id); - if (last == lastTime.end()) - { - std::cerr << "no 0 stage for " << e.name << ", id = " << p.id << std::endl; - p.time = -1; // TODO error?! - } - else - { - uint64_t lt = last->second; - last->second = p.time; - p.time -= lt; - } - } -} - -struct MBStatistics -{ - std::size_t count; - uint64_t min; - uint64_t max; - double rms; - - MBStatistics() : - count(0), - min(std::numeric_limits::max()), - max(std::numeric_limits::min()), - rms(0.0) - {} - - MBStatistics(uint64_t sample) : - count(1), - min(sample), - max(sample), - rms(sample*sample) - { - }; - - void addSample(uint64_t sample) - { - count++; - if (sample < min) min = sample; - if (sample > max) max = sample; - rms += sample*sample; - }; -}; - -typedef std::map StatsMapPerStage; - -void MBStats(MBEntity &e, std::ostream &o) -{ - MBNormalize(e); - - StatsMapPerStage stats; - - const std::size_t len = ATOMIC_GET(e.pos); - for (std::size_t i = 0; i < len; i++) - { - MBPoint& p = e.points[i]; - - // first stage is start time, skip - if (p.stage == 0) - continue; - - StatsMapPerStage::iterator s = stats.find(p.stage); - if (s == stats.end()) - stats[p.stage] = MBStatistics(p.time); - else - s->second.addSample(p.time); - } - - uint64_t smin = 0; - uint64_t smax = 0; - double srms = 0; - - for (StatsMapPerStage::iterator i = stats.begin(); - i != stats.end(); - i++) - { - smin += i->second.min; - smax += i->second.max; - double rrms = sqrt(i->second.rms/(double)i->second.count); - srms += rrms; - - o << "stage " << std::setw(4) << static_cast(i->first) - << ": min = " << std::setw(16) << i->second.min - << ", max = " << std::setw(16) << i->second.max - << ", rms = " << std::setw(16) << static_cast(rrms) << std::endl; - } - - o << std::string(82,'-') << std::endl; - - o << "stage " << std::setw(4) << "sum" - << ": min = " << std::setw(16) << smin - << ", max = " << std::setw(16) << smax - << ", rms = " << std::setw(16) << static_cast(srms) << std::endl; -} - -typedef std::vector EntitiesVector; - -static int nifty_counter; -static epicsMutex* MBMutex; - -// The counter is initialized at load-time, i.e., before any of the static objects are initialized. -MBMutexInitializer::MBMutexInitializer () -{ - if (0 == nifty_counter++) - { - // Initialize static members. - MBMutex = new epicsMutex(); - } -} - -MBMutexInitializer::~MBMutexInitializer () -{ - if (0 == --nifty_counter) - { - // Clean-up. - delete MBMutex; - } -} - -class MutexLock { -public: - - explicit MutexLock(epicsMutex &m) : - mutexPtr(m), - locked(true) - { - mutexPtr.lock(); - } - - ~MutexLock() - { - unlock(); - } - - void lock() - { - if (!locked) - { - mutexPtr.lock(); - locked = true; - } - } - void unlock() - { - if (locked) - { - mutexPtr.unlock(); - locked = false; - } - } - -private: - epicsMutex &mutexPtr; - bool locked; -}; - - -void MBEntityRegister(MBEntity *e) -{ - MutexLock lock(*MBMutex); - static EntitiesVector MBEntities; - - if (e) - { - MBEntities.push_back(e); - } - else - { - for(EntitiesVector::const_iterator i = MBEntities.begin(); - i != MBEntities.end(); - i++) - { - // skip empty entities - if ((*i)->pos) - { - char fileName[1024]; - char* path = getenv("MB_OUTPUT_DIR"); - if (path == 0) path = const_cast("."); - // NOTE: snprintf not used because of older VxWorks - sprintf(fileName, "%s/mb_%s_%d.csv", path, (*i)->name.c_str(), GETPID()); - std::ofstream out(fileName); - if (out.is_open()) - { - MBCSVExport(*(*i), out); - out.close(); - } - else - { - std::cerr << "failed to create a file " << fileName << ", skipping..." << std::endl; - } - } - } - } -} - -void MBAtExit() -{ - MBEntityRegister(0); -} - - -void MBInit() -{ - MutexLock lock(*MBMutex); - static bool inited = false; - if (!inited) - { - inited = true; - atexit(MBAtExit); - } -} - diff --git a/pvDataApp/mb/mb.h b/pvDataApp/mb/mb.h deleted file mode 100644 index 2e16f9b..0000000 --- a/pvDataApp/mb/mb.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _MB_H_ -#define _MB_H_ - -#include -#include -#include - -#include - -#include - -#if 0 //(EPICS_VERSION_INT >= VERSION_INT(3,15,0,0)) -//#include -// epicsAtomic only support int and size_t type -// TODO fully fenced (not optimal) -#define ATOMIC_GET_AND_INCREMENT(VAR) __sync_fetch_and_add(&VAR, 1) -#define ATOMIC_SET_ZERO(VAR) __sync_fetch_and_and(&VAR, 0) -#define ATOMIC_GET(VAR) __sync_fetch_and_or(&VAR, 0) -#else -// try to get away with GCC internals, or build will simply fail -#define ATOMIC_GET_AND_INCREMENT(VAR) __sync_fetch_and_add(&VAR, 1) -#define ATOMIC_SET_ZERO(VAR) __sync_fetch_and_and(&VAR, 0) -#define ATOMIC_GET(VAR) __sync_fetch_and_or(&VAR, 0) -#endif - -static class MBMutexInitializer { - public: - MBMutexInitializer (); - ~MBMutexInitializer (); -} mbStaticMutexInitializer; // Note object here in the header. - -struct MBPoint -{ - intptr_t id; - uint8_t stage; - uint64_t time; - - MBPoint() {} - MBPoint(intptr_t _id, uint8_t _stage) : id(_id), stage(_stage) {} -}; - -struct MBEntity; - -extern void MBEntityRegister(MBEntity *e); - -typedef std::vector MBPointType; - -struct MBEntity -{ - std::string name; - MBPointType points; - volatile std::size_t pos; - volatile intptr_t auto_id; - - MBEntity(const std::string &name_, std::size_t size) : name(name_) - { - // init vector at the beginning - points.resize(size); - ATOMIC_SET_ZERO(pos); - ATOMIC_SET_ZERO(auto_id); - - MBEntityRegister(this); - } -}; - -extern uint64_t MBTime(); - -extern void MBPointAdd(MBEntity &e, intptr_t id, uint8_t stage); - -extern void MBCSVExport(MBEntity &e, std::ostream &o); -extern void MBCSVImport(MBEntity &e, std::istream &i); - -extern void MBStats(MBEntity &e, std::ostream &o); - -extern void MBNormalize(MBEntity &e); - - -extern void MBInit(); - -#if PV_MB - -#define MB_NAME(NAME) g_MB_##NAME - -#define MB_DECLARE(NAME, SIZE) MBEntity MB_NAME(NAME)(#NAME, SIZE) -#define MB_DECLARE_EXTERN(NAME) extern MBEntity MB_NAME(NAME) - -#define MB_POINT_ID(NAME, ID, STAGE) MBPointAdd(MB_NAME(NAME), ID, STAGE) - -#define MB_INC_AUTO_ID(NAME) ATOMIC_GET_AND_INCREMENT(MB_NAME(NAME).auto_id) -#define MB_POINT(NAME, STAGE) MBPointAdd(MB_NAME(NAME), MB_NAME(NAME).auto_id, STAGE) -#define MB_POINT_CONDITIONAL(NAME, STAGE, COND) if (COND) MBPointAdd(MB_NAME(NAME), MB_NAME(NAME).auto_id, STAGE) - -#define MB_NORMALIZE(NAME) MBNormalize(MB_NAME(NAME)) - -#define MB_STATS(NAME, STREAM) MBStats(MB_NAME(NAME), STREAM) - -#define MB_CSV_EXPORT(NAME, STREAM) MBCSVExport(MB_NAME(NAME), STREAM) -#define MB_CSV_IMPORT(NAME, STREAM) MBCSVImport(MB_NAME(NAME), STREAM) - -#define MB_PRINT(NAME, STREAM) MB_CSV_EXPORT(NAME, STREAM) - -#define MB_INIT MBInit() - - -#else - -#define MB_DECLARE(NAME, SIZE) -#define MB_DECLARE_EXTERN(NAME) - -#define MB_POINT_ID(NAME, ID, STAGE) - -#define MB_INC_AUTO_ID(NAME) -#define MB_POINT(NAME, STAGE) - -#define MB_POINT_CONDITIONAL(NAME, STAGE, COND) - -#define MB_NORMALIZE(NAME) - -#define MB_STATS(NAME, STREAM) - -#define MB_CSV_EXPORT(NAME, STREAM) -#define MB_CSV_IMPORT(NAME, STREAM) - -#define MB_PRINT(NAME, STREAM) - -#define MB_INIT - -#endif - -#endif diff --git a/pvDataApp/mb/mb_stat.cpp b/pvDataApp/mb/mb_stat.cpp deleted file mode 100644 index e48fa8f..0000000 --- a/pvDataApp/mb/mb_stat.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include "mb.h" -#include - -MB_DECLARE(e, 64000); - -// TODO command line options -int main(int argc, char** argv) -{ - // norm hack - bool normalizeOnly = false; - if (argc == 3 && strcmp(argv[2],"-n")==0) - { - argc = 2; - normalizeOnly = true; - } - - - if (argc != 2) - { - std::cerr << "usage: " << argv[0] << " " << std::endl; - return -1; - } - - char * fileName = argv[1]; - - std::ifstream in(fileName); - if (in.is_open()) - { - MB_CSV_IMPORT(e, in); - in.close(); - - if (normalizeOnly) - { - MB_NORMALIZE(e); - MB_PRINT(e, std::cout); - } - else - MB_STATS(e, std::cout); - } - else - { - std::cerr << "failed to open a file " << fileName << ", skipping..." << std::endl; - return -1; - } - - return 0; -} - diff --git a/testApp/Makefile b/testApp/Makefile index f0afab6..2cb742e 100644 --- a/testApp/Makefile +++ b/testApp/Makefile @@ -5,6 +5,5 @@ DIRS += pv DIRS += property DIRS += monitor DIRS += capi -DIRS += mb include $(TOP)/configure/RULES_DIRS diff --git a/testApp/mb/Makefile b/testApp/mb/Makefile deleted file mode 100644 index 6fa2849..0000000 --- a/testApp/mb/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -TOP=../.. - -include $(TOP)/configure/CONFIG - -PROD_HOST += mb_test -mb_test_CXXFLAGS += -DPV_MB -mb_test_SRCS += mb_test.cpp -mb_test_LIBS += pvData Com - -include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE - diff --git a/testApp/mb/README b/testApp/mb/README deleted file mode 100644 index 16586e9..0000000 --- a/testApp/mb/README +++ /dev/null @@ -1,49 +0,0 @@ -channelGet -0 - client channelGet->get() -1 - client channelGet->serialize (start) -2 - client channelGet->serialize (end) -3 - server channelGet->deserialize request (start) -4 - server channelGet->deserialize request (end) -5 - server channelGet->getDone() -6 - server channelGet->serialize response (start) -7 - server channelGet->serialize response (end) -8 - client channelGet->deserialize (start) -9 - client channelGet->deserialize (end), just before channelGet->getDone() is called - - - -MB_DECLARE_EXPORT(channelGet); - -# 10000 - max size -MB_DECLARE(channelGet, 10000); - -# in main() to install atexit() hook -MB_INIT; - -MB_INC_AUTO_ID(channelGet); -MB_POINT(channelGet, 0); -MB_POINT(channelGet, 1); -MB_POINT(channelGet, 2); - -MB_INC_AUTO_ID(channelGet); -MB_POINT(channelGet, 3); -MB_POINT(channelGet, 4); -MB_POINT(channelGet, 5); -MB_POINT(channelGet, 6); -MB_POINT(channelGet, 7); - -MB_POINT(channelGet, 8); -MB_POINT(channelGet, 9); - - ----- - - -cat mb* | sort < mb.csv -mb_stat mb.csv - - -mb_stat mb.csv -n | grep ,2, | cut -d , -f 3 | gnuplot -p -e "plot '-'" - - ---- diff --git a/testApp/mb/mb_test.cpp b/testApp/mb/mb_test.cpp deleted file mode 100644 index 64ab697..0000000 --- a/testApp/mb/mb_test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -MB_DECLARE_EXTERN(test); -MB_DECLARE(test, 1000); - -int main() -{ - MB_INIT; - - for (int i = 0; i < 10; i++) - for (int j = 0; j < 100; j++) - MB_POINT_ID(test, i, j); - - return 0; -} -