From f73f18d692acfbdd39e9dd214ae0d2ba7dbf1836 Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Wed, 19 Jan 2011 14:29:12 -0500 Subject: [PATCH] fix problem in PVField::replaceStructure. There is still a memory leak --- pvDataApp/factory/AbstractPVField.h | 22 +++++-- pvDataApp/factory/TypeFunc.cpp.orig | 72 ---------------------- test/testLinkedListAux | 24 ++++---- test/testPVAppend | 14 +++++ test/testPVAppend.pl | 12 ++++ test/testPVAppendDiff | 0 test/testPVAppendGold | 14 +++++ test/testPVData | 2 +- test/testPVDataDiff | 4 ++ test/testThreadAux | 2 +- test/testTimeStampAux | 8 +-- test/testTimerAux | 12 ++-- testApp/pv/Makefile | 4 ++ testApp/pv/temp.cpp | 96 +++++++++++++++++++++++++++++ testApp/pv/testPVAppend.cpp | 96 +++++++++++++++++++++++++++++ 15 files changed, 281 insertions(+), 101 deletions(-) delete mode 100644 pvDataApp/factory/TypeFunc.cpp.orig create mode 100644 test/testPVAppend create mode 100755 test/testPVAppend.pl create mode 100644 test/testPVAppendDiff create mode 100644 test/testPVAppendGold create mode 100644 testApp/pv/temp.cpp create mode 100644 testApp/pv/testPVAppend.cpp diff --git a/pvDataApp/factory/AbstractPVField.h b/pvDataApp/factory/AbstractPVField.h index 1e4f9cb..c97449e 100644 --- a/pvDataApp/factory/AbstractPVField.h +++ b/pvDataApp/factory/AbstractPVField.h @@ -314,17 +314,29 @@ void PVField::computeOffset(PVField * pvField,int offset) { void PVField::replaceStructure(PVStructure *pvStructure,int length) { PVFieldPtrArray pvFields = pvStructure->getPVFields(); + StructureConstPtr old = static_cast(pImpl->field); + if(old->getNumberFields() == length) { + FieldConstPtrArray fields = old->getFields(); + for(int i=0; igetField(); + FieldConstPtr oldField = fields[i]; + if(newField==oldField) continue; + oldField->decReferenceCount(); + fields[i] = newField; + } + return; + } FieldConstPtrArray newFields = new FieldConstPtr[length]; for(int i=0; igetField(); + FieldConstPtr field = pvFields[i]->getField(); + field->incReferenceCount(); + newFields[i] = field; } StructureConstPtr newStructure = getFieldCreate()->createStructure( pImpl->field->getFieldName(),length, newFields); - PVStructure *parent = pImpl->parent; - if(parent==0) { - pImpl->field->decReferenceCount(); - } + pImpl->field->decReferenceCount(); pImpl->field = newStructure; + PVStructure *parent = pImpl->parent; if(parent!=0) { parent->replaceStructure( parent,parent->getStructure()->getNumberFields()); diff --git a/pvDataApp/factory/TypeFunc.cpp.orig b/pvDataApp/factory/TypeFunc.cpp.orig deleted file mode 100644 index 177325c..0000000 --- a/pvDataApp/factory/TypeFunc.cpp.orig +++ /dev/null @@ -1,72 +0,0 @@ -/*TypeFunc.cpp*/ -/** - * Copyright - See the COPYRIGHT that is included with this distribution. - * EPICS pvDataCPP is distributed subject to a Software License Agreement found - * in file LICENSE that is included with this distribution. - */ -#include -#include -#include -#include - -#include "pvIntrospect.h" - -namespace epics { namespace pvData { - - void TypeFunc::toString(StringBuilder buf,const Type type) { - static String unknownString = "logic error unknown Type"; - switch(type) { - case pvScalar : *buf += "scalar"; break; - case pvScalarArray : *buf += "scalarArray"; break; - case pvStructure : *buf += "structure"; break; - case pvStructureArray : *buf += "structureArray"; break; - default: - throw std::invalid_argument(unknownString); - } - } - - - bool ScalarTypeFunc::isInteger(ScalarType type) { - if(type>=pvByte && type<=pvLong) return true; - return false; - } - - bool ScalarTypeFunc::isNumeric(ScalarType type) { - if(type>=pvByte && type<=pvDouble) return true; - return false; - } - - bool ScalarTypeFunc::isPrimitive(ScalarType type) { - if(type>=pvBoolean && type<=pvDouble) return true; - return false; - } - - ScalarType ScalarTypeFunc::getScalarType(String pvalue) { - static String unknownString = "error unknown ScalarType"; - if(pvalue.compare("boolean")==0) return pvBoolean; - if(pvalue.compare("byte")==0) return pvByte; - if(pvalue.compare("short")==0) return pvShort; - if(pvalue.compare("int")==0) return pvInt; - if(pvalue.compare("long")==0) return pvLong; - if(pvalue.compare("float")==0) return pvFloat; - if(pvalue.compare("double")==0) return pvDouble; - if(pvalue.compare("string")==0) return pvString; - throw std::invalid_argument(unknownString); - } - void ScalarTypeFunc::toString(StringBuilder buf,const ScalarType scalarType) { - static String unknownString = "logic error unknown ScalarType"; - switch(scalarType) { - case pvBoolean : *buf += "boolean"; return; - case pvByte : *buf += "byte"; return;; - case pvShort : *buf += "short"; return; - case pvInt : *buf += "int"; return; - case pvLong : *buf += "long"; return; - case pvFloat : *buf += "float"; return; - case pvDouble : *buf += "double"; return; - case pvString : *buf += "string"; return; - } - throw std::invalid_argument(unknownString); - } - - -}} diff --git a/test/testLinkedListAux b/test/testLinkedListAux index 3216aaf..a295822 100644 --- a/test/testLinkedListAux +++ b/test/testLinkedListAux @@ -1,20 +1,20 @@ Time test -diff 23.623024 milliSeconds -time per iteration 23.623024 microseconds -time per addTail/removeHead 0.011812 microseconds +diff 23.288030 milliSeconds +time per iteration 23.288030 microseconds +time per addTail/removeHead 0.011644 microseconds Time test locked -diff 178.929120 milliSeconds -time per iteration 178.929120 microseconds -time per addTail/removeHead 0.089465 microseconds +diff 175.968013 milliSeconds +time per iteration 175.968013 microseconds +time per addTail/removeHead 0.087984 microseconds Time std::list test -diff 632.698846 milliSeconds -time per iteration 632.698846 microseconds -time per addTail/removeHead 0.316349 microseconds +diff 631.892603 milliSeconds +time per iteration 631.892603 microseconds +time per addTail/removeHead 0.315946 microseconds Time std::list test locked -diff 788.837800 milliSeconds -time per iteration 788.837800 microseconds -time per addTail/removeHead 0.394419 microseconds +diff 791.255075 milliSeconds +time per iteration 791.255075 microseconds +time per addTail/removeHead 0.395628 microseconds diff --git a/test/testPVAppend b/test/testPVAppend new file mode 100644 index 0000000..10339c1 --- /dev/null +++ b/test/testPVAppend @@ -0,0 +1,14 @@ +structure request + string fieldList value,timeStamp +structure request + string fieldList value,timeStamp + string extra junk +structure parent + structure child1 + string value bla + structure child2 + string value bla +field: totalConstruct 107 totalDestruct 101 ACTIVE 6 +pvField: totalConstruct 8 totalDestruct 8 +linkedListNode: totalConstruct 5 totalDestruct 5 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAppend.pl b/test/testPVAppend.pl new file mode 100755 index 0000000..799bf56 --- /dev/null +++ b/test/testPVAppend.pl @@ -0,0 +1,12 @@ +eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*- + if $running_under_some_shell; # testPVAppend.pl +use Env; +system ("rm testPVAppend"); +system ("rm testPVAppendDiff"); +system ("../bin/${EPICS_HOST_ARCH}/testPVAppend testPVAppend"); +system ("diff testPVAppend testPVAppendGold >> testPVAppendDiff"); +if(-z "testPVAppendDiff") { + print "testPVAppend OK\n"; +} else { + print "testPVAppend Failed\n"; +} diff --git a/test/testPVAppendDiff b/test/testPVAppendDiff new file mode 100644 index 0000000..e69de29 diff --git a/test/testPVAppendGold b/test/testPVAppendGold new file mode 100644 index 0000000..10339c1 --- /dev/null +++ b/test/testPVAppendGold @@ -0,0 +1,14 @@ +structure request + string fieldList value,timeStamp +structure request + string fieldList value,timeStamp + string extra junk +structure parent + structure child1 + string value bla + structure child2 + string value bla +field: totalConstruct 107 totalDestruct 101 ACTIVE 6 +pvField: totalConstruct 8 totalDestruct 8 +linkedListNode: totalConstruct 5 totalDestruct 5 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVData b/test/testPVData index f415392..5eba947 100644 --- a/test/testPVData +++ b/test/testPVData @@ -283,7 +283,7 @@ structure string timeStamp timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -field: totalConstruct 136 totalDestruct 136 +field: totalConstruct 136 totalDestruct 135 ACTIVE 1 pvField: totalConstruct 281 totalDestruct 281 linkedListNode: totalConstruct 5 totalDestruct 5 linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVDataDiff b/test/testPVDataDiff index e69de29..f383c96 100644 --- a/test/testPVDataDiff +++ b/test/testPVDataDiff @@ -0,0 +1,4 @@ +286c286 +< field: totalConstruct 136 totalDestruct 135 ACTIVE 1 +--- +> field: totalConstruct 136 totalDestruct 136 diff --git a/test/testThreadAux b/test/testThreadAux index 4b74ead..94bd57b 100644 --- a/test/testThreadAux +++ b/test/testThreadAux @@ -1 +1 @@ -time per call 37.293004 microseconds +time per call 40.057018 microseconds diff --git a/test/testTimeStampAux b/test/testTimeStampAux index 9ad1063..9693dc4 100644 --- a/test/testTimeStampAux +++ b/test/testTimeStampAux @@ -1,5 +1,5 @@ -current 1294842528 236065826 milliSec 1294842528236 -2011.01.12 09:28:48 236065826 nanoSeconds isDst false +current 1295462802 840097682 milliSec 1295462802840 +2011.01.19 13:46:42 840097682 nanoSeconds isDst false fromTime_t -current 1294842528 0 milliSec 1294842528000 -2011.01.12 09:28:48 0 nanoSeconds isDst false +current 1295462802 0 milliSec 1295462802000 +2011.01.19 13:46:42 0 nanoSeconds isDst false diff --git a/test/testTimerAux b/test/testTimerAux index 32afac2..d69a912 100644 --- a/test/testTimerAux +++ b/test/testTimerAux @@ -1,6 +1,6 @@ -one requested 0.400000 diff 0.400196 seconds -two requested 0.200000 diff 0.200182 seconds -one requested 0.200000 diff 0.200248 seconds -two requested 0.400000 diff 0.400307 seconds -one requested 0.000000 diff 0.000033 seconds -two requested 0.000000 diff 0.000049 seconds +one requested 0.400000 diff 0.400263 seconds +two requested 0.200000 diff 0.200168 seconds +one requested 0.200000 diff 0.200136 seconds +two requested 0.400000 diff 0.400176 seconds +one requested 0.000000 diff 0.000011 seconds +two requested 0.000000 diff 0.000018 seconds diff --git a/testApp/pv/Makefile b/testApp/pv/Makefile index 20e52c0..7eadc20 100644 --- a/testApp/pv/Makefile +++ b/testApp/pv/Makefile @@ -2,6 +2,10 @@ TOP=../.. include $(TOP)/configure/CONFIG +PROD_HOST += testPVAppend +testPVAppend_SRCS += testPVAppend.cpp +testPVAppend_LIBS += pvData Com + PROD_HOST += testPVType testPVType_SRCS += testPVType.cpp testPVType_LIBS += pvData Com diff --git a/testApp/pv/temp.cpp b/testApp/pv/temp.cpp new file mode 100644 index 0000000..86541c0 --- /dev/null +++ b/testApp/pv/temp.cpp @@ -0,0 +1,96 @@ +/* testPVAppend.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvDataCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/* Author: Marty Kraimer Date: 2010.11 */ + +#include +#include +#include +#include +#include + +#include + +#include "requester.h" +#include "pvIntrospect.h" +#include "pvData.h" +#include "convert.h" +#include "standardField.h" +#include "standardPVField.h" +#include "showConstructDestruct.h" + +using namespace epics::pvData; + +static FieldCreate * fieldCreate = 0; +static PVDataCreate * pvDataCreate = 0; +static StandardField *standardField = 0; +static StandardPVField *standardPVField = 0; +static Convert *convert = 0; +static String builder(""); +static String alarmTimeStamp("alarm,timeStamp"); +static String alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm"); +static String allProperties("alarm,timeStamp,display,control,valueAlarm"); + +static void testAppend(FILE * fd) +{ + FieldConstPtrArray fields = new FieldConstPtr[0]; + PVStructure *pvParent = pvDataCreate->createPVStructure( + 0,String("request"),0,fields); + PVString* pvStringField = static_cast( + pvDataCreate->createPVScalar(pvParent, "fieldList", pvString)); + pvStringField->put(String("value,timeStamp")); + pvParent->appendPVField(pvStringField); + builder.clear(); + pvParent->toString(&builder); + fprintf(fd,"%s\n",builder.c_str()); + pvStringField = static_cast( + pvDataCreate->createPVScalar(pvParent, "extra", pvString)); + pvStringField->put(String("junk")); + pvParent->appendPVField(pvStringField); + builder.clear(); + pvParent->toString(&builder); + fprintf(fd,"%s\n",builder.c_str()); + delete pvParent; + PVStructure* pvStructure = pvDataCreate->createPVStructure( + 0,"parent", 0); + PVStructure* pvChild1 = pvDataCreate->createPVStructure( + pvStructure, "child1", 0); + pvStringField = static_cast( + pvDataCreate->createPVScalar(pvChild1,"value", pvString)); + pvStringField->put("bla"); + pvChild1->appendPVField(pvStringField); + pvStructure->appendPVField(pvChild1); + PVStructure* pvChild2 = pvDataCreate->createPVStructure( + pvStructure, "child2", 0); + pvStringField = static_cast( + pvDataCreate->createPVScalar(pvChild2,"value", pvString)); + pvStringField->put("bla"); + pvChild2->appendPVField(pvStringField); + pvStructure->appendPVField(pvChild2); + builder.clear(); + pvStructure->toString(&builder); + fprintf(fd,"%s\n",builder.c_str()); + delete pvStructure; +} + +int main(int argc,char *argv[]) +{ + char *fileName = 0; + if(argc>1) fileName = argv[1]; + FILE * fd = stdout; + if(fileName!=0 && fileName[0]!=0) { + fd = fopen(fileName,"w+"); + } + fieldCreate = getFieldCreate(); + pvDataCreate = getPVDataCreate(); + standardField = getStandardField(); + standardPVField = getStandardPVField(); + convert = getConvert(); + testAppend(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); + return(0); +} + diff --git a/testApp/pv/testPVAppend.cpp b/testApp/pv/testPVAppend.cpp new file mode 100644 index 0000000..86541c0 --- /dev/null +++ b/testApp/pv/testPVAppend.cpp @@ -0,0 +1,96 @@ +/* testPVAppend.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvDataCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/* Author: Marty Kraimer Date: 2010.11 */ + +#include +#include +#include +#include +#include + +#include + +#include "requester.h" +#include "pvIntrospect.h" +#include "pvData.h" +#include "convert.h" +#include "standardField.h" +#include "standardPVField.h" +#include "showConstructDestruct.h" + +using namespace epics::pvData; + +static FieldCreate * fieldCreate = 0; +static PVDataCreate * pvDataCreate = 0; +static StandardField *standardField = 0; +static StandardPVField *standardPVField = 0; +static Convert *convert = 0; +static String builder(""); +static String alarmTimeStamp("alarm,timeStamp"); +static String alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm"); +static String allProperties("alarm,timeStamp,display,control,valueAlarm"); + +static void testAppend(FILE * fd) +{ + FieldConstPtrArray fields = new FieldConstPtr[0]; + PVStructure *pvParent = pvDataCreate->createPVStructure( + 0,String("request"),0,fields); + PVString* pvStringField = static_cast( + pvDataCreate->createPVScalar(pvParent, "fieldList", pvString)); + pvStringField->put(String("value,timeStamp")); + pvParent->appendPVField(pvStringField); + builder.clear(); + pvParent->toString(&builder); + fprintf(fd,"%s\n",builder.c_str()); + pvStringField = static_cast( + pvDataCreate->createPVScalar(pvParent, "extra", pvString)); + pvStringField->put(String("junk")); + pvParent->appendPVField(pvStringField); + builder.clear(); + pvParent->toString(&builder); + fprintf(fd,"%s\n",builder.c_str()); + delete pvParent; + PVStructure* pvStructure = pvDataCreate->createPVStructure( + 0,"parent", 0); + PVStructure* pvChild1 = pvDataCreate->createPVStructure( + pvStructure, "child1", 0); + pvStringField = static_cast( + pvDataCreate->createPVScalar(pvChild1,"value", pvString)); + pvStringField->put("bla"); + pvChild1->appendPVField(pvStringField); + pvStructure->appendPVField(pvChild1); + PVStructure* pvChild2 = pvDataCreate->createPVStructure( + pvStructure, "child2", 0); + pvStringField = static_cast( + pvDataCreate->createPVScalar(pvChild2,"value", pvString)); + pvStringField->put("bla"); + pvChild2->appendPVField(pvStringField); + pvStructure->appendPVField(pvChild2); + builder.clear(); + pvStructure->toString(&builder); + fprintf(fd,"%s\n",builder.c_str()); + delete pvStructure; +} + +int main(int argc,char *argv[]) +{ + char *fileName = 0; + if(argc>1) fileName = argv[1]; + FILE * fd = stdout; + if(fileName!=0 && fileName[0]!=0) { + fd = fopen(fileName,"w+"); + } + fieldCreate = getFieldCreate(); + pvDataCreate = getPVDataCreate(); + standardField = getStandardField(); + standardPVField = getStandardPVField(); + convert = getConvert(); + testAppend(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); + return(0); +} +