| /********************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| **********************************************************************/ |
| /* -*-C++-*- |
| ***************************************************************************** |
| * |
| * File: UdrExeIpc.cpp |
| * Description: IPC streams and message objects shared by the SQL/MX |
| * executor and the UDR server |
| * |
| * Created: 08/20/2000 |
| * Language: C++ |
| * |
| ***************************************************************************** |
| */ |
| |
| #include <iostream> |
| |
| #include "ComTransInfo.h" |
| #include "IpcMessageObj.h" |
| #include "ComplexObject.h" |
| #include "CliMsgObj.h" |
| #include "UdrExeIpc.h" |
| #include "sql_buffer.h" |
| #include "ExCextdecs.h" |
| #include "ComRtUtils.h" |
| |
| |
| //---------------------------------------------------------------------- |
| // UDR debugging code. See comments in UdrExeIpc.h. |
| //---------------------------------------------------------------------- |
| #ifdef UDR_DEBUG |
| #include <stdarg.h> |
| void UdrPrintf(FILE *f, const char *formatString, ...) |
| { |
| if (f) |
| { |
| va_list args; |
| va_start(args, formatString); |
| fprintf(f, "[UDR] "); |
| vfprintf(f, formatString, args); |
| fprintf(f, "\n"); |
| fflush(f); |
| } |
| } |
| #endif |
| |
| const char *GetUdrIpcTypeString(UdrIpcObjectType t) |
| { |
| switch (t) |
| { |
| case UDR_MSG_LOAD: return "UDR_MSG_LOAD"; |
| case UDR_MSG_LOAD_REPLY: return "UDR_MSG_LOAD_REPLY"; |
| case UDR_MSG_UNLOAD: return "UDR_MSG_UNLOAD"; |
| case UDR_MSG_UNLOAD_REPLY: return "UDR_MSG_UNLOAD_REPLY"; |
| case UDR_MSG_DATA_HEADER: return "UDR_MSG_DATA_HEADER"; |
| case UDR_MSG_DATA_REQUEST: return "UDR_MSG_DATA_REQUEST"; |
| case UDR_MSG_DATA_REPLY: return "UDR_MSG_DATA_REPLY"; |
| case UDR_MSG_CONTINUE_REQUEST: return "UDR_MSG_CONTINUE_REQUEST"; |
| case UDR_MSG_ERROR_REPLY: return "UDR_MSG_ERROR_REPLY"; |
| case UDR_MSG_SESSION: return "UDR_MSG_SESSION"; |
| case UDR_MSG_SESSION_REPLY: return "UDR_MSG_SESSION_REPLY"; |
| case UDR_MSG_ENTER_TX: return "UDR_MSG_ENTER_TX"; |
| case UDR_MSG_ENTER_TX_REPLY: return "UDR_MSG_ENTER_TX_REPLY"; |
| case UDR_MSG_EXIT_TX: return "UDR_MSG_EXIT_TX"; |
| case UDR_MSG_EXIT_TX_REPLY: return "UDR_MSG_EXIT_TX_REPLY"; |
| case UDR_MSG_RS_LOAD: return "UDR_MSG_RS_LOAD"; |
| case UDR_MSG_RS_LOAD_REPLY: return "UDR_MSG_RS_LOAD_REPLY"; |
| case UDR_MSG_RS_DATA_HEADER: return "UDR_MSG_RS_DATA_HEADER"; |
| case UDR_MSG_RS_CONTINUE: return "UDR_MSG_RS_CONTINUE"; |
| case UDR_MSG_RS_CLOSE: return "UDR_MSG_RS_CLOSE"; |
| case UDR_MSG_RS_CLOSE_REPLY: return "UDR_MSG_RS_CLOSE_REPLY"; |
| case UDR_MSG_RS_UNLOAD: return "UDR_MSG_RS_UNLOAD"; |
| case UDR_MSG_RS_UNLOAD_REPLY: return "UDR_MSG_RS_UNLOAD_REPLY"; |
| case UDR_MSG_RS_INFO: return "UDR_MSG_RS_INFO"; |
| case UDR_MSG_SUSPEND_TX: return "UDR_MSG_SUSPEND_TX"; |
| case UDR_MSG_SUSPEND_TX_REPLY: return "UDR_MSG_SUSPEND_TX_REPLY"; |
| case UDR_STREAM_CLIENT_CONTROL: return "UDR_STREAM_CLIENT_CONTROL"; |
| case UDR_STREAM_SERVER_CONTROL: return "UDR_STREAM_SERVER_CONTROL"; |
| case UDR_STREAM_CLIENT_DATA: return "UDR_STREAM_CLIENT_DATA"; |
| case UDR_STREAM_SERVER_DATA: return "UDR_STREAM_SERVER_DATA"; |
| case UDR_STREAM_SERVER_REPLY: return "UDR_STREAM_SERVER_REPLY"; |
| case UDR_IPC_INVALID: return "UDR_IPC_INVALID"; |
| default: return ComRtGetUnknownString((Int32) t); |
| } |
| } |
| |
| // |
| // Helper function to determine number of bytes that a string |
| // will occupy in a packed IpcMessageObj. |
| // |
| inline static IpcMessageObjSize packedStringLength(const char *s) |
| { |
| // |
| // The string will be preceded by a 4-byte length field and will |
| // include the null-terminator |
| // |
| IpcMessageObjSize result; |
| result = sizeof(Lng32); |
| if (s) |
| { |
| result += str_len(s) + 1; |
| } |
| return result; |
| } |
| |
| // ----------------------------------------------------------------------- |
| // class UdrParameterInfo |
| // ----------------------------------------------------------------------- |
| UdrParameterInfo::UdrParameterInfo(ComUInt32 position, |
| ComUInt32 flags, |
| ComSInt16 fsType, |
| ComSInt16 ansiType, |
| ComUInt16 paramNameLen, |
| const char *paramName, |
| ComUInt16 prec, |
| ComUInt16 scale, |
| ComUInt16 encodingCharSet, |
| ComUInt16 collation, |
| ComUInt32 dataLength, |
| ComSInt16 nullIndicatorLength, |
| ComSInt32 nullIndicatorOffset, |
| ComUInt32 dataOffset, |
| ComSInt32 vcLenIndOffset, |
| ComSInt16 vcIndicatorLength) |
| |
| : position_(position), |
| flags_(flags), |
| fsType_(fsType), |
| ansiType_(ansiType), |
| paramNameLen_((short) paramNameLen), |
| prec_(prec), |
| scale_(scale), |
| encodingCharSet_(encodingCharSet), |
| collation_(collation), |
| dataLength_(dataLength), |
| nullIndicatorLength_(nullIndicatorLength), |
| nullIndicatorOffset_(nullIndicatorOffset), |
| dataOffset_(dataOffset), |
| vcLenIndOffset_(vcLenIndOffset), |
| vcIndicatorLength_(vcIndicatorLength) |
| { |
| UdrExeAssert(paramNameLen <= 128, "Param name length cannot exceed 128"); |
| if (paramNameLen > 0) |
| str_cpy_all(paramName_, paramName, paramNameLen); |
| paramName_[paramNameLen_] = 0; |
| } |
| |
| IpcMessageObjSize UdrParameterInfo::packedLength() const |
| { |
| IpcMessageObjSize result = 0; |
| result += sizeof(position_); |
| result += sizeof(flags_); |
| result += sizeof(fsType_); |
| result += sizeof(ansiType_); |
| result += sizeof(paramNameLen_); |
| result += paramNameLen_; |
| result += sizeof(prec_); |
| result += sizeof(scale_); |
| result += sizeof(encodingCharSet_); |
| result += sizeof(collation_); |
| result += sizeof(dataLength_); |
| result += sizeof(nullIndicatorLength_); |
| result += sizeof(nullIndicatorOffset_); |
| result += sizeof(dataOffset_); |
| result += sizeof(vcLenIndOffset_); |
| result += sizeof(vcIndicatorLength_); |
| return result; |
| } |
| |
| IpcMessageObjSize UdrParameterInfo::pack(IpcMessageBufferPtr &buffer) const |
| { |
| IpcMessageObjSize result = 0; |
| result += packIntoBuffer(buffer, position_); |
| result += packIntoBuffer(buffer, flags_); |
| result += packIntoBuffer(buffer, fsType_); |
| result += packIntoBuffer(buffer, ansiType_); |
| result += packIntoBuffer(buffer, paramNameLen_); |
| if (paramNameLen_ > 0) |
| result += packStrIntoBuffer(buffer, (char *) (¶mName_[0]), |
| paramNameLen_); |
| result += packIntoBuffer(buffer, prec_); |
| result += packIntoBuffer(buffer, scale_); |
| result += packIntoBuffer(buffer, encodingCharSet_); |
| result += packIntoBuffer(buffer, collation_); |
| result += packIntoBuffer(buffer, dataLength_); |
| result += packIntoBuffer(buffer, nullIndicatorLength_); |
| result += packIntoBuffer(buffer, nullIndicatorOffset_); |
| result += packIntoBuffer(buffer, dataOffset_); |
| result += packIntoBuffer(buffer, vcLenIndOffset_); |
| result += packIntoBuffer(buffer, vcIndicatorLength_); |
| return result; |
| } |
| |
| void UdrParameterInfo::unpack(IpcConstMessageBufferPtr &buffer) |
| { |
| unpackBuffer(buffer, position_); |
| unpackBuffer(buffer, flags_); |
| unpackBuffer(buffer, fsType_); |
| unpackBuffer(buffer, ansiType_); |
| unpackBuffer(buffer, paramNameLen_); |
| if (paramNameLen_ > 0) |
| unpackStrFromBuffer(buffer, paramName_, paramNameLen_); |
| paramName_[paramNameLen_] = 0; |
| unpackBuffer(buffer, prec_); |
| unpackBuffer(buffer, scale_); |
| unpackBuffer(buffer, encodingCharSet_); |
| unpackBuffer(buffer, collation_); |
| unpackBuffer(buffer, dataLength_); |
| unpackBuffer(buffer, nullIndicatorLength_); |
| unpackBuffer(buffer, nullIndicatorOffset_); |
| unpackBuffer(buffer, dataOffset_); |
| unpackBuffer(buffer, vcLenIndOffset_); |
| unpackBuffer(buffer, vcIndicatorLength_); |
| } |
| |
| UdrParameterInfo& UdrParameterInfo::operator=(const UdrParameterInfo &other) |
| { |
| //-------------------------------------- |
| // Nothing to do when copying yourself |
| //-------------------------------------- |
| if (this == &other) |
| { |
| return *this; |
| } |
| |
| position_ = other.position_; |
| flags_ = other.flags_; |
| fsType_ = other.fsType_; |
| ansiType_ = other.ansiType_; |
| paramNameLen_ = other.paramNameLen_; |
| str_cpy_all(paramName_, other.paramName_, paramNameLen_ + 1); |
| prec_ = other.prec_; |
| scale_ = other.scale_; |
| encodingCharSet_ = other.encodingCharSet_; |
| collation_ = other.collation_; |
| dataLength_ = other.dataLength_; |
| nullIndicatorLength_ = other.nullIndicatorLength_; |
| nullIndicatorOffset_ = other.nullIndicatorOffset_; |
| dataOffset_ = other.dataOffset_; |
| vcLenIndOffset_ = other.vcLenIndOffset_; |
| vcIndicatorLength_ = other.vcIndicatorLength_; |
| |
| return *this; |
| |
| } //UdrParameterInfo::operator= |
| |
| |
| void UdrParameterInfo::display(FILE *f, Lng32 indent, |
| UdrParameterInfo *pi) const |
| { |
| char ind[100]; |
| Lng32 indIdx = 0; |
| if (indent > 99) |
| { |
| indent = 99; |
| } |
| for (indIdx = 0; indIdx < indent; indIdx++) |
| { |
| ind[indIdx] = ' '; |
| } |
| ind[indIdx] = '\0'; |
| |
| fprintf(f, "\n"); |
| fprintf(f, "%sContents of UdrParameterInfo:\n", ind); |
| fprintf(f, "%s-----------------------------\n", ind ); |
| |
| fprintf(f, "%sPosition : %d\n", ind , |
| (Lng32) pi->getPosition()); |
| fprintf(f, "%sFS Data Type : %d\n", ind , |
| (Lng32) pi->getFSType()); |
| fprintf(f, "%sANSI Data Type : %d\n", ind , |
| (Lng32) pi->getAnsiType()); |
| fprintf(f, "%sPrecision : %d\n", ind , |
| (Lng32) pi->getPrec()); |
| fprintf(f, "%sScale : %d\n", ind , |
| (Lng32) pi->getScale()); |
| fprintf(f, "%sencodingCharSet : %d\n", ind , |
| (Lng32) pi->getEncodingCharSet()); |
| fprintf(f, "%scollation : %d\n", ind , |
| (Lng32) pi->getCollation()); |
| |
| if (pi->isInOut()) |
| { |
| fprintf(f, "%sMode : INOUT\n", ind ); |
| } |
| else if (pi->isIn()) |
| { |
| fprintf(f, "%sMode : IN\n", ind ); |
| } |
| else if (pi->isOut()) |
| { |
| fprintf(f, "%sMode : OUT\n", ind ); |
| } |
| else |
| { |
| fprintf(f, "%sMode : INVALID\n", ind ); |
| } |
| |
| if (pi->isLmObjType()) |
| fprintf(f, "%sObject Mapping : TRUE\n", ind ); |
| else |
| fprintf(f, "%sObject Mapping : FALSE\n", ind ); |
| |
| if (pi->isNullable()) |
| fprintf(f, "%sNull Flag : TRUE\n", ind ); |
| else |
| fprintf(f, "%sNull Flag : FALSE\n", ind ); |
| |
| fprintf(f, "%sNull Indicator Length : %d\n", |
| ind , (Lng32) pi->getNullIndicatorLength()); |
| |
| fprintf(f, "%sNull Indicator Offset : %d\n", |
| ind , (Lng32) pi->getNullIndicatorOffset()); |
| |
| fprintf(f, "%sVC Len Indicator Offset : %d\n", |
| ind , (Lng32) pi->getVCLenIndOffset()); |
| |
| fprintf(f, "%sVC Indicator Length : %d\n", |
| ind , (Lng32) pi->getVCIndicatorLength()); |
| |
| fprintf(f, "%sData Offset : %d\n", |
| ind , (Lng32) pi->getDataOffset()); |
| |
| fprintf(f, "%sData Length : %d\n", |
| ind , (Lng32) pi->getDataLength()); |
| |
| fprintf(f, "%sPosition : %d\n\n", |
| ind , (Lng32) pi->getPosition()); |
| |
| fflush(f); |
| |
| } // UdrParameterInfo::display |
| |
| UdrTableInputInfo::UdrTableInputInfo( |
| ComUInt16 tabIndex, |
| ComUInt16 tableNameLen, |
| const char *tableName, |
| ComUInt16 numColumns, |
| ComUInt32 outputRowLen |
| ) |
| :tabIndex_(tabIndex), |
| tableNameLen_(tableNameLen), |
| numColumns_(numColumns), |
| outputRowLen_(outputRowLen), |
| inTableColumnDescs_(NULL) |
| { |
| if (tableNameLen >0) |
| { |
| str_cpy_all(tableName_,tableName,tableNameLen); |
| tableName_[tableNameLen_] = 0; |
| } |
| |
| } |
| const UdrParameterInfo &UdrTableInputInfo::getInTableColumnDesc(ComUInt32 i) const |
| { |
| UdrExeAssert(inTableColumnDescs_ && numColumns_ > i, |
| "An invalid index was passed to UdrLoadMsg::getInTableCoumndesc()"); |
| return inTableColumnDescs_[i]; |
| } |
| |
| void UdrTableInputInfo::setInTableColumnDesc(ComUInt32 i, const UdrParameterInfo &info, NAMemory *heap) |
| { |
| UdrExeAssert(numColumns_ > i, |
| "An invalid index was passed to UdrLoadMsg::setInTableColumnDesc()"); |
| |
| if(inTableColumnDescs_== NULL) |
| { |
| // allocate memory for the column desc info for this table desc entry |
| const ComUInt32 colsize= numColumns_ *sizeof(UdrParameterInfo); |
| inTableColumnDescs_ = (UdrParameterInfo *)(colsize ? |
| heap->allocateMemory(colsize) : NULL); |
| } |
| inTableColumnDescs_[i] = info; |
| } |
| |
| UdrTableInputInfo& UdrTableInputInfo::operator=(const UdrTableInputInfo &other) |
| { |
| tabIndex_ = other.tabIndex_; |
| tableNameLen_ = other.tableNameLen_; |
| str_cpy_all(tableName_,other.tableName_,tableNameLen_+1); |
| |
| numColumns_ = other.numColumns_; |
| outputRowLen_ = other.outputRowLen_; |
| inTableColumnDescs_ = other.inTableColumnDescs_; |
| return *this; |
| |
| } |
| IpcMessageObjSize UdrTableInputInfo::packedLength() const |
| { |
| IpcMessageObjSize result = 0; |
| result += sizeof(tabIndex_); |
| result += sizeof(tableNameLen_); |
| result += tableNameLen_; |
| result += sizeof(numColumns_); |
| result +=sizeof(outputRowLen_); |
| UInt32 i = 0; |
| for (i = 0; i < numColumns_; i++) |
| { |
| UdrParameterInfo &cinfo = inTableColumnDescs_[i]; |
| result += cinfo.packedLength(); |
| } |
| return result; |
| } |
| |
| IpcMessageObjSize UdrTableInputInfo::pack(IpcMessageBufferPtr &buffer) const |
| { |
| IpcMessageObjSize result = 0; |
| result += packIntoBuffer(buffer,tabIndex_); |
| result += packIntoBuffer(buffer,tableNameLen_); |
| if (tableNameLen_ >0) |
| result += packStrIntoBuffer(buffer,(char *)(&tableName_[0]), |
| tableNameLen_); |
| |
| result += packIntoBuffer(buffer,numColumns_); |
| result += packIntoBuffer(buffer,outputRowLen_); |
| UInt32 i = 0; |
| |
| for (i=0; i < numColumns_; i++) |
| { |
| const UdrParameterInfo &cinfo = inTableColumnDescs_[i]; |
| result += cinfo.pack(buffer); |
| } |
| return result; |
| } |
| |
| void UdrTableInputInfo::unpack(IpcConstMessageBufferPtr &buffer, NAMemory *heap) |
| { |
| unpackBuffer(buffer,tabIndex_); |
| unpackBuffer(buffer,tableNameLen_); |
| if (tableNameLen_ >0) |
| unpackStrFromBuffer(buffer,tableName_,tableNameLen_); |
| tableName_[tableNameLen_] = 0; |
| unpackBuffer(buffer,numColumns_); |
| unpackBuffer(buffer,outputRowLen_); |
| |
| // allocate memory for the column desc info for this table desc entry |
| const ComUInt32 colsize= numColumns_ *sizeof(UdrParameterInfo); |
| inTableColumnDescs_ = (UdrParameterInfo *)(colsize ? |
| heap->allocateMemory(colsize) : NULL); |
| ComUInt32 i; |
| for (i = 0; i < numColumns_; i++) |
| { |
| UdrParameterInfo &cinfo = inTableColumnDescs_[i]; |
| cinfo.unpack(buffer); |
| } |
| } |
| // ----------------------------------------------------------------------- |
| // class UdrMessageObj |
| // ----------------------------------------------------------------------- |
| UdrMessageObj::UdrMessageObj(UdrIpcObjectType objType, |
| IpcMessageObjVersion objVersion, |
| NAMemory *heap) |
| : IpcMessageObj(objType, objVersion), |
| heap_(heap), |
| handle_(INVALID_UDR_HANDLE) |
| { |
| } |
| |
| void UdrMessageObj::operator delete(void *p) |
| { |
| if (p) |
| { |
| NAMemory *h = ((UdrMessageObj *) p)->getHeap(); |
| if (h) |
| { |
| h->deallocateMemory(p); |
| } |
| else |
| { |
| ::delete ((UdrMessageObj *) p); |
| } |
| } |
| } |
| |
| |
| IpcMessageObjSize UdrMessageObj::packedLength() |
| { |
| return udrBaseClassPackedLength(); |
| } |
| |
| IpcMessageObjSize UdrMessageObj::packObjIntoMessage(IpcMessageBufferPtr buffer) |
| { |
| return packUdrBaseClass(buffer); |
| } |
| |
| void UdrMessageObj::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| unpackUdrBaseClass(buffer); |
| } |
| |
| #ifdef UDR_DEBUG |
| // |
| // Debug-build flags to control when the UDR server will force |
| // corruption in certain reply messages. By forcing corruption in a |
| // reply we can test the IPC integrity checks and error handling in |
| // the executor. |
| // |
| // Note: in the future it may not be a good idea to maintain these |
| // flags as global variables. Right now they are globals only because |
| // that allows us to make fewer getenv() calls in the UDR server. The |
| // fields are being set by udrBaseClassPackedLength() and read by |
| // packUdrBaseClass(). That is OK for now because for a given LOAD or |
| // UNLOAD reply those two methods are always called in a predictable |
| // sequence by the message stream. This assumption about the sequence |
| // of calls may not always be valid. |
| // |
| static NABoolean corruptLoadReply = FALSE; |
| static NABoolean corruptUnloadReply = FALSE; |
| #endif |
| |
| IpcMessageObjSize UdrMessageObj::udrBaseClassPackedLength() |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| IpcMessageObjSize result = 0; |
| result += super::baseClassPackedLength(); |
| |
| #ifdef UDR_DEBUG |
| // We allow the debug-build UDR server to corrupt a LOAD or UNLOAD |
| // reply by not packing the UDR handle. Note that the getenv() tests |
| // check for empty strings as values. These environment variables |
| // ans set and unset dynamically, and apparently in OSS calling |
| // putenv("X=") does not remove the environment variable, instead |
| // the variable gets an empty string as its value. |
| NABoolean packTheHandle = TRUE; |
| IpcMessageType t = getType(); |
| if (t == UDR_MSG_LOAD_REPLY) |
| { |
| char *val = getenv("MXUDR_CORRUPT_LOAD_REPLY"); |
| corruptLoadReply = (val && val[0]); |
| if (corruptLoadReply) |
| { |
| packTheHandle = FALSE; |
| } |
| } |
| else if (t == UDR_MSG_UNLOAD_REPLY) |
| { |
| char *val = getenv("MXUDR_CORRUPT_UNLOAD_REPLY"); |
| corruptUnloadReply = (val && val[0]); |
| if (corruptUnloadReply) |
| { |
| packTheHandle = FALSE; |
| } |
| } |
| if (packTheHandle) |
| { |
| result += sizeof(handle_); |
| } |
| #else |
| result += sizeof(handle_); |
| #endif |
| |
| return result; |
| } |
| |
| IpcMessageObjSize UdrMessageObj::packUdrBaseClass(IpcMessageBufferPtr &buffer) |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| // |
| // Note that we don't pack the heap pointer |
| // |
| IpcMessageObjSize result; |
| result = super::packBaseClassIntoMessage(buffer); |
| |
| #ifdef UDR_DEBUG |
| // We allow the debug-build UDR server to corrupt a LOAD or UNLOAD |
| // reply by not packing the UDR handle. See commentary above in |
| // udrBaseClassPackedLength(). |
| NABoolean packTheHandle = TRUE; |
| IpcMessageType t = getType(); |
| if (t == UDR_MSG_LOAD_REPLY && corruptLoadReply) |
| { |
| packTheHandle = FALSE; |
| } |
| else if (t == UDR_MSG_UNLOAD_REPLY && corruptUnloadReply) |
| { |
| packTheHandle = FALSE; |
| } |
| if (packTheHandle) |
| { |
| result += packIntoBuffer(buffer, handle_); |
| } |
| #else |
| result += packIntoBuffer(buffer, handle_); |
| #endif |
| |
| return result; |
| } |
| |
| void UdrMessageObj::unpackUdrBaseClass(IpcConstMessageBufferPtr &buffer) |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| super::unpackBaseClass(buffer); |
| unpackBuffer(buffer, handle_); |
| } |
| |
| NABoolean UdrMessageObj::checkObj(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr buffer) const |
| { |
| return checkUdrBaseClass(t, v, sameEndianness, size, buffer); |
| } |
| |
| NABoolean UdrMessageObj::checkUdrBaseClass(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr &buf) const |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| const IpcConstMessageBufferPtr lastByte = buf + size - 1; |
| if (!super::checkBaseClass(t, v, sameEndianness, size, buf)) |
| return FALSE; |
| if (!checkBuffer(buf, sizeof(handle_), lastByte)) |
| return FALSE; |
| return TRUE; |
| } |
| |
| IpcMessageRefCount UdrMessageObj::decrRefCount() |
| { |
| IpcMessageRefCount result = 0; |
| |
| if (getRefCount() == 1) |
| { |
| // |
| // IpcMessageObj::decrRefCount() would delete the object by calling |
| // global operator delete since IpcMessageObj doesn't have an |
| // operator delete. However, if we code the "delete this" statement |
| // in the context of this class we will pick up the correct operator |
| // delete. |
| // |
| delete this; |
| result = 0; |
| } |
| else |
| { |
| // |
| // This is the normal case. The object won't be deleted |
| // |
| result = IpcMessageObj::decrRefCount(); |
| } |
| |
| return result; |
| } |
| |
| char *UdrMessageObj::allocateMemory(ComUInt32 nBytes) |
| { |
| char *result = NULL; |
| if (getHeap()) |
| { |
| result = (char *) getHeap()->allocateMemory(nBytes); |
| } |
| else |
| { |
| result = new char[nBytes]; |
| } |
| return result; |
| } |
| |
| void UdrMessageObj::deallocateMemory(char *s) |
| { |
| if (s) |
| { |
| if (getHeap()) |
| { |
| getHeap()->deallocateMemory(s); |
| } |
| else |
| { |
| delete [] s; |
| } |
| } |
| } |
| |
| char *UdrMessageObj::allocateString(const char *s) |
| { |
| char *result = NULL; |
| if (s) |
| { |
| ComUInt32 n = str_len(s) + 1; |
| result = allocateMemory(n); |
| str_cpy_all(result, s, (Lng32)n); |
| } |
| return result; |
| } |
| |
| void UdrMessageObj::deallocateString(char *&s) |
| { |
| deallocateMemory(s); |
| s = NULL; |
| } |
| |
| //---------------------------------------------------------------------- |
| // UdrControlStream |
| //---------------------------------------------------------------------- |
| UdrControlStream::UdrControlStream(IpcEnvironment *env, |
| IpcMessageType msgType, |
| IpcMessageObjVersion version) |
| : IpcMessageStream(env, |
| msgType, |
| version, |
| 0, // 0 implies no fixed buffer size |
| TRUE) // share message objects? |
| { |
| sendCount_ = 0; |
| recvCount_ = 0; |
| } |
| |
| UdrControlStream::~UdrControlStream() |
| { |
| } |
| |
| void UdrControlStream::actOnSend(IpcConnection *connection) |
| { |
| // Base class implementation does nothing |
| } |
| |
| void UdrControlStream::actOnReceive(IpcConnection *connection) |
| { |
| // Base class implementation does nothing |
| } |
| |
| //---------------------------------------------------------------------- |
| // UdrLoadMsg |
| //---------------------------------------------------------------------- |
| UdrLoadMsg::UdrLoadMsg(NAMemory *heap) |
| : UdrControlMsg(UDR_MSG_LOAD, UdrLoadMsgVersionNumber, heap), |
| sqlName_(NULL), routineName_(NULL), routineSignature_(NULL), |
| containerName_(NULL), externalPath_(NULL), librarySqlName_(NULL),transactionAttrs_(0), |
| sqlAccessMode_(0), language_(0), paramStyle_(0), |
| externalSecurity_(0), maxNumResultSets_(0), |
| numParameters_(0), numInValues_(0), numOutValues_(0), |
| inBufferSize_(0), outBufferSize_(0), |
| inputRowSize_(0), outputRowSize_(0), |
| udrFlags_(0), inParamInfo_(NULL), outParamInfo_(NULL), |
| routineOwnerId_(0), |
| parentQid_(NULL), |
| numInputTables_(0), |
| inTables_(NULL), |
| instanceNum_(0), |
| numInstances_(0), |
| numOptionalDataBufs_(0), |
| optionalData_(NULL), |
| optionalDataIsShared_(TRUE), |
| udrSerInvocationInfoLen_(0), |
| udrSerInvocationInfo_(NULL), |
| udrSerPlanInfoLen_(0), |
| udrSerPlanInfo_(NULL), |
| udrJavaDebugPort_(-1), |
| udrJavaDebugTimeout_(0) |
| { |
| } |
| |
| UdrLoadMsg::UdrLoadMsg(NAMemory *heap, |
| const char *sqlName, |
| const char *routineName, |
| const char *routineSignature, |
| const char *containerName, |
| const char *externalPath, |
| const char *librarySqlName, |
| ComRoutineTransactionAttributes transactionAttrs, |
| ComRoutineSQLAccess sqlAccessMode, |
| ComRoutineLanguage language, |
| ComRoutineParamStyle paramStyle, |
| ComRoutineExternalSecurity externalSecurity, |
| ComUInt32 maxNumResultSets, |
| ComUInt32 numParameters, |
| ComUInt32 numInValues, |
| ComUInt32 numOutValues, |
| ComUInt32 inBufferSize, |
| ComUInt32 outBufferSize, |
| ComUInt32 inputRowSize, |
| ComUInt32 outputRowSize, |
| ComUInt32 udrFlags, |
| Int32 routineOwnerId, |
| const char *parentQid, |
| ComUInt32 udrSerInvocationInfoLen, |
| const char *udrSerInvocationInfo, |
| ComUInt32 udrSerPlanInfoLen, |
| const char *udrSerPlanInfo, |
| Int32 javaDebugPort, |
| Int32 javaDebugTimeout, |
| ComUInt32 instanceNum, |
| ComUInt32 numInstances |
| ) |
| : UdrControlMsg(UDR_MSG_LOAD, UdrLoadMsgVersionNumber, heap), |
| sqlName_(NULL), routineName_(NULL), routineSignature_(NULL), |
| containerName_(NULL), externalPath_(NULL), librarySqlName_(NULL),transactionAttrs_(transactionAttrs), |
| sqlAccessMode_(sqlAccessMode), language_(language), paramStyle_(paramStyle), |
| externalSecurity_(externalSecurity), |
| maxNumResultSets_(maxNumResultSets), |
| numParameters_(numParameters), numInValues_(numInValues), |
| numOutValues_(numOutValues), |
| inBufferSize_(inBufferSize), outBufferSize_(outBufferSize), |
| inputRowSize_(inputRowSize), outputRowSize_(outputRowSize), |
| udrFlags_(udrFlags), inParamInfo_(NULL), outParamInfo_(NULL), |
| numInputTables_(0), |
| inTables_(NULL), |
| routineOwnerId_(routineOwnerId), |
| parentQid_(NULL), |
| numOptionalDataBufs_(0), optionalData_(NULL), optionalDataIsShared_(TRUE), |
| udrSerInvocationInfoLen_(udrSerInvocationInfoLen), |
| udrSerInvocationInfo_(udrSerInvocationInfo), |
| udrSerPlanInfoLen_(udrSerPlanInfoLen), |
| udrSerPlanInfo_(udrSerPlanInfo), |
| instanceNum_(instanceNum), |
| numInstances_(numInstances), |
| udrJavaDebugPort_(javaDebugPort), |
| udrJavaDebugTimeout_(javaDebugTimeout) |
| { |
| sqlName_ = allocateString(sqlName); |
| routineName_ = allocateString(routineName); |
| routineSignature_ = allocateString(routineSignature); |
| containerName_ = allocateString(containerName); |
| externalPath_ = allocateString(externalPath); |
| librarySqlName_ = allocateString(librarySqlName); |
| parentQid_ = allocateString(parentQid); |
| allocateParamInfo(); |
| // allocateTableInputInfo(); |
| } |
| |
| // |
| // The following helper functions take care of memory management |
| // for parameter info arrays. They call NAMemory methods to allocate |
| // and deallocate memory. It is safe to call NAMemory::allocate(0), |
| // which returns NULL, and NAMemory::deallocate(NULL), which does |
| // nothing. |
| // |
| void UdrLoadMsg::allocateParamInfo() |
| { |
| deallocateParamInfo(); |
| const ComUInt32 n1 = numInValues_ * sizeof(UdrParameterInfo); |
| const ComUInt32 n2 = numOutValues_ * sizeof(UdrParameterInfo); |
| inParamInfo_ = (UdrParameterInfo *) (n1 ? allocateMemory(n1) : NULL); |
| outParamInfo_ = (UdrParameterInfo *) (n2 ? allocateMemory(n2) : NULL); |
| } |
| void UdrLoadMsg::deallocateParamInfo() |
| { |
| deallocateMemory((char *) inParamInfo_); |
| deallocateMemory((char *) outParamInfo_); |
| inParamInfo_ = NULL; |
| outParamInfo_ = NULL; |
| } |
| |
| void UdrLoadMsg::allocateTableInputInfo() |
| { |
| deallocateTableInputInfo(); |
| // First allocate the array of table descriptors |
| const ComUInt32 t1 = numInputTables_ * sizeof(UdrTableInputInfo); |
| inTables_ = (UdrTableInputInfo *) (t1 ? allocateMemory(t1) : NULL); |
| |
| |
| /* |
| // For each table descriptor allocate memory for the column descriptors |
| short j= 0; |
| for (j = 0; j < numInputTables_; j++) |
| { |
| const ComUInt32 colsize=inTables_[j].getNumColumns() *sizeof(UdrParameterInfo); |
| inTables_[j].inTableColumnDescs_ = (UdrParameterInfo *)(colsize ? |
| allocateMemory(colsize) : NULL); |
| |
| } */ |
| |
| } |
| |
| void UdrLoadMsg::deallocateTableInputInfo() |
| { |
| short j = 0; |
| if (inTables_) |
| { |
| for (j=0; j < numInputTables_;j++) |
| { |
| deallocateMemory((char *)inTables_[j].inTableColumnDescs_); |
| inTables_[j].inTableColumnDescs_ = NULL; |
| } |
| deallocateMemory((char *)inTables_); |
| |
| inTables_ = NULL; |
| } |
| } |
| |
| void UdrLoadMsg::allocateInvocationInfo() |
| { |
| if (udrSerInvocationInfoLen_) |
| udrSerInvocationInfo_ = allocateMemory(udrSerInvocationInfoLen_); |
| if (udrSerPlanInfoLen_) |
| udrSerPlanInfo_ = allocateMemory(udrSerPlanInfoLen_); |
| } |
| |
| void UdrLoadMsg::deallocateInvocationInfo() |
| { |
| if (udrSerInvocationInfoLen_) |
| deallocateMemory((char *) udrSerInvocationInfo_); |
| if (udrSerPlanInfoLen_) |
| deallocateMemory((char *) udrSerPlanInfo_); |
| udrSerInvocationInfoLen_ = 0; |
| udrSerInvocationInfo_ = NULL; |
| udrSerPlanInfoLen_ = 0; |
| udrSerPlanInfo_ = NULL; |
| } |
| |
| UdrParameterInfo *UdrLoadMsg::setInParam(ComUInt32 i, |
| const UdrParameterInfo &info) |
| { |
| UdrExeAssert(inParamInfo_ && numInValues_ > i, |
| "An invalid index was passed to UdrLoadMsg::setInParam()"); |
| UdrParameterInfo *result = NULL; |
| if (inParamInfo_ && numInValues_ > i) |
| { |
| inParamInfo_[i] = info; |
| result = &(inParamInfo_[i]); |
| } |
| return result; |
| } |
| |
| UdrParameterInfo *UdrLoadMsg::setOutParam(ComUInt32 i, |
| const UdrParameterInfo &info) |
| { |
| UdrExeAssert(outParamInfo_ && numOutValues_ > i, |
| "An invalid index was passed to UdrLoadMsg::setOutParam()"); |
| UdrParameterInfo *result = NULL; |
| if (outParamInfo_ && numOutValues_ > i) |
| { |
| outParamInfo_[i] = info; |
| result = &(outParamInfo_[i]); |
| } |
| return result; |
| } |
| |
| const UdrParameterInfo &UdrLoadMsg::getInParam(ComUInt32 i) const |
| { |
| UdrExeAssert(inParamInfo_ && numInValues_ > i, |
| "An invalid index was passed to UdrLoadMsg::getInParam()"); |
| return inParamInfo_[i]; |
| } |
| |
| const UdrParameterInfo &UdrLoadMsg::getOutParam(ComUInt32 i) const |
| { |
| UdrExeAssert(outParamInfo_ && numOutValues_ > i, |
| "An invalid index was passed to UdrLoadMsg::getOutParam()"); |
| return outParamInfo_[i]; |
| } |
| void UdrLoadMsg::setChildTableInput(ComUInt32 i, |
| const UdrTableInputInfo &info) |
| { |
| UdrExeAssert(inTables_ && numInputTables_ > i, |
| "An invalid index was passed to UdrLoadMsg::setInParam()"); |
| UdrTableInputInfo *result = NULL; |
| if (inTables_ && numInputTables_ > i) |
| { |
| inTables_[i] = info; |
| } |
| |
| } |
| void UdrLoadMsg::deallocateOptionalDataBufs() |
| { |
| if (optionalData_) |
| { |
| if (!optionalDataIsShared_) |
| { |
| for (ComUInt32 i = 0; i < numOptionalDataBufs_; i++) |
| deallocateMemory(optionalData_[i]); |
| } |
| deallocateMemory((char *) optionalData_); |
| } |
| |
| numOptionalDataBufs_ = 0; |
| optionalDataIsShared_ = TRUE; |
| optionalData_ = NULL; |
| } |
| |
| void UdrLoadMsg::initOptionalDataBufs(ComUInt32 numBufs, NABoolean isShared) |
| { |
| deallocateOptionalDataBufs(); |
| numOptionalDataBufs_ = numBufs; |
| optionalDataIsShared_ = isShared; |
| optionalData_ = NULL; |
| if (numBufs > 0) |
| optionalData_ = (char **) allocateMemory(numBufs * sizeof(char *)); |
| } |
| |
| ComUInt32 UdrLoadMsg::getNumOptionalDataBufs() |
| { |
| return numOptionalDataBufs_; |
| } |
| |
| void UdrLoadMsg::setOptionalDataBuf(ComUInt32 i, |
| const char *buf, |
| ComUInt32 bufLen) |
| { |
| UdrExeAssert(i < numOptionalDataBufs_, "Index out of range"); |
| const char *buf2 = buf; |
| if (!optionalDataIsShared_) |
| { |
| buf2 = allocateMemory(bufLen); |
| str_cpy_all((char *) buf2, buf, (Lng32) bufLen); |
| } |
| optionalData_[i] = (char *) buf2; |
| } |
| |
| char *UdrLoadMsg::getOptionalDataBuf(ComUInt32 i) |
| { |
| UdrExeAssert(i < numOptionalDataBufs_, "Index out of range"); |
| return optionalData_[i]; |
| } |
| |
| |
| |
| UdrLoadMsg::~UdrLoadMsg() |
| { |
| deallocateString(sqlName_); |
| deallocateString(routineName_); |
| deallocateString(routineSignature_); |
| deallocateString(containerName_); |
| deallocateString(externalPath_); |
| deallocateString(librarySqlName_); |
| deallocateString(parentQid_); |
| deallocateParamInfo(); |
| deallocateOptionalDataBufs(); |
| deallocateTableInputInfo(); |
| } |
| |
| IpcMessageObjSize UdrLoadMsg::packedLength() |
| { |
| IpcMessageObjSize result; |
| result = udrBaseClassPackedLength(); |
| result += packedStringLength(sqlName_); |
| result += packedStringLength(routineName_); |
| result += packedStringLength(routineSignature_); |
| result += packedStringLength(containerName_); |
| result += packedStringLength(externalPath_); |
| result += packedStringLength(librarySqlName_); |
| result += sizeof(transactionAttrs_); |
| result += sizeof(sqlAccessMode_); |
| result += sizeof(language_); |
| result += sizeof(paramStyle_); |
| result += sizeof(externalSecurity_); |
| result += sizeof(maxNumResultSets_); |
| result += sizeof(numParameters_); |
| result += sizeof(numInValues_); |
| result += sizeof(numOutValues_); |
| result += sizeof(inBufferSize_); |
| result += sizeof(outBufferSize_); |
| result += sizeof(inputRowSize_); |
| result += sizeof(outputRowSize_); |
| result += sizeof(udrFlags_); |
| result += sizeof(routineOwnerId_); |
| result += packedStringLength(parentQid_); |
| result += sizeof(udrJavaDebugPort_); |
| result += sizeof(udrJavaDebugTimeout_); |
| result += sizeof(numInputTables_); |
| result += sizeof(numInstances_); |
| result += sizeof(instanceNum_); |
| |
| ComUInt32 i = 0; |
| for (i = 0; i < numInValues_; i++) |
| { |
| const UdrParameterInfo &info = inParamInfo_[i]; |
| const IpcMessageObjSize infoSize = info.packedLength(); |
| result += infoSize; |
| } |
| for (i = 0; i < numOutValues_; i++) |
| { |
| const UdrParameterInfo &info = outParamInfo_[i]; |
| const IpcMessageObjSize infoSize = info.packedLength(); |
| result += infoSize; |
| } |
| |
| for (i=0; i <numInputTables_;i++) |
| { |
| const UdrTableInputInfo &tinfo = inTables_[i]; |
| const IpcMessageObjSize tinfosize = tinfo.packedLength(); |
| result += tinfosize; |
| } |
| |
| result += sizeof(numOptionalDataBufs_); |
| for (i = 0; i < numOptionalDataBufs_; i++) |
| { |
| const char *buf = optionalData_[i]; |
| ComUInt32 dataLen = 0; |
| str_cpy_all((char *) &dataLen, buf, 4); |
| result += (dataLen + 4); |
| } |
| |
| result += sizeof(udrSerInvocationInfoLen_); |
| result += sizeof(udrSerPlanInfoLen_); |
| result += udrSerInvocationInfoLen_; |
| result += udrSerPlanInfoLen_; |
| |
| return result; |
| } |
| |
| IpcMessageObjSize UdrLoadMsg::packObjIntoMessage(IpcMessageBufferPtr buffer) |
| { |
| IpcMessageObjSize result; |
| result = packUdrBaseClass(buffer); |
| result += packCharStarIntoBuffer(buffer, sqlName_); |
| result += packCharStarIntoBuffer(buffer, routineName_); |
| result += packCharStarIntoBuffer(buffer, routineSignature_); |
| result += packCharStarIntoBuffer(buffer, containerName_); |
| result += packCharStarIntoBuffer(buffer, externalPath_); |
| result += packCharStarIntoBuffer(buffer, librarySqlName_); |
| result += packIntoBuffer(buffer, transactionAttrs_); |
| result += packIntoBuffer(buffer, sqlAccessMode_); |
| result += packIntoBuffer(buffer, language_); |
| result += packIntoBuffer(buffer, paramStyle_); |
| result += packIntoBuffer(buffer, externalSecurity_); |
| result += packIntoBuffer(buffer, maxNumResultSets_); |
| result += packIntoBuffer(buffer, numParameters_); |
| result += packIntoBuffer(buffer, numInValues_); |
| result += packIntoBuffer(buffer, numOutValues_); |
| result += packIntoBuffer(buffer, inBufferSize_); |
| result += packIntoBuffer(buffer, outBufferSize_); |
| result += packIntoBuffer(buffer, inputRowSize_); |
| result += packIntoBuffer(buffer, outputRowSize_); |
| result += packIntoBuffer(buffer, udrFlags_); |
| result += packIntoBuffer(buffer, routineOwnerId_); |
| result += packCharStarIntoBuffer(buffer, parentQid_); |
| result += packIntoBuffer(buffer, udrJavaDebugPort_); |
| result += packIntoBuffer(buffer, udrJavaDebugTimeout_); |
| result += packIntoBuffer(buffer, numInstances_); |
| result += packIntoBuffer(buffer, instanceNum_); |
| |
| ComUInt32 i; |
| for (i = 0; i < numInValues_; i++) |
| { |
| const UdrParameterInfo &info = inParamInfo_[i]; |
| result += info.pack(buffer); |
| } |
| for (i = 0; i < numOutValues_; i++) |
| { |
| const UdrParameterInfo &info = outParamInfo_[i]; |
| result += info.pack(buffer); |
| } |
| |
| result +=packIntoBuffer(buffer,numInputTables_); |
| for (i = 0; i < numInputTables_; i++) |
| { |
| const UdrTableInputInfo &tinfo = inTables_[i]; |
| result += tinfo.pack(buffer); |
| } |
| result += packIntoBuffer(buffer, numOptionalDataBufs_); |
| for (i = 0; i < numOptionalDataBufs_; i++) |
| { |
| char *buf = optionalData_[i]; |
| ComUInt32 dataLen = 0; |
| str_cpy_all((char *) &dataLen, buf, 4); |
| result += packStrIntoBuffer(buffer, buf, (dataLen + 4)); |
| } |
| |
| result += packIntoBuffer(buffer, udrSerInvocationInfoLen_); |
| result += packIntoBuffer(buffer, udrSerPlanInfoLen_); |
| if (udrSerInvocationInfoLen_) |
| result += packStrIntoBuffer(buffer, |
| (char *) udrSerInvocationInfo_, |
| udrSerInvocationInfoLen_); |
| if (udrSerPlanInfoLen_) |
| result += packStrIntoBuffer(buffer, |
| (char *) udrSerPlanInfo_, |
| udrSerPlanInfoLen_); |
| |
| return result; |
| } |
| |
| void UdrLoadMsg::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| unpackUdrBaseClass(buffer); |
| unpackBuffer(buffer, sqlName_, getHeap()); |
| unpackBuffer(buffer, routineName_, getHeap()); |
| unpackBuffer(buffer, routineSignature_, getHeap()); |
| unpackBuffer(buffer, containerName_, getHeap()); |
| unpackBuffer(buffer, externalPath_, getHeap()); |
| unpackBuffer(buffer, librarySqlName_, getHeap()); |
| unpackBuffer(buffer, transactionAttrs_); |
| unpackBuffer(buffer, sqlAccessMode_); |
| unpackBuffer(buffer, language_); |
| unpackBuffer(buffer, paramStyle_); |
| unpackBuffer(buffer, externalSecurity_); |
| unpackBuffer(buffer, maxNumResultSets_); |
| unpackBuffer(buffer, numParameters_); |
| unpackBuffer(buffer, numInValues_); |
| unpackBuffer(buffer, numOutValues_); |
| unpackBuffer(buffer, inBufferSize_); |
| unpackBuffer(buffer, outBufferSize_); |
| unpackBuffer(buffer, inputRowSize_); |
| unpackBuffer(buffer, outputRowSize_); |
| unpackBuffer(buffer, udrFlags_); |
| unpackBuffer(buffer, routineOwnerId_); |
| unpackBuffer(buffer, parentQid_, getHeap()); |
| unpackBuffer(buffer, udrJavaDebugPort_); |
| unpackBuffer(buffer, udrJavaDebugTimeout_); |
| unpackBuffer(buffer, numInstances_); |
| unpackBuffer(buffer, instanceNum_); |
| allocateParamInfo(); |
| |
| ComUInt32 i; |
| for (i = 0; i < numInValues_; i++) |
| { |
| UdrParameterInfo &info = inParamInfo_[i]; |
| info.unpack(buffer); |
| } |
| for (i = 0; i < numOutValues_; i++) |
| { |
| UdrParameterInfo &info = outParamInfo_[i]; |
| info.unpack(buffer); |
| } |
| unpackBuffer(buffer, numInputTables_); |
| allocateTableInputInfo(); |
| for (i =0; i < numInputTables_; i++) |
| { |
| UdrTableInputInfo &tinfo = inTables_[i]; |
| tinfo.unpack(buffer, getHeap()); |
| } |
| ComUInt32 numBufs = 0; |
| unpackBuffer(buffer, numBufs); |
| initOptionalDataBufs(numBufs, FALSE); |
| for (i = 0; i < numOptionalDataBufs_; i++) |
| { |
| ComUInt32 dataLen = 0; |
| str_cpy_all((char *) &dataLen, buffer, 4); |
| ComUInt32 totalLen = dataLen + 4; |
| setOptionalDataBuf(i, buffer, totalLen); |
| buffer += totalLen; |
| } |
| |
| deallocateInvocationInfo(); |
| unpackBuffer(buffer, udrSerInvocationInfoLen_); |
| unpackBuffer(buffer, udrSerPlanInfoLen_); |
| allocateInvocationInfo(); |
| if (udrSerInvocationInfoLen_) |
| unpackStrFromBuffer(buffer, |
| (char *) udrSerInvocationInfo_, |
| udrSerInvocationInfoLen_); |
| if (udrSerPlanInfoLen_) |
| unpackStrFromBuffer(buffer, |
| (char *) udrSerPlanInfo_, |
| udrSerPlanInfoLen_); |
| } |
| |
| //---------------------------------------------------------------------- |
| // UdrSessionMsg |
| //---------------------------------------------------------------------- |
| UdrSessionMsg::UdrSessionMsg(NAMemory *heap) |
| : UdrControlMsg(UDR_MSG_SESSION, UdrSessionMsgVersionNumber, heap), |
| attrType_(UDR_SESSION_TYPE_UNKNOWN), |
| flags_(0), |
| strings_(heap) |
| { |
| } |
| |
| UdrSessionMsg::UdrSessionMsg(UdrSessionAttrType attrType, |
| ComUInt32 flags, |
| NAMemory *heap) |
| : UdrControlMsg(UDR_MSG_SESSION, UdrSessionMsgVersionNumber, heap), |
| attrType_(attrType), |
| flags_(flags), |
| strings_(heap) |
| { |
| } |
| |
| UdrSessionMsg::~UdrSessionMsg() |
| { |
| ComUInt32 e = strings_.entries(); |
| for (ULng32 i = 0; i < e; i++) |
| { |
| NADELETEBASIC(strings_[i], getHeap()); |
| } |
| } |
| |
| void UdrSessionMsg::addString(const char *option) |
| { |
| if (option == NULL || option[0] == '\0') |
| { |
| return; |
| } |
| Int32 len = str_len(option); |
| char *copy = new (getHeap()) char[len + 1]; |
| str_cpy_all(copy, option, len + 1); |
| strings_.insert(copy); |
| } |
| |
| IpcMessageObjSize UdrSessionMsg::packedLength() |
| { |
| IpcMessageObjSize result; |
| result = udrBaseClassPackedLength(); |
| |
| result += sizeof(attrType_); |
| result += sizeof(flags_); |
| |
| ComUInt32 e = strings_.entries(); |
| result += sizeof(e); |
| |
| for (ULng32 i = 0; i < e; i++) |
| { |
| result += packedStringLength(strings_[i]); |
| } |
| |
| return result; |
| } |
| |
| IpcMessageObjSize UdrSessionMsg::packObjIntoMessage(IpcMessageBufferPtr buffer) |
| { |
| IpcMessageObjSize result; |
| result = packUdrBaseClass(buffer); |
| result += packIntoBuffer(buffer, attrType_); |
| result += packIntoBuffer(buffer, flags_); |
| |
| ComUInt32 e = strings_.entries(); |
| result += packIntoBuffer(buffer, e); |
| |
| for (ULng32 i = 0; i < e; i++) |
| { |
| result += packCharStarIntoBuffer(buffer, strings_[i]); |
| } |
| |
| return result; |
| } |
| |
| void UdrSessionMsg::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| unpackUdrBaseClass(buffer); |
| |
| unpackBuffer(buffer, attrType_); |
| unpackBuffer(buffer, flags_); |
| |
| ComUInt32 e; |
| unpackBuffer(buffer, e); |
| |
| char *copy; |
| for (ULng32 i = 0; i < e; i++) |
| { |
| // The unpackBuffer() call will deallocate copy from the heap if |
| // copy is non-NULL which is not what we want. So we make sure |
| // copy is set to NULL before calling unpackBuffer(). |
| copy = NULL; |
| unpackBuffer(buffer, copy, getHeap()); |
| strings_.insert(copy); |
| } |
| } |
| |
| #ifdef UDR_DEBUG |
| void UdrSessionMsg::display(FILE *f, const char *prefix) const |
| { |
| fprintf(f, "%s[UdrSessionMsg] type %d, flags 0x%08x\n", |
| prefix, (Lng32) attrType_, (Lng32) flags_); |
| |
| ComUInt32 e = strings_.entries(); |
| for (ULng32 i = 0; i < e; i++) |
| { |
| fprintf(f, "%s '%s'\n", prefix, strings_[i]); |
| } |
| |
| fflush(f); |
| } |
| #endif // UDR_DEBUG |
| |
| //---------------------------------------------------------------------- |
| // UdrDataBuffer |
| //---------------------------------------------------------------------- |
| |
| // |
| // Constructor for either copyless send or allocation on an NAMemory heap. |
| // For copyless send the NAMemory pointer should be NULL. |
| // |
| UdrDataBuffer::UdrDataBuffer(ULng32 sqlBufferLength, |
| InOut mode, NAMemory *heap) |
| : UdrMessageObj(mode == UDR_DATA_IN ? |
| UDR_MSG_DATA_REQUEST : UDR_MSG_DATA_REPLY, |
| UdrDataBufferVersionNumber, |
| heap), |
| sqlBufferLength_(sqlBufferLength), |
| flags_(0) |
| { |
| if (getHeap()) |
| { |
| // |
| // Allocate SqlBuffer on a heap |
| // |
| theBuffer_ = (SqlBuffer *) new (getHeap()) char[sqlBufferLength]; |
| } |
| else |
| { |
| // |
| // The SqlBuffer starts at the next address that is aligned on an |
| // 8-byte boundary |
| // |
| IpcMessageBufferPtr bufferStart = (IpcMessageBufferPtr) this; |
| bufferStart += sizeof(*this); |
| alignBufferForNextObj(bufferStart); |
| theBuffer_ = (SqlBuffer *) (bufferStart); |
| } |
| |
| theBuffer_->driveInit(sqlBufferLength_, FALSE, SqlBuffer::NORMAL_); |
| theBuffer_->bufferInUse(); |
| tableIndex_ = -1; |
| } |
| |
| // |
| // Constructors for copyless receive |
| // |
| UdrDataBuffer::UdrDataBuffer(IpcBufferedMsgStream *msgStream, |
| NABoolean driveUnPack) |
| : UdrMessageObj(msgStream) |
| { |
| copylessUnpack(FALSE, 0, driveUnPack); |
| } |
| |
| |
| UdrDataBuffer::UdrDataBuffer(/* IN */ IpcBufferedMsgStream *msgStream, |
| /* IN */ IpcMessageObjSize objSize, |
| /* OUT */ NABoolean &integrityCheckResult ) |
| : UdrMessageObj(msgStream) |
| { |
| integrityCheckResult = copylessUnpack(TRUE, objSize); |
| } |
| |
| NABoolean UdrDataBuffer::copylessUnpack(NABoolean doChecks, |
| IpcMessageObjSize objSize, |
| NABoolean driveUnPack) |
| { |
| // |
| // Notes about this method |
| // |
| // When doChecks is TRUE we verify that the in-place unpacking of |
| // this object does not cause us to create pointers that reference |
| // memory outside the bounds of this object. |
| // |
| // The SqlBuffer starts at the next address beyond "this" that is |
| // aligned on an 8-byte boundary. |
| // |
| theBuffer_ = NULL; |
| NABoolean result = TRUE; |
| IpcConstMessageBufferPtr buffer = (IpcMessageBufferPtr) this; |
| IpcConstMessageBufferPtr lastByte = (doChecks ? buffer + objSize - 1 : 0); |
| |
| IpcMessageObjSize bytesForThis = sizeof(*this); |
| alignSizeForNextObj(bytesForThis); |
| |
| // The buffer must be large enough to hold an instance of this class |
| if (doChecks) |
| { |
| if (!checkBuffer(buffer, bytesForThis, lastByte)) |
| { |
| result = FALSE; |
| } |
| } |
| else |
| { |
| buffer += bytesForThis; |
| } |
| |
| if (result) |
| { |
| if (doChecks) |
| { |
| // The buffer must be large enough to hold a SqlBufferNormal instance |
| IpcConstMessageBufferPtr startOfSqlBuffer = buffer; |
| if (!checkBuffer(startOfSqlBuffer, sizeof(SqlBufferNormal), lastByte)) |
| { |
| result = FALSE; |
| } |
| else |
| { |
| // Now we verify the contents of the SqlBuffer instance. We must |
| // not call virtual methods on the SqlBuffer at this point. That |
| // can only be done reliably after the SqlBuffer has been |
| // unpacked. |
| theBuffer_ = (SqlBuffer *) buffer; |
| if (theBuffer_->bufType() != SqlBufferBase::NORMAL_ || |
| theBuffer_->get_buffer_size() != sqlBufferLength_ || |
| !theBuffer_->packed() || |
| !theBuffer_->driveVerify(lastByte - buffer + 1)) |
| { |
| theBuffer_ = NULL; |
| result = FALSE; |
| } |
| } |
| } // if (doChecks) |
| |
| else |
| { |
| theBuffer_ = (SqlBuffer *) buffer; |
| } |
| |
| } // if (result) |
| |
| if (result && driveUnPack) |
| { |
| theBuffer_->driveUnpack(); |
| |
| // |
| // The sql_buffer state was set to IN_USE by the sender. This |
| // prevents the buffer from being deallocated during I/O. Once all |
| // rows have been consumed from this sql_buffer then isFree() will |
| // return TRUE and the buffer will eventually be deallocated by the |
| // stream. Here we assert that the buffer is not yet free, a way of |
| // showing that the sender set its state to IN_USE. |
| // |
| // This test was not done earlier with the other SqlBuffer tests |
| // because it requires a virtual method and we have to unpack the |
| // object before we can reliably invoke virtual methods. |
| // |
| if (doChecks) |
| { |
| if (theBuffer_->isFree()) |
| { |
| theBuffer_ = NULL; |
| result = FALSE; |
| } |
| } |
| else |
| { |
| UdrExeAssert(!(theBuffer_->isFree()), |
| "An empty UdrDataBuffer arrived on a UDR data stream"); |
| } |
| } // if (result) |
| |
| if (!result) |
| { |
| UdrExeAssert(theBuffer_ == NULL, |
| "SqlBuffer should be NULL following integrity check failure"); |
| } |
| |
| return result; |
| } |
| |
| UdrDataBuffer::~UdrDataBuffer() |
| { |
| if (getHeap()) |
| { |
| getHeap()->deallocateMemory(theBuffer_); |
| } |
| } |
| |
| // |
| // Determine if UdrDataBuffer in IpcMessageBuffer is available for recycle |
| // |
| NABoolean UdrDataBuffer::msgObjIsFree() |
| { |
| NABoolean result = (theBuffer_ && (!theBuffer_->packed()) ? theBuffer_->isFree() : TRUE); |
| return result; |
| } |
| |
| // |
| // Deal with transport issues, change pointers to offsets, etc. |
| // |
| void UdrDataBuffer::prepMsgObjForSend() |
| { |
| theBuffer_->drivePack(); |
| #ifdef UDR_DEBUG |
| // We allow the debug-build UDR server to corrupt an INVOKE |
| // reply. Note that the getenv() test must also check for an empty |
| // string value because in OSS calling putenv("X=") apparently does |
| // not remove the environment setting. |
| { |
| char *val = getenv("MXUDR_CORRUPT_DATA_REPLY"); |
| if (val && val[0]) |
| { |
| sqlBufferLength_ -= 1; |
| } |
| } |
| #endif |
| } |
| |
| NABoolean UdrDataBuffer::moreRows() const |
| { |
| NABoolean result = FALSE; |
| if (theBuffer_ && !theBuffer_->atEOTD()) |
| { |
| result = TRUE; |
| } |
| return result; |
| } |
| |
| IpcMessageObjSize UdrDataBuffer::packedLength() |
| { |
| // |
| // Note: The number returned by this function is valid only for use |
| // with "regular" message streams, not with buffered message streams |
| // using copyless IPC |
| // |
| IpcMessageObjSize result = 0; |
| result = udrBaseClassPackedLength(); |
| result += sizeof(flags_); |
| result += sizeof(sqlBufferLength_); |
| result +=sizeof(tableIndex_); |
| result += sqlBufferLength_; |
| return result; |
| } |
| |
| IpcMessageObjSize UdrDataBuffer::packObjIntoMessage(IpcMessageBufferPtr buffer) |
| { |
| IpcMessageObjSize result = 0; |
| result += packUdrBaseClass(buffer); |
| result += packIntoBuffer(buffer, flags_); |
| result += packIntoBuffer(buffer, sqlBufferLength_); |
| |
| // |
| // Convert pointers in the SqlBuffer to offsets and copy the SqlBuffer |
| // |
| theBuffer_->drivePack(); |
| str_cpy_all(buffer, (char *) theBuffer_, (Lng32)sqlBufferLength_); |
| result += sqlBufferLength_; |
| result += packIntoBuffer(buffer,tableIndex_); |
| return result; |
| } |
| |
| void UdrDataBuffer::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| UdrExeAssert((objType == UDR_MSG_DATA_REQUEST |
| || objType == UDR_MSG_DATA_REPLY) |
| && objVersion == UdrDataBufferVersionNumber |
| && sameEndianness |
| && objSize > sizeof(IpcMessageObj), |
| "Invalid type or version seen by UdrDataBuffer::unpackObj()"); |
| |
| unpackUdrBaseClass(buffer); |
| unpackBuffer(buffer, flags_); |
| unpackBuffer(buffer, sqlBufferLength_); |
| |
| // |
| // Unpack the SqlBuffer |
| // |
| str_cpy_all((char *) theBuffer_, buffer, (Lng32)sqlBufferLength_); |
| theBuffer_->driveUnpack(); |
| unpackBuffer(buffer,tableIndex_); |
| |
| } |
| |
| NABoolean UdrDataBuffer::checkObj(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr buffer) const |
| { |
| // |
| // This method is not implemented for now. All UDR data replies |
| // travel on buffered streams via copyless IPC and should be |
| // verified by calling the appropriate copyless receive constructor. |
| // |
| UdrExeAssert(FALSE, "UdrDataBuffer::checkObj() should not be called"); |
| return FALSE; |
| } |
| |
| //---------------------------------------------------------------------- |
| // class UdrRSMessageObj |
| //---------------------------------------------------------------------- |
| IpcMessageObjSize UdrRSMessageObj::packedLength() |
| { |
| return udrBaseClassPackedLength(); |
| } |
| |
| IpcMessageObjSize UdrRSMessageObj::packObjIntoMessage(IpcMessageBufferPtr buf) |
| { |
| return packUdrBaseClass(buf); |
| } |
| |
| void UdrRSMessageObj::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| unpackUdrBaseClass(buffer); |
| } |
| |
| IpcMessageObjSize UdrRSMessageObj::udrBaseClassPackedLength() |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| IpcMessageObjSize result; |
| result = super::udrBaseClassPackedLength(); |
| result += sizeof(rshandle_); |
| return result; |
| } |
| |
| IpcMessageObjSize UdrRSMessageObj::packUdrBaseClass(IpcMessageBufferPtr &buf) |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| IpcMessageObjSize result; |
| result = super::packUdrBaseClass(buf); |
| result += packIntoBuffer(buf, rshandle_); |
| return result; |
| } |
| |
| void UdrRSMessageObj::unpackUdrBaseClass(IpcConstMessageBufferPtr &buffer) |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| super::unpackUdrBaseClass(buffer); |
| unpackBuffer(buffer, rshandle_); |
| } |
| |
| NABoolean UdrRSMessageObj::checkObj(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr buffer) const |
| { |
| return checkUdrBaseClass(t, v, sameEndianness, size, buffer); |
| } |
| |
| NABoolean |
| UdrRSMessageObj::checkUdrBaseClass(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr &buf) const |
| { |
| // NOTE: changes to any of the following methods also require |
| // corresponding changes in the others: |
| // - udrBaseClassPackedLength() |
| // - packUdrBaseClass() |
| // - unpackUdrBaseClass() |
| // - checkUdrBaseClass() |
| |
| const IpcConstMessageBufferPtr lastByte = buf + size - 1; |
| if (!super::checkUdrBaseClass(t, v, sameEndianness, size, buf)) |
| return FALSE; |
| if (!checkBuffer(buf, sizeof(rshandle_), lastByte)) |
| return FALSE; |
| return TRUE; |
| } |
| |
| //---------------------------------------------------------------------- |
| // class UdrRSLoadMsg |
| //---------------------------------------------------------------------- |
| UdrRSLoadMsg::UdrRSLoadMsg(ComUInt32 rsIndex, |
| ComUInt32 numRSCols, |
| ComUInt32 rowSize, |
| ComUInt32 bufferSize, |
| ComUInt32 flags, |
| NAMemory *heap) |
| : UdrRSControlMsg(UDR_MSG_RS_LOAD, UdrRSLoadMsgVersionNumber, heap), |
| rsIndex_(rsIndex), numRSCols_(numRSCols), rsColumnDesc_(NULL), |
| outputRowSize_(rowSize), outBufferSize_(bufferSize), rsLoadFlags_(flags) |
| { |
| allocateColumnDescs(); |
| } |
| |
| UdrRSLoadMsg::UdrRSLoadMsg(NAMemory *heap) |
| : UdrRSControlMsg(UDR_MSG_RS_LOAD, UdrRSLoadMsgVersionNumber, heap), |
| rsIndex_(0), numRSCols_(0), rsColumnDesc_(NULL), |
| outputRowSize_(0), outBufferSize_(0), rsLoadFlags_(0) |
| { |
| } |
| |
| UdrRSLoadMsg::~UdrRSLoadMsg() |
| { |
| deallocateColumnDescs(); |
| } |
| |
| void UdrRSLoadMsg::allocateColumnDescs() |
| { |
| deallocateColumnDescs(); |
| const ComUInt32 n = numRSCols_ * sizeof(UdrParameterInfo); |
| rsColumnDesc_ = (UdrParameterInfo *) (n ? allocateMemory(n) : NULL); |
| } |
| |
| void UdrRSLoadMsg::deallocateColumnDescs() |
| { |
| deallocateMemory((char *) rsColumnDesc_); |
| rsColumnDesc_ = NULL; |
| } |
| |
| UdrParameterInfo& UdrRSLoadMsg::getColumnDesc(ComUInt32 i) const |
| { |
| UdrExeAssert(rsColumnDesc_ && numRSCols_ > i, |
| "An invalid index was passed to UdrRSLoadMsg::getColumnDesc()"); |
| return rsColumnDesc_[i]; |
| } |
| |
| UdrParameterInfo * UdrRSLoadMsg::setColumnDesc(ComUInt32 i, |
| const UdrParameterInfo &info) |
| { |
| UdrExeAssert(rsColumnDesc_ && numRSCols_ > i, |
| "An invalid index was passed to UdrRSLoadMsg::setColumnDesc()"); |
| rsColumnDesc_[i] = info; |
| return &rsColumnDesc_[i]; |
| } |
| |
| IpcMessageObjSize UdrRSLoadMsg::packedLength() |
| { |
| IpcMessageObjSize result; |
| result = udrBaseClassPackedLength(); |
| result += sizeof(rsIndex_); |
| result += sizeof(numRSCols_); |
| result += sizeof(outputRowSize_); |
| result += sizeof(outBufferSize_); |
| result += sizeof(rsLoadFlags_); |
| |
| ComUInt32 i = 0; |
| for (i = 0; i < numRSCols_; i++) |
| { |
| result += getColumnDesc(i).packedLength(); |
| } |
| |
| return result; |
| } |
| |
| IpcMessageObjSize UdrRSLoadMsg::packObjIntoMessage(IpcMessageBufferPtr buffer) |
| { |
| IpcMessageObjSize result; |
| result = packUdrBaseClass(buffer); |
| result += packIntoBuffer(buffer, rsIndex_); |
| result += packIntoBuffer(buffer, numRSCols_); |
| result += packIntoBuffer(buffer, outputRowSize_); |
| result += packIntoBuffer(buffer, outBufferSize_); |
| result += packIntoBuffer(buffer, rsLoadFlags_); |
| |
| for (ComUInt32 i=0; i<numRSCols_; i++) |
| { |
| result += getColumnDesc(i).pack(buffer); |
| } |
| |
| return result; |
| } |
| |
| void UdrRSLoadMsg::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| unpackUdrBaseClass(buffer); |
| unpackBuffer(buffer, rsIndex_); |
| unpackBuffer(buffer, numRSCols_); |
| unpackBuffer(buffer, outputRowSize_); |
| unpackBuffer(buffer, outBufferSize_); |
| unpackBuffer(buffer, rsLoadFlags_); |
| |
| allocateColumnDescs(); |
| |
| for (ComUInt32 i=0; i<numRSCols_; i++) |
| { |
| getColumnDesc(i).unpack(buffer); |
| } |
| } |
| |
| //---------------------------------------------------------------------- |
| // struct ResultSetInfo |
| //---------------------------------------------------------------------- |
| ResultSetInfo::ResultSetInfo(const char *proxy, |
| SQLSTMT_ID *stmtID, |
| ComUInt32 cntxID, |
| NAMemory *heap) |
| : stmtID_(stmtID), cntxID_(cntxID), proxySyntax_(NULL), heap_(heap) |
| { |
| proxySyntax_ = allocateString(proxy); |
| } |
| |
| ResultSetInfo::~ResultSetInfo() |
| { |
| deallocateString(proxySyntax_); |
| } |
| |
| void ResultSetInfo::deallocateString(char *&s) |
| { |
| if (s) |
| { |
| if (heap_) |
| heap_->deallocateMemory(s); |
| else |
| delete [] s; |
| s = NULL; |
| } |
| } |
| |
| char *ResultSetInfo::allocateString(const char *s) |
| { |
| char *result = NULL; |
| if (s) |
| { |
| ComUInt32 n = str_len(s) + 1; |
| |
| if (heap_) |
| result = (char *) heap_->allocateMemory(n); |
| else |
| result = new char[n]; |
| |
| str_cpy_all(result, s, (Lng32) n); |
| } |
| |
| return result; |
| } |
| |
| IpcMessageObjSize ResultSetInfo::packedLength() |
| { |
| IpcMessageObjSize result = 0; |
| result += sizeof(stmtID_); |
| result += sizeof(cntxID_); |
| result += packedStringLength(proxySyntax_); |
| |
| return result; |
| } |
| |
| IpcMessageObjSize ResultSetInfo::pack(IpcMessageBufferPtr &buffer) const |
| { |
| IpcMessageObjSize result = 0; |
| result += packIntoBuffer(buffer, stmtID_); |
| result += packIntoBuffer(buffer, cntxID_); |
| result += packCharStarIntoBuffer(buffer, proxySyntax_); |
| |
| return result; |
| } |
| |
| void ResultSetInfo::unpack(IpcConstMessageBufferPtr &buffer) |
| { |
| |
| unpackBuffer(buffer, stmtID_); |
| unpackBuffer(buffer, cntxID_); |
| unpackBuffer(buffer, proxySyntax_, heap_); |
| } |
| |
| NABoolean ResultSetInfo::checkResultSetInfoClass(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr &buf) |
| { |
| IpcConstMessageBufferPtr lastByte = buf + size - 1; |
| |
| // check the buffer for stmtID_ |
| if (!checkBuffer(buf, sizeof(void *), lastByte)) |
| { |
| ipcIntegrityCheckEpilogue(FALSE); |
| return FALSE; |
| } |
| |
| // check the buffer after cntxID_ |
| if (!checkBuffer(buf, sizeof(ComUInt32), lastByte)) |
| { |
| ipcIntegrityCheckEpilogue(FALSE); |
| return FALSE; |
| } |
| |
| // check for proxySyntax_, it is stored as (long length, *char) |
| if (!(checkCharStarInBuffer(buf, sameEndianness, lastByte))) |
| return FALSE; |
| |
| return TRUE; |
| } |
| |
| ResultSetInfo& ResultSetInfo::operator=(const ResultSetInfo &src) |
| { |
| // Nothing to do if source and target are same |
| if (this == &src) |
| return *this; |
| |
| deallocateString(proxySyntax_); |
| proxySyntax_ = allocateString(src.proxySyntax_); |
| |
| stmtID_ = src.stmtID_; |
| cntxID_ = src.cntxID_; |
| |
| return *this; |
| } |
| |
| //---------------------------------------------------------------------- |
| // class UdrRSInfoMsg |
| //---------------------------------------------------------------------- |
| UdrRSInfoMsg::UdrRSInfoMsg(ComUInt32 numRS, NAMemory *heap) |
| : UdrMessageObj(UDR_MSG_RS_INFO, UdrRSInfoMsgVersionNumber, heap), |
| numRS_(numRS), resultSetInfo_(NULL) |
| { |
| allocateResultSetInfo(); |
| } |
| |
| UdrRSInfoMsg::~UdrRSInfoMsg() |
| { |
| deallocateResultSetInfo(); |
| } |
| |
| ResultSetInfo &UdrRSInfoMsg::getRSInfo(ComUInt32 i) const |
| { |
| UdrExeAssert(resultSetInfo_ && numRS_ > i, |
| "An invalid index was passed to UdrRSInfoMsg::getRSInfo()"); |
| return resultSetInfo_[i]; |
| } |
| |
| void UdrRSInfoMsg::setRSInfo(ComUInt32 i, const ResultSetInfo &info) |
| { |
| UdrExeAssert(resultSetInfo_ && numRS_ > i, |
| "An invalid index was passed to UdrRSInfoMsg::setRSInfo()"); |
| resultSetInfo_[i] = info; |
| } |
| |
| void UdrRSInfoMsg::allocateResultSetInfo() |
| { |
| deallocateResultSetInfo(); |
| |
| // Allocate memory for resultSetInfo_ field |
| ComUInt32 n = numRS_ * sizeof(ResultSetInfo); |
| resultSetInfo_ = (ResultSetInfo *) (n ? allocateMemory(n) : NULL); |
| memset(resultSetInfo_, 0, n); |
| |
| for (ComUInt32 i=0; i < numRS_; i++) |
| resultSetInfo_[i].setHeap(getHeap()); |
| } |
| |
| void UdrRSInfoMsg::deallocateResultSetInfo() |
| { |
| if (resultSetInfo_) |
| { |
| for (ComUInt32 i=0; i < numRS_; i++) |
| { |
| deallocateMemory(resultSetInfo_[i].proxySyntax_); |
| } |
| } |
| deallocateMemory((char *) resultSetInfo_); |
| resultSetInfo_ = NULL; |
| } |
| |
| IpcMessageObjSize UdrRSInfoMsg::packedLength() |
| { |
| IpcMessageObjSize result = super::packedLength(); |
| result += sizeof(numRS_); |
| |
| for (ComUInt32 i=0; i<numRS_; i++) |
| result += getRSInfo(i).packedLength(); |
| |
| return result; |
| } |
| |
| IpcMessageObjSize UdrRSInfoMsg::packObjIntoMessage(IpcMessageBufferPtr buffer) |
| { |
| IpcMessageObjSize result = 0; |
| |
| result += packUdrBaseClass(buffer); |
| |
| #ifdef UDR_DEBUG |
| char *val = getenv("MXUDR_CORRUPT_UDRRSINFOMSG"); |
| if (val && val[0]) |
| { |
| result += packIntoBuffer(buffer, (numRS_+ 1)); |
| } else |
| result += packIntoBuffer(buffer, numRS_); |
| |
| #else |
| result += packIntoBuffer(buffer, numRS_); |
| #endif |
| |
| for (ComUInt32 i=0; i<numRS_; i++) |
| { |
| result += getRSInfo(i).pack(buffer); |
| } |
| |
| return result; |
| } |
| |
| void UdrRSInfoMsg::unpackObj(IpcMessageObjType objType, |
| IpcMessageObjVersion objVersion, |
| NABoolean sameEndianness, |
| IpcMessageObjSize objSize, |
| IpcConstMessageBufferPtr buffer) |
| { |
| unpackUdrBaseClass(buffer); |
| |
| unpackBuffer(buffer, numRS_); |
| |
| allocateResultSetInfo(); |
| |
| for (ComUInt32 i=0; i<numRS_; i++) |
| { |
| getRSInfo(i).unpack(buffer); |
| } |
| } |
| |
| NABoolean UdrRSInfoMsg::checkObj(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr buffer) const |
| { |
| return checkUdrBaseClass(t, v, sameEndianness, size, buffer); |
| } |
| |
| NABoolean UdrRSInfoMsg::checkUdrBaseClass(IpcMessageObjType t, |
| IpcMessageObjVersion v, |
| NABoolean sameEndianness, |
| IpcMessageObjSize size, |
| IpcConstMessageBufferPtr &buf) const |
| { |
| IpcConstMessageBufferPtr lastByte = buf + size - 1; |
| IpcConstMessageBufferPtr oldBuf = buf; |
| |
| if (!super::checkUdrBaseClass(t, v, sameEndianness, size, buf)) |
| return FALSE; |
| |
| // We need to adjust size since it will be used by |
| // ResultSetInfo::checkResultSetInfoClass() |
| size -= (buf - oldBuf); |
| oldBuf = buf; |
| |
| ComUInt32 numRS = 0; |
| if (!checkAndUnpackBuffer(buf, sizeof(numRS), |
| (char *) &numRS, lastByte)) |
| { |
| ipcIntegrityCheckEpilogue(FALSE); |
| return FALSE; |
| } |
| |
| for (ComUInt32 i=0; i<numRS; i++) |
| { |
| size -= (buf - oldBuf); |
| oldBuf = buf; |
| if (!(ResultSetInfo::checkResultSetInfoClass(t, v, sameEndianness, size, buf))) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |