| /*========================================================================= |
| * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * one or more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| /* |
| * PdxHelper.cpp |
| * |
| * Created on: Dec 13, 2011 |
| * Author: npatel |
| */ |
| |
| #include "PdxHelper.hpp" |
| #include "PdxTypeRegistry.hpp" |
| #include "PdxWriterWithTypeCollector.hpp" |
| #include "SerializationRegistry.hpp" |
| #include "PdxLocalReader.hpp" |
| #include "PdxRemoteReader.hpp" |
| #include "PdxType.hpp" |
| #include "PdxReaderWithTypeCollector.hpp" |
| #include "PdxInstanceImpl.hpp" |
| #include "Utils.hpp" |
| #include "PdxRemoteWriter.hpp" |
| #include "CacheRegionHelper.hpp" |
| #include "../Cache.hpp" |
| |
| namespace gemfire { |
| uint8_t PdxHelper::PdxHeader = 8; |
| |
| PdxHelper::PdxHelper() { |
| } |
| |
| PdxHelper::~PdxHelper() { |
| } |
| |
| CacheImpl* PdxHelper::getCacheImpl() { |
| CachePtr cache = CacheFactory::getAnyInstance(); |
| if (cache == NULLPTR) |
| { |
| throw IllegalStateException("cache has not been created yet.");; |
| } |
| if (cache->isClosed()) |
| { |
| throw IllegalStateException("cache has been closed. "); |
| } |
| return CacheRegionHelper::getCacheImpl(cache.ptr()); |
| } |
| |
| void PdxHelper::serializePdx(DataOutput& output, |
| const PdxSerializable& pdxObject) { |
| const char* pdxClassname = NULL; |
| //bool isPdxWrapper = false; |
| |
| PdxSerializable& pdx = const_cast<PdxSerializable&>(pdxObject); |
| PdxInstanceImpl* pdxII = dynamic_cast<PdxInstanceImpl*>(&pdx/*.ptr()*/); |
| |
| if(pdxII != NULL) |
| { |
| PdxTypePtr piPt = pdxII->getPdxType(); |
| if(piPt != NULLPTR && piPt->getTypeId() == 0)//from pdxInstance factory need to get typeid from server |
| { |
| int typeId = PdxTypeRegistry::getPDXIdForType(piPt, output.getPoolName()); |
| pdxII->setPdxId(typeId); |
| } |
| PdxLocalWriterPtr plw(new PdxLocalWriter(output, piPt)); |
| pdxII->toData(plw); |
| plw->endObjectWriting();//now write typeid |
| int len = 0; |
| uint8_t* pdxStream = plw->getPdxStream(len); |
| pdxII->updatePdxStream( pdxStream, len); |
| |
| /* |
| ==18904== 265,458 bytes in 2 blocks are definitely lost in loss record 928 of 932 |
| ==18904== at 0x400791A: operator new[](unsigned int) (vg_replace_malloc.c:378) |
| ==18904== by 0x4324354: gemfire::PdxLocalWriter::getPdxStream(int&) (DataOutput.hpp:744) |
| ==18904== by 0x4303E6F: gemfire::PdxHelper::serializePdx(gemfire::DataOutput&, gemfire::PdxSerializable const&) (PdxHelper.cpp:64) |
| ==18904== by 0x4377028: gemfire::TcrMessage::writeObjectPart(gemfire::SharedPtr<gemfire::Serializable> const&, bool, bool, gemfire::VectorOfCacheableKey const*) (DataOutput.hpp:580) |
| ==18904== by 0x437BB9E: gemfire::TcrMessage::TcrMessage(gemfire::TcrMessage::MsgType, gemfire::Region const*, gemfire::SharedPtr<gemfire::CacheableKey> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable> const&, bool, gemfire::ThinClientBaseDM*, bool, bool, char const*) (TcrMessage.cpp:2216) |
| ==18904== by 0x43B9EE5: gemfire::ThinClientRegion::putNoThrow_remote(gemfire::SharedPtr<gemfire::CacheableKey> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::VersionTag>&, bool) (ThinClientRegion.cpp:909) |
| ==18904== by 0x42EFCEF: GfErrType gemfire::LocalRegion::updateNoThrow<gemfire::PutActions>(gemfire::SharedPtr<gemfire::CacheableKey> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable>&, int, gemfire::CacheEventFlags, gemfire::SharedPtr<gemfire::VersionTag>, gemfire::DataInput*, gemfire::SharedPtr<gemfire::EventId>) (LocalRegion.cpp:1097) |
| ==18904== by 0x42E4DC6: gemfire::LocalRegion::putNoThrow(gemfire::SharedPtr<gemfire::CacheableKey> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable>&, int, gemfire::CacheEventFlags, gemfire::SharedPtr<gemfire::VersionTag>, gemfire::DataInput*, gemfire::SharedPtr<gemfire::EventId>) (LocalRegion.cpp:1799) |
| ==18904== by 0x42DBEB4: gemfire::LocalRegion::put(gemfire::SharedPtr<gemfire::CacheableKey> const&, gemfire::SharedPtr<gemfire::Serializable> const&, gemfire::SharedPtr<gemfire::Serializable> const&) (LocalRegion.cpp:342) |
| ==18904== by 0x8069744: void gemfire::Region::put<gemfire::SharedPtr<gemfire::WritablePdxInstance> >(gemfire::SharedPtr<gemfire::CacheableKey> const&, gemfire::SharedPtr<gemfire::WritablePdxInstance> const&, gemfire::SharedPtr<gemfire::Serializable> const&) (in /export/pnq-gst-dev01a/users/adongre/cedar_dev_Nov12/build-artifacts/linux/tests/cppcache/testThinClientPdxInstance) |
| ==18904== by 0x808D107: Task_modifyPdxInstance::doTask() (in /export/pnq-gst-dev01a/users/adongre/cedar_dev_Nov12/build-artifacts/linux/tests/cppcache/testThinClientPdxInstance) |
| ==18904== by 0x80986CA: dunit::TestSlave::begin() (in /export/pnq-gst-dev01a/users/adongre/cedar_dev_Nov12/build-artifacts/linux/tests/cppcache/testThinClientPdxInstance) |
| ==18904== |
| */ |
| delete [] pdxStream; |
| |
| return; |
| } |
| |
| const char* pdxType = pdx.getClassName(); |
| pdxClassname = pdxType; |
| PdxTypePtr localPdxType = PdxTypeRegistry::getLocalPdxType(pdxType); |
| |
| if(localPdxType == NULLPTR) |
| { |
| //need to grab type info, as fromdata is not called yet |
| |
| PdxWriterWithTypeCollectorPtr ptc(new PdxWriterWithTypeCollector(output, pdxType)); |
| PdxWriterPtr pwp(dynCast<PdxWriterPtr>(ptc)); |
| pdx.toData(pwp); |
| PdxTypePtr nType = ptc->getPdxLocalType(); |
| |
| nType->InitializeType(); |
| |
| //int32 nTypeId =(int32) SerializationRegistry::GetPDXIdForType(output.getPoolName(), nType); |
| int32 nTypeId =(int32) PdxTypeRegistry::getPDXIdForType(pdxType, output.getPoolName(), nType, true); |
| nType->setTypeId( nTypeId ); |
| |
| ptc->endObjectWriting(); |
| PdxTypeRegistry::addLocalPdxType(pdxType, nType); |
| PdxTypeRegistry::addPdxType(nTypeId, nType); |
| |
| //[ToDo] need to write bytes for stats |
| CacheImpl* cacheImpl = PdxHelper::getCacheImpl(); |
| if (cacheImpl != NULL) { |
| uint8_t* stPos = const_cast<uint8_t*> (output.getBuffer()) + ptc->getStartPositionOffset(); |
| int pdxLen = PdxHelper::readInt32(stPos); |
| cacheImpl->m_cacheStats->incPdxSerialization(pdxLen + 1 + 2*4); //pdxLen + 93 DSID + len + typeID |
| } |
| |
| }else//we know locasl type, need to see preerved data |
| { |
| //if object got from server than create instance of RemoteWriter otherwise local writer. |
| |
| PdxSerializablePtr pdxObjptr = NULLPTR; |
| pdxObjptr = PdxSerializablePtr(&pdx); |
| |
| PdxRemotePreservedDataPtr pd = PdxTypeRegistry::getPreserveData(pdxObjptr); |
| |
| //now always remotewriter as we have API Read/WriteUnreadFields |
| //so we don't know whether user has used those or not;; Can we do some trick here? |
| PdxRemoteWriterPtr prw = NULLPTR; |
| |
| if(pd != NULLPTR) |
| { |
| PdxTypePtr mergedPdxType = PdxTypeRegistry::getPdxType(pd->getMergedTypeId()); |
| prw = PdxRemoteWriterPtr(new PdxRemoteWriter(output, mergedPdxType, pd)); |
| } |
| else{ |
| prw = PdxRemoteWriterPtr(new PdxRemoteWriter(output, pdxClassname)); |
| } |
| PdxWriterPtr pwptr(dynCast<PdxWriterPtr>(prw)); |
| pdx.toData(pwptr); |
| prw->endObjectWriting(); |
| |
| //[ToDo] need to write bytes for stats |
| CacheImpl* cacheImpl = PdxHelper::getCacheImpl(); |
| if (cacheImpl != NULL) { |
| uint8_t* stPos = const_cast<uint8_t*> (output.getBuffer()) + prw->getStartPositionOffset(); |
| int pdxLen = PdxHelper::readInt32(stPos); |
| cacheImpl->m_cacheStats->incPdxSerialization(pdxLen + 1 + 2*4); //pdxLen + 93 DSID + len + typeID |
| } |
| } |
| } |
| |
| PdxSerializablePtr PdxHelper::deserializePdx(DataInput& dataInput, bool forceDeserialize, int32 typeId, int32 length ){ |
| char* pdxClassname = NULL; |
| //char* pdxDomainClassname = NULL; |
| PdxSerializablePtr pdxObjectptr = NULLPTR; |
| PdxTypePtr pdxLocalType = NULLPTR; |
| |
| PdxTypePtr pType = PdxTypeRegistry::getPdxType(typeId); |
| if(pType != NULLPTR) {//this may happen with PdxInstanceFactory { |
| pdxLocalType = PdxTypeRegistry::getLocalPdxType(pType->getPdxClassName());//this should be fine for IPdxTypeMapper |
| } |
| if(pType != NULLPTR && pdxLocalType != NULLPTR)//type found |
| { |
| pdxClassname = pType->getPdxClassName(); |
| LOGDEBUG("deserializePdx ClassName = %s, isLocal = %d ", pType->getPdxClassName(), pType->isLocal()); |
| |
| pdxObjectptr = SerializationRegistry::getPdxType(pdxClassname); |
| if(pType->isLocal())//local type no need to read Unread data |
| { |
| PdxLocalReaderPtr plr (new PdxLocalReader(dataInput, pType, length)); |
| PdxReaderPtr prp(dynCast<PdxReaderPtr>(plr)); |
| pdxObjectptr->fromData(prp); |
| plr->MoveStream(); |
| } |
| else |
| { |
| PdxRemoteReaderPtr prr(new PdxRemoteReader(dataInput, pType, length)); |
| PdxReaderPtr prp(dynCast<PdxReaderPtr>(prr)); |
| pdxObjectptr->fromData(prp); |
| PdxTypePtr mergedVersion = PdxTypeRegistry::getMergedType(pType->getTypeId()); |
| |
| PdxRemotePreservedDataPtr preserveData = prr->getPreservedData(mergedVersion, pdxObjectptr); |
| if(preserveData != NULLPTR) |
| PdxTypeRegistry::setPreserveData(pdxObjectptr, preserveData);//it will set data in weakhashmap |
| prr->MoveStream(); |
| } |
| } |
| else |
| { |
| //type not found; need to get from server |
| if (pType == NULLPTR) |
| { |
| pType = SerializationRegistry::GetPDXTypeById(dataInput.getPoolName(), typeId); |
| pdxLocalType = PdxTypeRegistry::getLocalPdxType(pType->getPdxClassName()); |
| } |
| /* adongre - Coverity II |
| * CID 29298: Unused pointer value (UNUSED_VALUE) |
| * Pointer "pdxClassname" returned by "pType->getPdxClassName()" is never used. |
| * Fix : Commented the line |
| */ |
| //pdxClassname = pType->getPdxClassName(); |
| pdxObjectptr = SerializationRegistry::getPdxType(pType->getPdxClassName()); |
| PdxSerializablePtr pdxRealObject = pdxObjectptr; |
| //bool isPdxWrapper = false; |
| /* |
| PdxWrapperPtr pdxWrapper = dynamic_cast<PdxWrapperPtr>(pdxObject); |
| |
| if(pdxWrapper != nullptr) |
| { |
| isPdxWrapper = true; |
| } |
| else{}*/ |
| if(pdxLocalType == NULLPTR)//need to know local type |
| { |
| PdxReaderWithTypeCollectorPtr prtc (new PdxReaderWithTypeCollector(dataInput,pType,length)); |
| PdxReaderPtr prp(dynCast<PdxReaderPtr>(prtc)); |
| pdxObjectptr->fromData(prp); |
| |
| //Check for the PdxWrapper |
| |
| pdxLocalType = prtc->getLocalType(); |
| |
| if(pType-> Equals(pdxLocalType)){ |
| PdxTypeRegistry::addLocalPdxType(pdxRealObject->getClassName(), pType); |
| PdxTypeRegistry::addPdxType(pType->getTypeId(), pType); |
| pType->setLocal(true); |
| } |
| else{ |
| //Need to know local type and then merge type |
| pdxLocalType->InitializeType(); |
| pdxLocalType->setTypeId(PdxTypeRegistry::getPDXIdForType(pdxObjectptr->getClassName(), dataInput.getPoolName(), pdxLocalType, true)); |
| pdxLocalType->setLocal(true); |
| PdxTypeRegistry::addLocalPdxType(pdxRealObject->getClassName(), pdxLocalType);//added local type |
| PdxTypeRegistry::addPdxType(pdxLocalType->getTypeId(), pdxLocalType); |
| |
| pType->InitializeType(); |
| PdxTypeRegistry::addPdxType(pType->getTypeId(), pType); //adding remote type |
| |
| //create merge type |
| createMergedType(pdxLocalType, pType, dataInput); |
| |
| PdxTypePtr mergedVersion = PdxTypeRegistry::getMergedType(pType->getTypeId()); |
| |
| PdxRemotePreservedDataPtr preserveData = prtc->getPreservedData(mergedVersion, pdxObjectptr); |
| if(preserveData != NULLPTR) |
| PdxTypeRegistry::setPreserveData(pdxObjectptr, preserveData); |
| } |
| prtc->MoveStream(); |
| } |
| else{ //remote reader will come here as local type is there |
| pType->InitializeType(); |
| LOGDEBUG("Adding type %d " , pType->getTypeId()); |
| PdxTypeRegistry::addPdxType(pType->getTypeId(), pType); //adding remote type |
| PdxRemoteReaderPtr prr (new PdxRemoteReader(dataInput, pType, length)); |
| PdxReaderPtr prp(dynCast<PdxReaderPtr>(prr)); |
| pdxObjectptr->fromData(prp); |
| |
| //Check for PdxWrapper to getObject. |
| |
| createMergedType(pdxLocalType, pType, dataInput); |
| |
| PdxTypePtr mergedVersion = PdxTypeRegistry::getMergedType(pType->getTypeId()); |
| |
| PdxRemotePreservedDataPtr preserveData = prr->getPreservedData(mergedVersion, pdxObjectptr); |
| if(preserveData != NULLPTR) |
| PdxTypeRegistry::setPreserveData(pdxObjectptr, preserveData); |
| prr->MoveStream(); |
| } |
| } |
| return pdxObjectptr; |
| } |
| |
| PdxSerializablePtr PdxHelper::deserializePdx(DataInput& dataInput, bool forceDeserialize ) { |
| if(PdxTypeRegistry::getPdxReadSerialized() == false || forceDeserialize){ |
| |
| //Read Length |
| int32_t len; |
| dataInput.readInt(&len); |
| |
| int32_t typeId; |
| //read typeId |
| dataInput.readInt(&typeId); |
| |
| CacheImpl* cacheImpl = PdxHelper::getCacheImpl(); |
| if (cacheImpl != NULL) { |
| cacheImpl->m_cacheStats->incPdxDeSerialization(len + 9);//pdxLen + 1 + 2*4 |
| } |
| return PdxHelper::deserializePdx(dataInput, forceDeserialize, (int32)typeId, (int32)len); |
| |
| }else{ |
| //PdxSerializablePtr pdxObject = NULLPTR; |
| //Read Length |
| int32_t len; |
| dataInput.readInt(&len); |
| |
| int typeId; |
| //read typeId |
| dataInput.readInt(&typeId); |
| |
| PdxTypePtr pType = PdxTypeRegistry::getPdxType(typeId); |
| |
| if (pType == NULLPTR) { |
| PdxTypePtr pType = SerializationRegistry::GetPDXTypeById(dataInput.getPoolName(), typeId); |
| PdxTypeRegistry::addLocalPdxType(pType->getPdxClassName(), pType); |
| PdxTypeRegistry::addPdxType(pType->getTypeId(), pType); |
| } |
| |
| |
| /* |
| ==2018== 398,151 bytes in 3 blocks are definitely lost in loss record 707 of 710 |
| ==2018== at 0x400791A: operator new[](unsigned int) (vg_replace_malloc.c:378) |
| ==2018== by 0x4303969: gemfire::PdxHelper::deserializePdx(gemfire::DataInput&, bool) (DataInput.hpp:1007) |
| ==2018== by 0x43210D4: gemfire::PdxInstantiator::fromData(gemfire::DataInput&) (PdxInstantiator.cpp:30) |
| ==2018== by 0x434A72E: gemfire::SerializationRegistry::deserialize(gemfire::DataInput&, signed char) (SerializationRegistry.cpp:378) |
| ==2018== by 0x42280FB: gemfire::DataInput::readObjectInternal(gemfire::SharedPtr<gemfire::Serializable>&, signed char) (DataInput.cpp:9) |
| ==2018== by 0x438107E: gemfire::TcrMessage::readObjectPart(gemfire::DataInput&, bool) (DataInput.hpp:694) |
| ==2018== by 0x4375638: gemfire::TcrMessage::handleByteArrayResponse(char const*, int, unsigned short) (TcrMessage.cpp:1087) |
| ==2018== by 0x4375B2E: gemfire::TcrMessage::setData(char const*, int, unsigned short) (TcrMessage.cpp:3933) |
| ==2018== by 0x4367EE6: gemfire::TcrEndpoint::sendRequestConn(gemfire::TcrMessage const&, gemfire::TcrMessage&, gemfire::TcrConnection*, stlp_std::basic_string<char, stlp_std::char_traits<char>, stlp_std::allocator<char> >&) (TcrEndpoint.cpp:764) |
| ==2018== by 0x43682E3: gemfire::TcrEndpoint::sendRequestWithRetry(gemfire::TcrMessage const&, gemfire::TcrMessage&, gemfire::TcrConnection*&, bool&, stlp_std::basic_string<char, stlp_std::char_traits<char>, stlp_std::allocator<char> >&, int, bool, long long, bool) (TcrEndpoint.cpp:869) |
| ==2018== by 0x4368EBA: gemfire::TcrEndpoint::sendRequestConnWithRetry(gemfire::TcrMessage const&, gemfire::TcrMessage&, gemfire::TcrConnection*&, bool) (TcrEndpoint.cpp:1060) |
| ==2018== by 0x4393D2D: gemfire::ThinClientPoolDM::sendSyncRequest(gemfire::TcrMessage&, gemfire::TcrMessage&, bool, bool, gemfire::SharedPtr<gemfire::BucketServerLocation> const&) (ThinClientPoolDM.cpp:1408) |
| ==2018== |
| */ |
| //TODO::Enable it once the PdxInstanceImple is CheckedIn. |
| PdxSerializablePtr pdxObject ( new PdxInstanceImpl((uint8_t*)dataInput.currentBufferPosition(), len, typeId )); |
| |
| |
| dataInput.advanceCursor(len); |
| |
| //dataInput->AdvanceCursorPdx(len); |
| //dataInput->AdvanceUMCursor(); |
| //dataInput->SetBuffer(); |
| |
| CacheImpl* cacheImpl = PdxHelper::getCacheImpl(); |
| if (cacheImpl != NULL) { |
| cacheImpl->m_cacheStats->incPdxInstanceCreations(); |
| } |
| return pdxObject; |
| } |
| } |
| |
| void PdxHelper::createMergedType(PdxTypePtr localType, PdxTypePtr remoteType, DataInput& dataInput) |
| { |
| |
| PdxTypePtr mergedVersion = localType->mergeVersion(remoteType); |
| |
| if(mergedVersion->Equals(localType)) |
| { |
| PdxTypeRegistry::setMergedType(remoteType->getTypeId(), localType); |
| } |
| else if(mergedVersion->Equals(remoteType)) |
| { |
| PdxTypeRegistry::setMergedType(remoteType->getTypeId(), remoteType); |
| } |
| else |
| {//need to create new version |
| mergedVersion->InitializeType(); |
| if(mergedVersion->getTypeId() == 0) |
| mergedVersion->setTypeId(SerializationRegistry::GetPDXIdForType(dataInput.getPoolName(), mergedVersion)); |
| |
| // PdxTypeRegistry::AddPdxType(remoteType->TypeId, mergedVersion); |
| PdxTypeRegistry::addPdxType(mergedVersion->getTypeId(), mergedVersion); |
| PdxTypeRegistry::setMergedType(remoteType->getTypeId(), mergedVersion); |
| PdxTypeRegistry::setMergedType(mergedVersion->getTypeId(), mergedVersion); |
| } |
| } |
| |
| int32 PdxHelper::readInt32(uint8_t* offsetPosition) { |
| int32 data = offsetPosition[0]; |
| data = (data << 8) | offsetPosition[1]; |
| data = (data << 8) | offsetPosition[2]; |
| data = (data << 8) | offsetPosition[3]; |
| |
| return data; |
| } |
| |
| void PdxHelper::writeInt32(uint8_t* offsetPosition, int32 value) { |
| offsetPosition[0] = (uint8_t)(value >> 24); |
| offsetPosition[1] = (uint8_t)(value >> 16); |
| offsetPosition[2] = (uint8_t)(value >> 8); |
| offsetPosition[3] = (uint8_t) value; |
| } |
| |
| int32 PdxHelper::readInt16(uint8_t* offsetPosition){ |
| int16_t data = offsetPosition[0]; |
| data = (data << 8) | offsetPosition[1]; |
| return (int32) data; |
| } |
| |
| int32 PdxHelper::readUInt16(uint8_t* offsetPosition){ |
| uint16 data = offsetPosition[0]; |
| data = (data << 8) | offsetPosition[1]; |
| return (int32) data; |
| } |
| |
| int32 PdxHelper::readByte(uint8_t* offsetPosition){ |
| return (int32)offsetPosition[0]; |
| } |
| |
| void PdxHelper::writeInt16(uint8_t* offsetPosition, int32 value){ |
| int16 val = (int16) value; |
| offsetPosition[0] = (uint8_t)(val >> 8); |
| offsetPosition[1] = (uint8_t) val; |
| } |
| |
| void PdxHelper::writeByte(uint8_t* offsetPosition, int32 value){ |
| offsetPosition[0] = (uint8_t)value; |
| } |
| |
| int32 PdxHelper::readInt(uint8_t* offsetPosition, int size){ |
| switch (size) { |
| case 1: |
| return readByte(offsetPosition); |
| case 2: |
| return readUInt16(offsetPosition); |
| case 4: |
| return readInt32(offsetPosition); |
| } |
| throw; |
| } |
| |
| int32 PdxHelper::getEnumValue(const char* enumClassName, const char* enumName, int hashcode) |
| { |
| EnumInfoPtr ei(new EnumInfo(enumClassName, enumName, hashcode)); |
| return PdxTypeRegistry::getEnumValue(ei); |
| } |
| |
| EnumInfoPtr PdxHelper::getEnum(int enumId) |
| { |
| EnumInfoPtr ei = PdxTypeRegistry::getEnum(enumId); |
| return ei; |
| } |
| } |
| |