/**********************************************************************
// @@@ 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:         spinfo.cpp
 * Description:  The SPInfo and SPList Classes
 *               Methods for SPInfo and SPList classes
 *
 *
 * Created:      01/01/2001
 * Language:     C++
 *
 *****************************************************************************
 */


#include "Platform.h"
#include "spinfo.h"
#include "UdrStreams.h"
#include "udrutil.h"
#include "str.h"
#include <time.h>
#include "UdrResultSet.h"
#include "LmRoutine.h"
#include "LmParameter.h"
#include "LmRoutineCSqlRowTM.h"
#include "sql_buffer.h"
#include "UdrResultSet.h"
#include "ex_queue.h"
#include "ComRtUtils.h"
#include "UdfDllInteraction.h"

#include "sqlcli.h"
#include "sqludr.h"
#include "udrdecs.h"


#include "dtm/tm.h"
 
extern void ServerDebug(const char *, ...);
extern void doMessageBox(UdrGlobals *UdrGlob, Int32 trLevel,
                         NABoolean moduleType, const char *moduleName);

extern void backoutTupps(SqlBuffer &b, Lng32 numTuppsBefore);

extern NABoolean allocateReplyRowAndEOD(UdrGlobals *UdrGlob,
                                SqlBuffer &replyBuffer,
                                queue_index parentIndex,
                                char *&replyData,
                                Int32 rowLen,
                                ControlInfo *&newControlInfo);
extern NABoolean allocateEODRow(UdrGlobals *UdrGlob,
                         SqlBuffer &replyBuffer,
                         queue_index parentIndex);

extern NABoolean convertReplyRowToErrorRow(SqlBuffer *sqlBuf,
                                    Lng32 numTuppsBefore,
                                    queue_index requestQueueIndex,
                                    UdrServerDataStream &msgStream,
                                    UdrGlobals *UdrGlob);

//**********************************************************
// SPInfo constructor & Destructor
//
//
//**********************************************************
SPInfo::SPInfo(UdrGlobals *udrGlobals,
               NAHeap *heapPtr,
               const UdrHandle &udrHandle,
               char *pSqlName,
               char *pExternalName,
               char *pRoutineSig,
               char *pContainerName,
               char *pExternalPathName,
               char *pLibrarySqlName,
               ComUInt32 pNumParams,
	       ComUInt32 pNumInParams,
	       ComUInt32 pNumOutParams,
               ComUInt32 pMaxRSets,
               ComRoutineTransactionAttributes ptransactionAttrs,
               ComRoutineSQLAccess psqlAccessMode,
	       ComRoutineLanguage pLanguage,
	       ComRoutineParamStyle pParamStyle,
	       NABoolean pIsolate,
	       NABoolean pCallOnNull,
	       NABoolean pExtraCall,
	       NABoolean pDeterministic,
               ComRoutineExternalSecurity pExternalSecurity,
               Int32     pRoutineOwnerId,
               ComUInt32 requestBufferSize,
               ComUInt32 replyBufferSize,
               ComUInt32 requestRowSize,
               ComUInt32 replyRowSize,
               ComDiagsArea &d,
               char *parentQid)
      : udrGlobals_(udrGlobals),
        udrHandle_(udrHandle),
        lmHandle_(FALSE),
#ifdef UDR_MULTIPLE_CONTEXTS
        cliContextHandle_(0),
#endif
        spInfoState_(INITIAL),
        transactionAttrs_(ptransactionAttrs),
        sqlAccessMode_(psqlAccessMode),
	numParameters_(pNumParams),
	numInParams_(pNumInParams),
  	numOutParams_(pNumOutParams),
	lmParameters_(NULL),
	returnValue_(NULL),
	sqlName_(NULL),
	externalName_(NULL),
	routineSig_(NULL),
	containerName_(NULL),
	externalPathName_(NULL),
	librarySqlName_(NULL),
	numCalls_(0),
        lastCallTs_(0),
	language_(pLanguage),
	paramStyle_(pParamStyle),
	isolate_(pIsolate),
	callOnNull_(pCallOnNull),
	extraCall_(pExtraCall),
	deterministic_(pDeterministic),
	externalSecurity_(pExternalSecurity),
	routineOwnerId_(pRoutineOwnerId),
	maxNumResultSets_(pMaxRSets),
	numResultSets_(0),
   	requestBufferSize_(requestBufferSize),
	replyBufferSize_(replyBufferSize),
	requestRowSize_(requestRowSize),
	replyRowSize_(replyRowSize),
        dataStream_(NULL),
        txStream_(NULL),
        currentRequest_(NULL),
        rsList_(heapPtr),
        udrHeapPtr_(heapPtr),
        numTableInfo_(0),
        tableInfo_(NULL),
        sqlBufferScalar_(NULL),
        sqlBufferTVF_(NULL),
        parentIndex_(0),
        parentQid_(NULL),
        rowDiags_(NULL)
{
  doMessageBox(udrGlobals_, TRACE_SHOW_DIALOGS,
               udrGlobals_->showSPInfo_, "SPInfo Constructor");


  str_cpy_all(&eyeCatcher_[0], EYE_SP, 4);
  udrGlobals_->getSPList()->addToSPList(this);
  lastCallTs_ = createUniqueIdentifier();

  if (pSqlName == NULL)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_ERROR);
    d << DgString0("Stored procedure SQL Name is NULL");
    // EH_THROW(EH_INTERNAL_EXCEPTION);
  }
  else
  {
    assignStringMember(sqlName_, pSqlName);
  }
  
  if (pExternalName == NULL)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_ERROR);
    d << DgString0("Stored procedure external name is NULL");
    // EH_THROW(EH_INTERNAL_EXCEPTION);
  }
  else
  {
    assignStringMember(externalName_, pExternalName);
  }
  
  if (pRoutineSig == NULL)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_ERROR);
    d << DgString0("Stored procedure Routine Signature is NULL");
    // EH_THROW(EH_INTERNAL_EXCEPTION);
  }
  else
  {
    assignStringMember(routineSig_, pRoutineSig);
  }
  
  if (pContainerName == NULL)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_ERROR);
    d << DgString0("Stored procedure Container Name is NULL");
    // EH_THROW(EH_INTERNAL_EXCEPTION);
  }
  else
  {
    assignStringMember(containerName_, pContainerName);
  }
  
  if (pExternalPathName == NULL)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_ERROR);
    d << DgString0("Stored procedure External Path Name is NULL");
    // EH_THROW(EH_INTERNAL_EXCEPTION);
  }
  else
  {
    assignStringMember(externalPathName_, pExternalPathName);
  }

  if (pLibrarySqlName == NULL)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_ERROR);
    d << DgString0("Stored procedure library SQL Name is NULL");
    // EH_THROW(EH_INTERNAL_EXCEPTION);
  }
  else
  {
    assignStringMember(librarySqlName_, pLibrarySqlName);
  }
  
  assignStringMember(parentQid_, parentQid);

  if (getNumParameters() > 0)
  {
    ComUInt32 lmParamBytes = getNumParameters() * sizeof(LmParameter);

    lmParameters_ = (LmParameter *) udrHeapPtr_->allocateMemory(lmParamBytes);
    memset(lmParameters_, 0, lmParamBytes);
  }

  // Now we create the data stream that will be used by this SPInfo
  // instance. All we need to do is call a constructor, but first there
  // is logic to compute data buffer sizes.
  //
  // We currently assume the following about data buffer sizes:
  // - On a given stream, request and reply buffers are the same size
  // - All message objects are aligned on 8-byte boundaries
  // - A data request consists of a UdrDataHeader followed by a
  //   UdrDataBuffer
  // - The sql_buffer size for the stream was sent to the server as
  //   part of the load request and is being stored inside this SPInfo
  //   object
  // - Data buffers contain a pad for diagnostics. The pad does not
  //   cause extra bytes to go on the wire. It allows data plus
  //   diags to exist in a single reply buffer which eliminates the
  //   need for the client to send a continue request to retrieve diags.
  //
  IpcMessageObjSize sqlBufSize = 0;
  IpcMessageObjSize maxBufSize = 0;

  sqlBufSize = MAXOF (
    getRequestBufferSize(),
    getReplyBufferSize()
    );

  maxBufSize += sizeof(UdrDataHeader);
  IpcMessageBuffer::alignOffset(maxBufSize);

  maxBufSize += sizeof(UdrDataBuffer);
  IpcMessageBuffer::alignOffset(maxBufSize);

  maxBufSize += sqlBufSize;
  IpcMessageBuffer::alignOffset(maxBufSize);

  Lng32 diagsPad = 1000;

#ifdef _DEBUG
  //
  // In a debug build we can get the pad size from the Java system
  // property UDR_BUFFER_PAD.
  //
  Lng32 tempPad = 0;
  if (udrGlobals_ && udrGlobals_->getJavaLM())
  {
    if (getLmProperty(*(udrGlobals_->getJavaLM()),
                      "UDR_BUFFER_PAD", tempPad, NULL))
    {
      diagsPad = tempPad;
    }
  }
#endif // _DEBUG

  maxBufSize += diagsPad;
  IpcMessageBuffer::alignOffset(maxBufSize);

  //
  // Normally all data requests and replies involve a single request
  // buffer and a single output buffer. If diags do not fit into a
  // data reply buffer then a second reply buffer is created and is
  // returned to the client as the response to a continue request. To
  // allow for continue requests/responses our server-side data streams
  // can have up to 2 send buffers.
  //
  dataStream_ = new (udrHeapPtr_) UdrServerDataStream (
    udrGlobals_->getIpcEnvironment(),
    2,           // long sendBufferLimit
    1,           // long inUseBufferLimit
    maxBufSize,  // IpcMessageObjSize bufferSize
    udrGlobals_,
    this
    );

  txStream_ = new (udrHeapPtr_) UdrServerReplyStream(
    udrGlobals_->getIpcEnvironment(),
    udrGlobals_,
    UDR_STREAM_SERVER_REPLY,
    UdrServerReplyStreamVersionNumber); 

} // SPInfo::SPInfo()

SPInfo::SPInfo(UdrGlobals *udrGlobals,
               NAHeap *heapPtr,
               const UdrHandle &udrHandle)
      : udrGlobals_(udrGlobals),
        udrHandle_(udrHandle),
        lmHandle_(FALSE),
#ifdef UDR_MULTIPLE_CONTEXTS
        cliContextHandle_(0),
#endif
        spInfoState_(INITIAL),
        transactionAttrs_(COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE),
        sqlAccessMode_(COM_UNKNOWN_ROUTINE_SQL_ACCESS),
	numParameters_(0),
	numInParams_(0),
  	numOutParams_(0),
	lmParameters_(NULL),
	returnValue_(NULL),
	sqlName_(NULL),
	externalName_(NULL),
	routineSig_(NULL),
	containerName_(NULL),
	externalPathName_(NULL),
	librarySqlName_(NULL),
	numCalls_(0),
        lastCallTs_(0),
	language_(COM_UNKNOWN_ROUTINE_LANGUAGE),
	paramStyle_(COM_UNKNOWN_ROUTINE_PARAM_STYLE),
	isolate_(FALSE),
	callOnNull_(FALSE),
	extraCall_(FALSE),
	deterministic_(FALSE),
	externalSecurity_(COM_ROUTINE_EXTERNAL_SECURITY_INVOKER),
	routineOwnerId_(0),
	maxNumResultSets_(0),
	numResultSets_(0),
   	requestBufferSize_(0),
	replyBufferSize_(0),
	requestRowSize_(0),
	replyRowSize_(0),
        dataStream_(NULL),
        txStream_(NULL),
        currentRequest_(NULL),
        rsList_(heapPtr),
        udrHeapPtr_(heapPtr),
        numTableInfo_(0),
        tableInfo_(NULL),
        sqlBufferScalar_(NULL),
        sqlBufferTVF_(NULL),
        parentIndex_(0),
        parentQid_(NULL),
        rowDiags_(NULL)
{
  str_cpy_all(&eyeCatcher_[0], EYE_SP , 4);
  lastCallTs_ = createUniqueIdentifier();
  udrGlobals_->getSPList()->addToSPList(this);
}

SPInfo::~SPInfo()
{
  udrGlobals_->getSPList()->removeFromSPList(this);

  if (dataStream_) delete dataStream_;

  if (txStream_) delete txStream_;

  //
  // Note: we do not bother checking for NULL inputs to the delete and
  // deallocate calls below because they are no-ops when the input is
  // NULL.
  //

  if (udrHeapPtr_ == NULL)
  {
    delete [] sqlName_;
    delete [] externalName_;
    delete [] routineSig_;
    delete [] containerName_;
    delete [] externalPathName_;
    delete [] librarySqlName_;
    if (parentQid_)
      delete [] parentQid_;
  }
  else
  {
    udrHeapPtr_->deallocateMemory(sqlName_);
    udrHeapPtr_->deallocateMemory(externalName_);
    udrHeapPtr_->deallocateMemory(routineSig_);
    udrHeapPtr_->deallocateMemory(containerName_);
    udrHeapPtr_->deallocateMemory(externalPathName_);
    udrHeapPtr_->deallocateMemory(librarySqlName_);
    if (parentQid_)
      udrHeapPtr_->deallocateMemory(parentQid_);

    // Deallocate the LmParameter array
    if (lmParameters_)
    {
      for (ComUInt32 i = 0; i < numParameters_; i++)
      {
        LmParameter &p = lmParameters_[i];
        p.freeResources();
      }
      udrHeapPtr_->deallocateMemory(lmParameters_);
    }

    //Deallocate tableInfo
    if(tableInfo_)
    {
      for(ComUInt32 i = 0; i < numTableInfo_; i++)
      {
        tableInfo_[i].freeResources(udrHeapPtr_);
      }
      udrHeapPtr_->deallocateMemory(tableInfo_);
    }
  }

  if (rowDiags_)
    rowDiags_->decrRefCount();
  
} // SPInfo::~SPInfo()

void SPInfo::assignStringMember(
		char *&memberBuff,
		const char *const src)
{
	if (udrHeapPtr_ != NULL)
	{
		udrHeapPtr_->deallocateMemory(memberBuff);
		memberBuff = NULL;
	}
	else
	{
		delete [] memberBuff;
		memberBuff = NULL;
	}

	// if src is non-NULL then we need to create a buff, copy it over...
	if (src != NULL)
	{
          UInt32 buffsize = str_len(src) + 1;
          if (udrHeapPtr_ != NULL)
          {
            memberBuff = (char *) (udrHeapPtr_->allocateMemory(buffsize));
          }
          else
          {
            memberBuff = new char[buffsize];
          }
          
          UDR_ASSERT(memberBuff != NULL, "Out of Memory");
          str_cpy(memberBuff, src, (Lng32) buffsize);
          memberBuff[buffsize-1] = '\0';
	}
        
}  // assignStringMember

void SPInfo::setInParam(ComUInt32 i, const UdrParameterInfo &info)
{
  UDR_ASSERT(numInParams_ > i,
             "An invalid index was passed to SPInfo::setInParam()");
  initLmParameter(info, TRUE);
}

void SPInfo::setOutParam(ComUInt32 i,
                         const UdrParameterInfo &info)
{
  UDR_ASSERT(numOutParams_ > i,
             "An invalid index was passed to SPInfo::setOutParam()");
  initLmParameter(info, FALSE);
}

// setUdrContext
NABoolean SPInfo::setUdrContext(ComDiagsArea &d) const
{

  return TRUE;

} // setUdrContext

// Set corresponding LmParameter using given UdrParamterInfo object
void SPInfo::initLmParameter(const UdrParameterInfo &pInfo,
                             NABoolean isInput)
{
  LmParameter &lmp = getLmParameter(pInfo.getPosition());

  // Cases to consider
  //
  // a. This is an IN parameter. isInput will be TRUE. All LmParameter
  // fields must be initialized.
  // 
  // b. This is an OUT parameter. isInput will be FALSE. All
  // LmParameter fields must be initialized.
  // 
  // c. This is an INOUT parameter and isInput is TRUE. All
  // LmParameter fields must be initialized.
  //
  // d. This is an INOUT parameter and isInput is FALSE. We assume the
  // LmParameter instance is partially initialized because this method
  // was already called once for the same LmParameter with isInput set
  // to TRUE. Now we only need to initialze the output offset and
  // length fields of the LmParameter.

  // First, check for case d
  if (pInfo.isInOut() && isInput == FALSE)
  {
    lmp.setOutDataInfo(pInfo.getDataOffset(),
                       pInfo.getDataLength(),
                       pInfo.getNullIndicatorOffset(),
                       pInfo.getNullIndicatorLength(),
                       pInfo.getVCLenIndOffset(),
                       pInfo.getVCIndicatorLength());
  }

  else
  {
    // Cases a, b, and c. We need to initialize all fields of the
    // LmParameter.
    
    ComColumnDirection direction;
    if (pInfo.isInOut())
      direction = COM_INOUT_COLUMN;
    else if (pInfo.isIn())
      direction = COM_INPUT_COLUMN;
    else
      direction = COM_OUTPUT_COLUMN;
    
    // Determine the encoding charset. We will use =_SQL_MX_ISO_MAPPING
    // define value if the param's charset is ISO88591.
    CharInfo::CharSet charset = (CharInfo::CharSet) pInfo.getEncodingCharSet();
    if (charset == CharInfo::ISO88591)
      charset = udrGlobals_->getIsoMapping();
    
    if (isInput)
    {
      lmp.init((ComFSDataType) pInfo.getFSType(),
               pInfo.getPrec(),
               pInfo.getScale(),
               charset,
               (CharInfo::Collation) pInfo.getCollation(),
               direction,
               pInfo.isLmObjType(),
               RS_NONE,
               pInfo.getDataOffset(),
               pInfo.getDataLength(),
               pInfo.getNullIndicatorOffset(),
               pInfo.getNullIndicatorLength(),
               pInfo.getVCLenIndOffset(),
               pInfo.getVCIndicatorLength(),
               0, 0, 0, 0, 0, 0, // output offsets and lengths
               pInfo.getParamName());
    }
    else
    {
      lmp.init((ComFSDataType) pInfo.getFSType(),
               pInfo.getPrec(),
               pInfo.getScale(),
               charset,
               (CharInfo::Collation) pInfo.getCollation(),
               direction,
               pInfo.isLmObjType(),
               RS_NONE,
               0, 0, 0, 0, 0, 0, // input offsets and lengths
               pInfo.getDataOffset(),
               pInfo.getDataLength(),
               pInfo.getNullIndicatorOffset(),
               pInfo.getNullIndicatorLength(),
               pInfo.getVCLenIndOffset(),
               pInfo.getVCIndicatorLength(),
               pInfo.getParamName());
    }

  } // Cases a, b, and c
}

void SPInfo::resetLastCallTs()
{
  lastCallTs_ = createUniqueIdentifier();
  numCalls_++;
  numResultSets_ = 0;
}

// displaySPInfo - Used when tracing objects
void SPInfo::displaySPInfo(Lng32 indent)
{
  char ind[100];

  Lng32 indmax = (indent > 99) ? 99 : indent;

  Lng32 indIdx = 0;
  for (indIdx = 0; indIdx < indmax; indIdx++)
	  ind[indIdx] = ' ';
  ind[indIdx] = '\0';

  ServerDebug("%sContents of SPInfo:", ind );
  ServerDebug("%s---------------------", ind );
  ServerDebug("%sEye Catcher         : %s", ind, &eyeCatcher_ );
  ServerDebug("%sUdr Handle          : " INT64_SPEC , ind, udrHandle_ );
  if (lmHandle_ == NULL)
      ServerDebug("%sLM Handle           : NULL", ind);
  else
      ServerDebug("%sLM Handle           : %p", ind, lmHandle_ );

#ifdef UDR_MULTIPLE_CONTEXTS
  ServerDebug("%sCLI Context Handle  : %d", ind, (Lng32) cliContextHandle_ );
#endif // UDR_MULTIPLE_CONTEXTS
  ServerDebug("%sSPInfoState         : %i", ind, (Int32) spInfoState_ );  
  ServerDebug("%sTransaction Required     : %i", ind, (Int32) transactionAttrs_ );
  ServerDebug("%sSQL Access Mode     : %i", ind, (Int32) sqlAccessMode_ );
  ServerDebug("%sNumber of Params    : %u", ind, numParameters_ );
  ServerDebug("%sNumber of In Params : %u", ind, numInParams_ );
  ServerDebug("%sNumber of Out Params: %u", ind, numOutParams_ );

  ServerDebug("%sSQL Name            : %s", ind, sqlName_ );
  ServerDebug("%sExternal Name       : %s", ind, externalName_ );
  ServerDebug("%sRoutine SQL         : %s", ind, routineSig_ );
  ServerDebug("%sContainer Name      : %s", ind, containerName_ );
  ServerDebug("%sExternal Path Name  : %s", ind, externalPathName_ );
  ServerDebug("%sLibrary SQL Name    : %s", ind, librarySqlName_ );

  ServerDebug("%sNumber of Invokes   : " INT64_SPEC , ind, numCalls_ );
  ServerDebug("%sLast Call Timestamp : " INT64_SPEC , ind, lastCallTs_ );

  const char *lang = "***Unknown***";
  switch (language_)
  {
    case COM_UNKNOWN_ROUTINE_LANGUAGE:
	  lang = "***Unknown***"; break;

    case COM_LANGUAGE_JAVA:
	  lang = "Java"; break;

    case COM_LANGUAGE_C:
	  lang = "C"; break;

    case COM_LANGUAGE_CPP:
	  lang = "C++"; break;

    case COM_LANGUAGE_SQL:
	  lang = "SQL"; break;

    default:
	  break;
  }
  ServerDebug("%sLanguage            : %s", ind, lang );

  const char *paramStyle = "UNKNOWN";
  switch (paramStyle_)
  {
    case COM_UNKNOWN_ROUTINE_PARAM_STYLE:
	  paramStyle = "UNKNOWN"; break;

    case COM_STYLE_GENERAL:
	  paramStyle = "GENERAL"; break;

    case COM_STYLE_JAVA_CALL:
	  paramStyle = "JAVA"; break;

    case COM_STYLE_JAVA_OBJ:
	  paramStyle = "JAVA_OBJ"; break;

    case COM_STYLE_SQL:
	  paramStyle = "SQL"; break;

    case COM_STYLE_SQLROW:
          paramStyle = "SQLROW"; break;

    case COM_STYLE_SQLROW_TM:
          paramStyle = "SQLROW_TM"; break;

    case COM_STYLE_CPP_OBJ:
          paramStyle = "C++"; break;

    default:
	  break;
  }
  ServerDebug("%sParameter Style      : %s", ind, paramStyle );

  ServerDebug("%sIsolate?            : %i", ind, (Int32) isolate_ );
  ServerDebug("%sCallOnNull?         : %i", ind, (Int32) callOnNull_ );
  ServerDebug("%sExtraCall?          : %i", ind, (Int32) extraCall_ );
  ServerDebug("%sDeterministic?      : %i", ind, (Int32) deterministic_ );

  const char *externalSecurity = "UNKNOWN";
  switch (externalSecurity_)
  {
    case COM_ROUTINE_EXTERNAL_SECURITY_INVOKER:
      externalSecurity = "EXTERNAL SECURITY INVOKER";
      break;

    case COM_ROUTINE_EXTERNAL_SECURITY_DEFINER:
      externalSecurity = "EXTERNAL SECURITY DEFINER";
      break;

    default:
      break;
  }
  ServerDebug("%sExternalSecurity    : %s", ind, externalSecurity );
  ServerDebug("%sRoutine Owner Id    : %u", ind, routineOwnerId_ );

  ServerDebug("%sMax RSets           : %u", ind, maxNumResultSets_ );
  ServerDebug("%sNum Current RSets   : %u", ind, numResultSets_ );

  ServerDebug("%sRequest Buffer Size : %u", ind, requestBufferSize_ );
  ServerDebug("%sReply Buffer Size   : %u", ind, replyBufferSize_ );

  ServerDebug("%sRequest Row Size    : %u", ind, requestRowSize_ );
  ServerDebug("%sReply Row Size      : %u", ind, replyRowSize_ );

  if (dataStream_ == NULL)
      ServerDebug("%sDataStreamPtr       : NULL", ind);
  else
      ServerDebug("%sDataStreamPtr       : %p", ind, dataStream_ );

  if (udrHeapPtr_ == NULL)
      ServerDebug("%sHeapPtr             : NULL", ind);
  else
      ServerDebug("%sHeapPtr             : %p", ind, udrHeapPtr_ );

  ServerDebug("");

} // SPInfo::displaySPInfo

void SPInfo::displaySPInfoId(Lng32 indent)
{
  char ind[100];

  Lng32 indmax = (indent > 99) ? 99 : indent;
  
  Lng32 indIdx = 0;
  for (indIdx = 0; indIdx < indmax; indIdx++)
    ind[indIdx] = ' ';
  ind[indIdx] = '\0';
  
  ServerDebug("%sObject ID         : " INT64_SPEC , ind, udrHandle_ );

} // SPInfo::displaySPInfoId

// createUniqueIdentifier
Int64 SPInfo::createUniqueIdentifier()
{
  Int64 result;
  //
  // During R1.6 testing it was discovered that JULIANTIMESTAMP was
  // not always returning unique values on Windows. We believe this is
  // due to occasional clock synchronization performed by the NonStop
  // Cluster services. To avoid the duplicate timestamp problem we use
  // a sequential counter to generate process-wide unique identifiers.
  //
  result = udrGlobals_->nextUniqueIdentifier_++;
  return result;
}


// releaseSP
Lng32 SPInfo::releaseSP(NABoolean reportErrors,
                       ComDiagsArea &d)
{
  const char *moduleName = "SPInfo releaseSP";
  char errorText[MAXERRTEXT];
  LmResult lmResult = LM_OK;
  LmRoutine *lmr;

  doMessageBox(udrGlobals_, TRACE_SHOW_DIALOGS,
               udrGlobals_->showSPInfo_, moduleName);

  // Deallocate UdrResultSet objects
  for (ComUInt32 index = 0; index < rsList_.entries(); index++)
  {
    UdrResultSet *rs = rsList_[index];
    NADELETE(rs, UdrResultSet, udrHeapPtr_);
  }

  rsList_.clear();

  // drop LM Handle...
  lmr = this->getLMHandle();
  if (lmr != NULL)
  {
    lmResult = udrGlobals_->getLM(getLanguage())->putRoutine(lmr, &d);

    if (lmResult == LM_ERR)
    {
      if (reportErrors)
      {
        if (udrGlobals_->verbose_ &&
            udrGlobals_->traceLevel_ >= TRACE_DATA_AREAS &&
            udrGlobals_->showSPInfo_)
        {

          sprintf(errorText,
                  "[UdrServ (%.30s)]  LM putRoutine call resulted in error.",
                  moduleName);
          ServerDebug(errorText);
        }
      }
      udrGlobals_->numErrLMCall_++;
    }
  } // if (lmr != NULL)

  setLMHandle(NULL);
  delete this;
  return 0;
    
} // SPInfo::releaseSP

const char *SPInfo::getSPInfoStateString() const
{
  switch (spInfoState_)
  {
    case INITIAL:                 return "INITIAL";
    case LOADED:                  return "LOADED";
    case LOAD_FAILED:             return "LOAD_FAILED";
    case INVOKED:                 return "INVOKED";
    case INVOKE_FAILED:           return "INVOKE_FAILED";
    case INVOKED_EMITROWS:        return "INVOKED_EMITROWS";
    case INVOKED_GETROWS:         return "INVOKED_GETROWS";
    case INVOKED_GETROWS_FAILED:  return "INVOKED_GETROWS_FAILED";
    case UNLOADING:               return "UNLOADING";
    default:
      return ComRtGetUnknownString((Int32) spInfoState_);
  }
}

// (Re)Initializes rsList_ field after a udr is invoked.
NABoolean SPInfo::setupUdrResultSets(ComDiagsArea &d)
{
  ComUInt32 numRS = lmHandle_->getNumResultSets();

  // If UDR invocation produced no resultsets, just return
  if ( numRS <= 0)
    return TRUE;

  for (ComUInt32 index = 0; index < numRS; index++)
  {
    LmResultSet *lmRS = lmHandle_->getLmResultSet(index);

    if (rsList_.entries() < index+1)
    {
      // We do not have a UdrResultSet object at 'index' location
      // So create one & insert in rsList_.
      UdrResultSet *udrRS = new (udrHeapPtr_) UdrResultSet(this, lmRS, d);
      if (d.getNumber(DgSqlCode::ERROR_) > 0)
      {
        delete udrRS;
        return FALSE;
      }

      rsList_.insert(udrRS);
    }
    else
    {
      // A UdrResultSet object exists at 'index' location, lets update it
      if (rsList_[index]->reInit(lmRS, d) != 0)
        return FALSE;
    }
  }


  setNumResultSets(rsList_.entries());
  return TRUE;
}

SQLSTMT_ID *SPInfo::executeSqlStmt(const char *sql_str, ComDiagsArea &d)
{
  Lng32 retcode = 0;

  retcode = SQL_EXEC_ClearDiagnostics(NULL);
  if (retcode < 0)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_CLI_ERROR)
      << DgString0("SQL_EXEC_ClearDiagnostics")
      << DgInt0(retcode);

    return NULL;
  }

  // Allocate a SQL statement
  SQLMODULE_ID *module = new (udrHeapPtr_) SQLMODULE_ID;
  memset(module, 0, sizeof(SQLMODULE_ID));
  module->module_name = 0;

  SQLSTMT_ID *stmt = new (udrHeapPtr_) SQLSTMT_ID;
  memset(stmt, 0, sizeof(SQLSTMT_ID));
  stmt->name_mode = stmt_handle;
  stmt->module = module;
  stmt->identifier = 0;
  stmt->handle = 0;

  retcode = SQL_EXEC_AllocStmt(stmt, 0);
  if (retcode < 0)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_CLI_ERROR)
      << DgString0("SQL_EXEC_AllocStmt")
      << DgInt0(retcode);

    udrHeapPtr_->deallocateMemory(module);
    udrHeapPtr_->deallocateMemory(stmt);
    return NULL;
  }

  // Allocate a descriptor to hold the sql statement source
  SQLMODULE_ID descmodule;
  memset(&descmodule, 0, sizeof(SQLMODULE_ID));
  descmodule.module_name = 0;

  SQLDESC_ID sqlsrc_desc;
  memset(&sqlsrc_desc, 0, sizeof(SQLDESC_ID));
  sqlsrc_desc.name_mode = desc_handle;
  sqlsrc_desc.module = &descmodule;
  sqlsrc_desc.identifier = 0;
  sqlsrc_desc.handle = 0;
  retcode = SQL_EXEC_AllocDesc(&sqlsrc_desc, 1);
  if (retcode < 0)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_CLI_ERROR)
      << DgString0("SQL_EXEC_AllocDesc")
      << DgInt0(retcode);

    SQL_EXEC_DeallocStmt(stmt);

    udrHeapPtr_->deallocateMemory(module);
    udrHeapPtr_->deallocateMemory(stmt);
    return NULL;
  }

  SQLDESC_ITEM desc_items[3];

  desc_items[0].item_id = SQLDESC_TYPE;
  desc_items[0].entry = 1;
  desc_items[0].num_val_or_len = SQLTYPECODE_VARCHAR;

  desc_items[1].item_id = SQLDESC_VAR_PTR;
  desc_items[1].entry = 1;
  desc_items[1].num_val_or_len = (Long) sql_str;

  desc_items[2].item_id = SQLDESC_LENGTH;
  desc_items[2].entry = 1;
  desc_items[2].num_val_or_len = (Lng32) strlen(sql_str) + 1;

  retcode = SQL_EXEC_SetDescItems2(&sqlsrc_desc, 3, desc_items);
  if (retcode < 0)
  {
    d << DgSqlCode(-UDR_ERR_INTERNAL_CLI_ERROR)
      << DgString0("SQL_EXEC_SetDescItem2")
      << DgInt0(retcode);

    SQL_EXEC_DeallocDesc(&sqlsrc_desc);
    SQL_EXEC_DeallocStmt(stmt);

    udrHeapPtr_->deallocateMemory(module);
    udrHeapPtr_->deallocateMemory(stmt);
    return NULL;
  }

  // Prepare the statement; stmt has the prepared plan
  retcode = SQL_EXEC_Prepare(stmt, &sqlsrc_desc);
  if (retcode < 0)
  {
    SQL_EXEC_MergeDiagnostics_Internal(d);

    d << DgSqlCode(-UDR_ERR_INTERNAL_CLI_ERROR)
      << DgString0("SQL_EXEC_Prepare")
      << DgInt0(retcode);

    SQL_EXEC_DeallocDesc(&sqlsrc_desc);
    SQL_EXEC_DeallocStmt(stmt);

    udrHeapPtr_->deallocateMemory(module);
    udrHeapPtr_->deallocateMemory(stmt);
    return NULL;
  }

  // Execute the statement
  retcode = SQL_EXEC_ExecClose(stmt, 0, 0, 0);
  if (retcode < 0)
  {
    SQL_EXEC_MergeDiagnostics_Internal(d);

    d << DgSqlCode(-UDR_ERR_INTERNAL_CLI_ERROR)
      << DgString0("SQL_EXEC_Exec")
      << DgInt0(retcode);

    SQL_EXEC_DeallocDesc(&sqlsrc_desc);
    SQL_EXEC_DeallocStmt(stmt);

    udrHeapPtr_->deallocateMemory(module);
    udrHeapPtr_->deallocateMemory(stmt);
    return NULL;
  }

  SQL_EXEC_DeallocDesc(&sqlsrc_desc);

  return stmt;
}

// loadUdrResultSet() loads a UdrResultSet object at given location.
// When a UdrResultSet is loaded, it will have all the column information
// (got from executor) filled in.
void SPInfo::loadUdrResultSet(ComUInt32 index,
                              RSHandle handle,
                              ComUInt32 numRSCols,
                              ComUInt32 rowSize,
                              ComUInt32 bufferSize,
                              UdrParameterInfo *columnDesc,
                              ComDiagsArea &d)
{
  const char *moduleName = "SPInfo::loadUdrResultSet";
  UdrResultSet *rs = rsList_[index];

  if (udrGlobals_->verbose_ &&
      udrGlobals_->traceLevel_ >= TRACE_DETAILS &&
      udrGlobals_->showRSLoad_)
    ServerDebug("[Udrserv (%s)] Loading ResultSet at position %d",
                moduleName, index + 1);

  NABoolean result =
    rs->load(handle, numRSCols, rowSize, bufferSize, columnDesc, d);

  if (udrGlobals_->verbose_ &&
      udrGlobals_->traceLevel_ >= TRACE_DETAILS &&
      udrGlobals_->showRSLoad_)
  ServerDebug("[Udrserv (%s)] ResultSet load %s",
              moduleName, (result) ? "succeded" : "failed");

  return ;
}

UdrResultSet *SPInfo::getUdrResultSetByHandle(RSHandle handle)
{
  UdrResultSet *rs = NULL;

  ComUInt32 entries = rsList_.entries();
  for (ComUInt32 i = 0; i < entries; i++)
  {
    rs = rsList_.at(i);
    if (rs != NULL && rs->getRSHandle() == handle)
      return rs;
  }

  return rs;
}

void SPInfo::prepareForReinvoke(ComDiagsArea *diags)
{
  ComUInt32 index;

  // Reset UdrResultSet object on rsList_ for UDR reinvocation.
  // This will reset all the fields that are generated by udrserv.
  for (index = 0; index < rsList_.entries(); index++)
  {
    UdrResultSet *rs = rsList_[index];
    rs->prepareForReinvoke();
  }

  // Let LM cleanup any resources.
  lmHandle_->cleanupResultSets(diags);

}

// If there is an active Enter Tx request for this SP, activate
// it's transaction
NABoolean SPInfo::activateTransaction()
{
  const char *moduleName = "SPInfo::activateTransaction";
  NABoolean result = FALSE;

#ifdef UDR_DEBUG
  if (udrGlobals_->verbose_)
  {
    Int64 tx_id = 0;
    short tmfRetcode = GETTRANSID((short*) &tx_id);

    ServerDebug("[UdrServ (%s)] Activating transaction...", moduleName);
    ServerDebug("         Before setting transaction...");
    ServerDebug("           GETTRANSID returned %d. Transid is %Ld.",
                 tmfRetcode, tx_id);
  }
#endif

  if (txStream_->getState() == IpcMessageStream::RECEIVED)
  {
    txStream_->activateCurrentMsgTransaction();
    result = TRUE;
  }

#ifdef UDR_DEBUG
  if (udrGlobals_->verbose_)
  {
    Int64 tx_id = 0;
    short tmfRetcode = GETTRANSID((short*) &tx_id);

    ServerDebug("         After setting transaction...");
    ServerDebug("           GETTRANSID returned %d. Transid is %Ld.",
                 tmfRetcode, tx_id);

    ServerDebug("[UdrServ (%s)] Done", moduleName);
  }
#endif

  return result;

} // SPInfo::activateTransaction()

void SPInfo::replyToEnterTxMsg(NABoolean doneWithRS)
{
  const char *moduleName = "SPInfo::replyToEnterTxMsg";

  NABoolean doTrace =
    (udrGlobals_->verbose_ && udrGlobals_->traceLevel_ >= TRACE_IPMS) ?
    TRUE : FALSE;

  if (doTrace)
  {
    ServerDebug("[UdrServ (%s)] Sending ENTER TX Reply", moduleName);
  }

  // Restore the transaction associated with Enter Tx message and
  // quiesce executor if needed.
  activateTransaction();
  quiesceExecutor();

  // Reply to the Enter Tx message
  UdrEnterTxReply *txreply = new (udrHeapPtr_) UdrEnterTxReply(udrHeapPtr_);
  txreply->setHandle(udrHandle_);

  txStream_->clearAllObjects();
  *txStream_ << *txreply;

  NABoolean waited = TRUE;
  txStream_->send(waited);

  if (doTrace)
  {
    ServerDebug("[UdrServ (%s)] Sent ENTER TX Reply", moduleName);
  }

  txreply->decrRefCount();

  if (doneWithRS)
  {
    // If we are not going to use RS of this SPInfo, cleanup
    // RS resources. diags will be ignored since anyway we are closing
    // the statement.
    ComDiagsArea *diags = ComDiagsArea::allocate(udrGlobals_->getIpcHeap());
    prepareForReinvoke(diags);
    diags->decrRefCount();
  }

} // SPInfo::replyToEnterTxMsg()

void SPInfo::prepareToReply(UdrServerReplyStream &msgStream)
{
  const char *moduleName = "SPInfo::prepareToReply";
  NABoolean doTrace =
    (udrGlobals_->verbose_ && udrGlobals_->traceLevel_ >= TRACE_IPMS) ?
    TRUE : FALSE;

  if (doTrace)
    ServerDebug("[UdrServ (%s)] Preparing to reply", moduleName);

  // Check if we have to Quiesce the executor.
  // If the message came with transaciton, we may have to quiesce
  // the executor.

  // If we do have a request waiting in txStream_ then, we are sure
  // that the message did not carry transaction. 
  if (txStream_->getState() == IpcMessageStream::RECEIVED)
  {
    // We are under an Enter Tx message, no need to quiesce.
    if (doTrace)
      ServerDebug("         Quiesce is not needed for the current reply.");
  }
  else
  {
    // We are not under Enter Tx message, so we have to quiesce
    // executor if necessary
    msgStream.activateCurrentMsgTransaction();
    quiesceExecutor();
  }

  if (doTrace)
    ServerDebug("[UdrServ (%s)] Done.", moduleName);

} // SPInfo::prepareToReply()

void SPInfo::prepareToReply(UdrServerDataStream &msgStream)
{
  const char *moduleName = "SPInfo::prepareToReply";
  NABoolean doTrace =
    (udrGlobals_->verbose_ && udrGlobals_->traceLevel_ >= TRACE_IPMS) ?
    TRUE : FALSE;

  if (doTrace)
    ServerDebug("[UdrServ (%s)] Preparing to reply", moduleName);

  // Check if we have to Quiesce the executor.

  // If we do have a request waiting in txStream_ then, we are sure
  // that the message did not carry transaction. 
  if (txStream_->getState() == IpcMessageStream::RECEIVED)
  {
    // We are under an Enter Tx message, no need to quiesce.
    if (doTrace)
      ServerDebug("         Quiesce is not needed for the current reply.");
  }
  else
  {
    // We are not under Enter Tx message, so we have to quiesce
    // executor if needed.
    msgStream.activateCurrentMsgTransaction(); 
    quiesceExecutor();
  }

  if (doTrace)
    ServerDebug("[UdrServ (%s)] Done.", moduleName);

} // SPInfo::prepareToReply()

void SPInfo::quiesceExecutor()
{
  NABoolean doTrace =
    (udrGlobals_->verbose_ && udrGlobals_->traceLevel_ >= TRACE_IPMS) ?
    TRUE : FALSE;

  // With UDFs, the messages do not carry transaction id. Just return
  // from here without even checking if transaction exists.
  // $$$$ It would be better to check the routine type here rather
  // than the parameter style
  if (getParamStyle() == COM_STYLE_SQLROW ||
      getParamStyle() == COM_STYLE_SQL)
  {
    if (doTrace)
      ServerDebug( "         Quiescing is not needed for UDFs.");

    return ;
  }

  // With SPJs, we don't do any SQL in UDR Server process on NEO since
  // we use Type 4 JDBC. But SQL execution is possible in UDR Server on
  // Windows platform.
  if (getParamStyle() == COM_STYLE_JAVA_CALL)
  {
    Int64 tx_id = 0;
    short tmfCode = GETTRANSID((short*) &tx_id);
    
    if (doTrace)
    {
      ServerDebug("         GetTransID returned %d.", tmfCode);
      ServerDebug("         Current Transid is %Ld.", tx_id);
    }
    
    // Quiesce the executor if the message carried a transaction
    if (tmfCode == 0)
    {
      if (doTrace)
        ServerDebug("         "
                    "Message carried a transaction. About to quiesce.");
      
      Lng32 sqlcode = SQL_EXEC_Xact(SQLTRANS_QUIESCE, NULL);
      if (sqlcode < 0)
      {
        char msg[MAXERRTEXT];
        str_sprintf(msg, "SQL_EXEC_Xact returned error %d", (Int32) sqlcode);
        UDR_ASSERT(FALSE, msg);
      }
      
      if (doTrace)
        ServerDebug("         Quiesce was successful");
    }
    else if (tmfCode == 75 || tmfCode == 78)
    {
      if (doTrace)
        ServerDebug("         "
                    "Message did not have a transaction. "
                    "Quiescing is not neeeded.");
    }
    else
    {
      char msg[MAXERRTEXT];
      str_sprintf(msg,
                  "Unable to get transaction state. TMF returned error %d",
                  tmfCode);
      if (doTrace)
      {
        ServerDebug(msg);
        ServerDebug("Aborting...");
      }
      
      UDR_ASSERT(FALSE, msg);
    }
  } // if COM_STYLE_JAVA

} // SPInfo::quiesceExecutor()

void SPInfo::work()
{
  const char *moduleName = "SPInfo::work";

  NABoolean traceInvokeIPMS = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_IPMS)
    traceInvokeIPMS = true;

  NABoolean traceInvokeDataAreas = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_DATA_AREAS)
    traceInvokeDataAreas = true;

  doMessageBox(udrGlobals_,
               TRACE_SHOW_DIALOGS,
               udrGlobals_->showInvoke_,
               moduleName);

  // Do we have a request to process?
  if (! currentRequest_)
  {
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  No current request buffer to process",
                  moduleName);

    return;
  }

  if (traceInvokeIPMS)
    ServerDebug("[UdrServ (%s)]  Processing Invoke Request", moduleName);

  // Free up any receive buffers no longer in use
  dataStream_->cleanupBuffers();

  // Extract the SqlBuffer from the request
  SqlBuffer *reqSqlBuf = currentRequest_->getSqlBuffer();
  if (reqSqlBuf == NULL)
  {
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  Empty request buffer in the request",
              moduleName);

    dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                   INVOKE_ERR_NO_REQUEST_BUFFER, NULL);

    sendDataReply(udrGlobals_, *dataStream_, NULL);
    currentRequest_ = NULL;
    return;
  }

  if (reqSqlBuf->atEOTD())
  {
    // This is the case where the rows in the request buffer
    // are all processed in the previous iteration of work()
    // and reply is sent to client but end of tupps is not seen
    // in request buffer.
    // In this case we just have to do some cleanup and return.

    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  No request rows to process in the"
                  " request SQL buffer", moduleName);

    reqSqlBuf->bufferFull();
    currentRequest_ = NULL;
    return ;
  }

  ComUInt32 initialNumRequestTupps = reqSqlBuf->getTotalTuppDescs();
  if (traceInvokeIPMS)
    ServerDebug("[UdrServ (%s)]  There are %d tupps in the request buffer",
               moduleName, initialNumRequestTupps);

  // Does stream have room for next buffer?
  if (dataStream_->sendLimitReached())
  {
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  Send limit reached in the data stream",
                  moduleName);
    return;
  }

  // Allocate a reply buffer
  UdrDataBuffer *reply = new (*dataStream_, getReplyBufferSize())
    UdrDataBuffer(getReplyBufferSize(), UdrDataBuffer::UDR_DATA_OUT, NULL);
  
  if (reply == NULL || reply->getSqlBuffer() == NULL)
  {
    dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                   INVOKE_ERR_NO_REPLY_DATA_BUFFER, NULL);

    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)] Send Invoke Error Reply", moduleName);

    sendDataReply(udrGlobals_, *dataStream_, NULL);

    // We will not need the request buffer anymore. Mark as such so
    // the stream deletes this buffer later.
    reqSqlBuf->bufferFull();
    currentRequest_ = NULL;

    return;
  }

  // Activate Enter TX transaction if we have already seen an
  // Enter Tx msg. Otherwise, activate this INVOKE msg's transaction
  if (! activateTransaction())
    dataStream_->activateCurrentMsgTransaction();

  // Prepare for re-invocation on the same SP
  if (isInvoked() || isInvokeFailed())
  {
    // !FIXME: WHAT TO DO ABOUT THESE DIAGS
    //prepareForReinvoke(diags);
    prepareForReinvoke(NULL);
  }

  resetLastCallTs();

  // Process request rows until all rows are processed or ther is no
  // room left in reply buffer
  Lng32 numRowsProcessed = 0;
  RequestRowProcessingStatus status;
  do
  {
    status = processOneRequestRow(reqSqlBuf,
                                  reply->getSqlBuffer(),
                                  numRowsProcessed);

  } while (status != ALL_ROWS_PROCESSED && status != REPLY_BUFFER_FULL);

  // Print reply buffer
  if (traceInvokeDataAreas)
  {
    ServerDebug("");
    ServerDebug("[UdrServ (%s)] Processed %d rows from the request buffer.",
      moduleName, numRowsProcessed);
    ServerDebug("[UdrServ (%s)] %d tupps remaining in request buffer.",
      moduleName, initialNumRequestTupps - reqSqlBuf->getProcessedTuppDescs());
    ServerDebug("[UdrServ (%s)] Reply Row Length %d", moduleName,
      (Lng32) getReplyRowSize());
    ServerDebug("[UdrServ (%s)] Invoke Reply SQL Buffer", moduleName);
    displaySqlBuffer(reply->getSqlBuffer(), (Lng32)reply->getSqlBufferLength());
  }

  // If all the rows in request buffer are processed, make sure
  // it gets cleaned up and then release it's reference here
  if (status == ALL_ROWS_PROCESSED || reqSqlBuf->atEOTD())
  {
    // This is the last reply buffer for the current request buffer
    reply->setLastBuffer(TRUE);

    if (traceInvokeDataAreas)
      ServerDebug("[UdrServ (%s)] Processed all rows from the request buffer.",
        moduleName);

    // We need the request buffer in a state where the stream knows
    // it can be freed. We call SqlBuffer::bufferFull() to accomplish
    // this even though the method name is a bit misleading.
    reqSqlBuf->bufferFull();
    currentRequest_ = NULL;
  }

  // Send reply if we have processed any rows
  if (numRowsProcessed > 0)
  {
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)] Send Invoke Reply", moduleName);
    sendDataReply(udrGlobals_, *dataStream_, this);
  }

}  // SPInfo::work


RequestRowProcessingStatus
SPInfo::processOneRequestRow(SqlBuffer *reqSqlBuf,
                             SqlBuffer *replySqlBuf,
                             Lng32 &numRowsProcessed)
{
  const char *moduleName = "SPInfo::processOneRequestRow";

  NABoolean traceInvokeDataAreas = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_DATA_AREAS)
    traceInvokeDataAreas = true;

  NABoolean traceInvokeIPMS = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_IPMS)
    traceInvokeIPMS = true;

  Lng32 numTuppsBefore = replySqlBuf->getTotalTuppDescs();

  // First, allocate space in the reply buffer for one row plus EOD
  char *replyData = NULL;
  ControlInfo *replyControlInfo = NULL;
  NABoolean replyRowAllocated =
    allocateReplyRowAndEOD(udrGlobals_,
                           *replySqlBuf,
                           0, // dummy queue index, will be updated later
                           replyData,
                           (Lng32) getReplyRowSize(),
                           replyControlInfo);

  if (! replyRowAllocated)
  {
    // There are two cases.
    // Case 1: This is the first row in the reply buffer and row
    // allocation failed.
    if (numTuppsBefore == 0)
    {
      dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                     INVOKE_ERR_NO_REPLY_ROW, NULL);

      return ALL_ROWS_PROCESSED;
    }

    // Case 2: We have already inserted few reply rows. There is no more
    // room for reply row and EOD in reply buffer.
    // Also, it is possible that Data row is allocated and EOD is not
    // allocated. So lets' try to back out if there are any new tupps.
    backoutTupps(*replySqlBuf, numTuppsBefore);
    return REPLY_BUFFER_FULL;
  }
  
  // Extract a row from the request buffer
  down_state downState;
  tupp requestRow;
  NABoolean endOfData = reqSqlBuf->moveOutSendOrReplyData(
      TRUE,          // [IN] sending? (vs. replying)
      &downState,    // [OUT] queue state
      requestRow,    // [OUT] new data tupp_descriptor
      NULL,          // [OUT] new ControlInfo area
      NULL,          // [OUT] new diags tupp_descriptor
      NULL);         // [OUT] new stats area

  if (endOfData)
  {
    // delete the allocated row in reply buffer
    backoutTupps(*replySqlBuf, numTuppsBefore);

    return ALL_ROWS_PROCESSED;
  }

  numRowsProcessed++;
  char *requestData = requestRow.getDataPointer();
  queue_index requestQueueIndex = downState.parentIndex;

  // correct the queue index of reply row
  replyControlInfo->getUpState().parentIndex = requestQueueIndex;

  if (traceInvokeDataAreas)
  {
    ComUInt32 requestRowLen = requestRow.getAllocatedSize();
    ServerDebug("[UdrServ (%s)] Request info: queue index %d", moduleName,
                (Lng32) requestQueueIndex);
    ServerDebug("[UdrServ (%s)] Request Row Length %u", moduleName,
                (ULng32) requestRowLen);
    ServerDebug("[UdrServ (%s)] Dump of Request Invoke Data", moduleName);
    dumpBuffer((unsigned char *) requestData, requestRowLen);
  }

  if (rowDiags_ == NULL)
    rowDiags_ = ComDiagsArea::allocate(udrGlobals_->getIpcHeap());
  UDR_ASSERT(rowDiags_, "Unable to allocate memory for SQL diagnostics area");

  if (traceInvokeIPMS)
    ServerDebug("[UdrServ (%s)]  Call LM invokeRoutine", moduleName);

  // Call into Language manager
  LmLanguageManager *lm = udrGlobals_->getLM(getLanguage());
  UDR_ASSERT(lm,
             "No Language Manager available to process this INVOKE message");
  UDR_ASSERT(getLMHandle(), "Missing LM Routine handle");

  LmResult lmResult = lm->invokeRoutine(getLMHandle(),
					requestData, replyData,
                                        rowDiags_);

  if (traceInvokeIPMS)
  {
    char errorText[MAXERRTEXT];
    if (lmResult == LM_OK)
      sprintf(errorText,
              "[UdrServ (%.30s)]  LM::invokeRoutine was successful.",
              moduleName);
    else
      sprintf(errorText,
              "[UdrServ (%.30s)]  LM::invokeRoutine resulted in error.",
              moduleName);

    ServerDebug(errorText);
    doMessageBox(udrGlobals_,
                 TRACE_SHOW_DIALOGS,
                 udrGlobals_->showInvoke_,
                 errorText);
  }

  if (lmResult == LM_OK)
  {
    // Routine execution successful. Set state to INVOKED.
    if (getParamStyle() != COM_STYLE_SQLROW)
    {
      // $$$$ It would be better to check the routine type or the
      // number of result sets here rather than the parameter style
      if (getParamStyle() == COM_STYLE_JAVA_CALL)
        setupUdrResultSets(*rowDiags_);
    }

    setSPInfoState(SPInfo::INVOKED);
  }
  else
  {
    // Routine returned error. do result set cleanup in LM.
    // Set state to INVOKE_FAILED.
    getLMHandle()->cleanupResultSets(NULL);
    setSPInfoState(SPInfo::INVOKE_FAILED);
    NABoolean ok = convertReplyRowToErrorRow(replySqlBuf,
                                             numTuppsBefore,
                                             requestQueueIndex,
                                             *dataStream_,
                                             udrGlobals_);

    RequestRowProcessingStatus retcode;
    if (ok)
    {
      moveDiagsIntoStream(rowDiags_, replyControlInfo);
      retcode = A_ROW_IS_PROCESSED;
    }
    else
      retcode = ALL_ROWS_PROCESSED;

    rowDiags_->decrRefCount();
    rowDiags_ = NULL;
    return retcode;
  }

  // If the routine returned RS then add the details
  // about each RS into the reply.
  if (getNumResultSets() > 0)
  {
    NABoolean rsMoveOk = moveRSInfoIntoStream();
    if (! rsMoveOk)
    {
      // FIXME: We need to see if this is correct
      backoutTupps(*replySqlBuf, 0);
      dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                     INVOKE_ERR_NO_REPLY_BUFFER, NULL);

      rowDiags_->decrRefCount();
      rowDiags_ = NULL;
      return ALL_ROWS_PROCESSED;
    }
  }

  // Move diags into stream
  if (rowDiags_->getNumber() > 0)
  {
    moveDiagsIntoStream(rowDiags_, replyControlInfo);
    rowDiags_->decrRefCount();
    rowDiags_ = NULL;

    udrGlobals_->numErrUDR_++;
    udrGlobals_->numErrSP_++;
    udrGlobals_->numErrInvokeSP_++;
  }

#ifdef _DEBUG
  // In the debug build we allow the UDR server to corrupt the reply
  // by reversing the diags flag for this reply row. In response the
  // executor should cause the statement to fail due to some sort of
  // IPC error. The executor should not crash or allow the statement
  // to complete successfully.
  char *val = getenv("MXUDR_CORRUPT_DIAGS_FLAG");
  if (val && val[0] && replyControlInfo)
  {
    NABoolean oldValue = replyControlInfo->getIsExtDiagsAreaPresent();
    replyControlInfo->setIsExtDiagsAreaPresent(!oldValue);
  }
#endif

  return A_ROW_IS_PROCESSED;
}  // SPInfo::processOneRequestRow

void SPInfo::workTM()
{
  const char *moduleName = "SPInfo::workTM";

  NABoolean traceInvokeIPMS = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_IPMS)
    traceInvokeIPMS = true;

  NABoolean traceInvokeDataAreas = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_DATA_AREAS)
    traceInvokeDataAreas = true;

  doMessageBox(udrGlobals_,
               TRACE_SHOW_DIALOGS,
               udrGlobals_->showInvoke_,
               moduleName);

  // Do we have a request to process?
  if (! currentRequest_)
  {
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  No current request buffer to process",
                  moduleName);

    return;
  }

  if (traceInvokeIPMS)
    ServerDebug("[UdrServ (%s)]  Processing Invoke Request", moduleName);

  // At this point we have three possibilities.
  // 1. Sql Buffer may not even be shipped if the server had 
  //    requested the client to send a continue request.
  // 2. Data buffer contains a flag indicating whether this is a
  //    scalar values buffer or data row buffer. In both these cases
  //    sql buffer is shipped.

  // Lets check if server had requested a continue request.
  if(spInfoState_ == INVOKED_EMITROWS)
  {
    //Nothing much to do except return.
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  Continue request Received",
                   moduleName);
    
    //check to make sure there is no sql buffer to be released.
    //also make sure tmudf is already isInvoked()
    //PV
    return ;
  }

  // Print request buffer
  if (traceInvokeDataAreas)
  {
    ServerDebug("");
    ServerDebug("[UdrServ (%s)] Request SQL Buffer", moduleName);
    ServerDebug("[UdrServ (%s)] SPInfo State %s", moduleName, getSPInfoStateString());

    //Note that in the case of TM, we do not get a unpacked buffer.
    SqlBuffer *tempSqlBuffer = 
      (SqlBuffer*)udrHeapPtr_->allocateMemory(getRequestBufferSize());
    memset(tempSqlBuffer, '\0', getRequestBufferSize());
  
    // Copy the packed sql buffer from IPc stream.
    memcpy(tempSqlBuffer,currentRequest_->getSqlBuffer(),getRequestBufferSize());
    tempSqlBuffer->driveUnpack();

    displaySqlBuffer(tempSqlBuffer, getRequestBufferSize());
    udrHeapPtr_->deallocateMemory(tempSqlBuffer);
  }

  // Extract the SqlBuffer from the request. Note that this buffer is 
  // still in packed form. First the packed buffer must be copied and then
  // drive unpack on the copied buffer.
  SqlBuffer *reqSqlBuf = currentRequest_->getSqlBuffer();
  if (reqSqlBuf == NULL)
  {
    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)]  Empty request buffer in the request",
              moduleName);

    // Note that we need to do reply to client only if Invoke rountine
    // is not called. Because, we may enter here as part of getNextRow
    // callback, in which case, just return by setting error
    // codes.
    if(spInfoState_ == INVOKED_GETROWS)
    {
      spInfoState_ = INVOKED_GETROWS_FAILED;
      return;
    }
    
    dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                 INVOKE_ERR_NO_REQUEST_BUFFER, NULL);

    sendDataReply(udrGlobals_, *dataStream_, NULL);
    currentRequest_ = NULL;
    return ;
  }

  if (traceInvokeIPMS)
  {
    ComUInt32 initialNumRequestTupps = reqSqlBuf->getTotalTuppDescs();
    ServerDebug("[UdrServ (%s)]  There are %d tupps in the request buffer",
               moduleName, initialNumRequestTupps);
  }

  // Irrespective of sqlbuffer containing scalar values or data rows, 
  // we make a copy of the sqlBuffer to release the current sql buffer 
  // in IPC stream. This is because we may need to reuse the IPC buffer
  // for call backs to client from getNextRow and emitRow.
  
  //First init a preexisting copy if any
  SqlBuffer *sqlBufCopy = getReqSqlBuffer(currentRequest_->tableIndex());

  if(sqlBufCopy == NULL)
  {
    // Now allocate a new copy
    sqlBufCopy =
      (SqlBuffer*)udrHeapPtr_->allocateMemory(getRequestBufferSize());
  }

  // Initilize pre existing buffer rather than allocate new.
  //sqlBufCopy->driveInit(getRequestBufferSize(),
  //                      TRUE, SqlBuffer::NORMAL_);
  
  memset(sqlBufCopy, '\0', getRequestBufferSize());
  
  // Copy the packed sql buffer from IPc stream.
  memcpy(sqlBufCopy,reqSqlBuf,getRequestBufferSize());
  
  // Now drive unpack on the copied sql buffer.
  sqlBufCopy->driveUnpack();

  // Set flag indicating that buffer in use.
  sqlBufCopy->bufferInUse();

  // Set this unpacked buffer inside corresponding table info.
  setReqSqlBufferCopy(sqlBufCopy,currentRequest_->tableIndex());

  // Set the flag to indicate this is the last buffer sent by client.
  if(currentRequest_->isLastBuffer())
    setLastReqSqlBuffer(currentRequest_->tableIndex());

  //now release reqSqlBuf
  reqSqlBuf->bufferFull();

  // Free up any receive buffers no longer in use
  dataStream_->cleanupBuffers();

  //check if row data
  if(spInfoState_ == INVOKED_GETROWS)
  {
    //nothing more to do. just return, it
    // should be getNextRow processing

    // make sure client is sending data rows when the server
    // is expecting data rows. Client indicates that it is 
    // data rows by not setting scalar values flag.
    if(currentRequest_->sendingScalarValues())
    {
      spInfoState_ =  INVOKED_GETROWS_FAILED;
    }
    return;
  }

  // We reach here means initial scalar values to be processed.
  
  // Check Spinfo state to be in LOADED state if we are going to 
  // process scalar values.
  if(spInfoState_ != LOADED)
  {
    dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                   INVOKE_ERR_NO_REQUEST_BUFFER, NULL);

    sendDataReply(udrGlobals_, *dataStream_, NULL);
    currentRequest_ = NULL;
    return;
  }

  // Extract a row from the request buffer
  up_state  upState;
  tupp requestRow;
  NABoolean endOfData = sqlBufCopy->moveOutSendOrReplyData(
      TRUE,          // [IN] sending? (vs. replying)
      &upState,    // [OUT] queue state
      requestRow,    // [OUT] new data tupp_descriptor
      NULL,          // [OUT] new ControlInfo area
      NULL,          // [OUT] new diags tupp_descriptor
      NULL);         // [OUT] new stats area

 if(endOfData || (upState.status == ex_queue::Q_NO_DATA))
 {
   //nothing much we can do. return PV
 }

  char *requestData = requestRow.getDataPointer();
  queue_index requestQueueIndex = upState.parentIndex;

  // Store the parent index in spinfo for reply message later
  setParentIndex(requestQueueIndex);

  // Allocate diags area
  if (rowDiags_ == NULL)
    rowDiags_ = ComDiagsArea::allocate(udrGlobals_->getIpcHeap());
  UDR_ASSERT(rowDiags_, "Unable to allocate memory for SQL diagnostics area");
  
  // Call into Language manager
  LmLanguageManager *lm = udrGlobals_->getLM(getLanguage());
  UDR_ASSERT(lm,
             "No Language Manager available to process this INVOKE message");
  UDR_ASSERT(getLMHandle(), "Missing LM Routine handle");

  setSPInfoState(SPInfo::INVOKED);

  LmResult lmResult = lm->invokeRoutine(getLMHandle(),
					requestData, NULL,
                                        rowDiags_);

  if (traceInvokeIPMS)
  {
    char errorText[MAXERRTEXT];
    if (lmResult == LM_OK)
      sprintf(errorText,
              "[UdrServ (%.30s)]  LM::invokeRoutine was successful.",
              moduleName);
    else
      sprintf(errorText,
              "[UdrServ (%.30s)]  LM::invokeRoutine resulted in error.",
              moduleName);

    ServerDebug(errorText);
    doMessageBox(udrGlobals_,
                 TRACE_SHOW_DIALOGS,
                 udrGlobals_->showInvoke_,
                 errorText);
  }

  if (lmResult != LM_OK)
  {
    dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                   INVOKE_ERR_NO_REPLY_DATA_BUFFER, NULL, rowDiags_);
    rowDiags_ = NULL;

    if (traceInvokeIPMS)
      ServerDebug("[UdrServ (%s)] Send Invoke Error Reply", moduleName);

    sendDataReply(udrGlobals_, *dataStream_, NULL);
    currentRequest_ = NULL;
    return;
  }

  // release the row in the SqlBuffer before we allocate new buffers
  // and do other cleanup
  requestRow.release();
  requestData = NULL;

  if (paramStyle_ != COM_STYLE_CPP_OBJ &&
      paramStyle_ != COM_STYLE_JAVA_OBJ)
    {
      // should happen in the C interface only, C++ interface
      // sends this inside LmRoutine::invoke()

      //allocate reply buffer
      UdrDataBuffer *reply = new (*dataStream_, getReplyBufferSize())
        UdrDataBuffer(getReplyBufferSize(), UdrDataBuffer::UDR_DATA_OUT, NULL);
  
      if (reply == NULL || reply->getSqlBuffer() == NULL)
        {
          dataErrorReply(udrGlobals_, *dataStream_, UDR_ERR_MESSAGE_PROCESSING,
                         INVOKE_ERR_NO_REPLY_DATA_BUFFER, NULL);

          if (traceInvokeIPMS)
            ServerDebug("[UdrServ (%s)] Send Invoke Error Reply", moduleName);

          sendDataReply(udrGlobals_, *dataStream_, NULL);
          currentRequest_ = NULL;
          return;
        }

      // Allocate a reply row with EOD reply
      SqlBuffer *replyBuffer = reply->getSqlBuffer();
      allocateEODRow(udrGlobals_, *replyBuffer, requestQueueIndex); 

      // Indicate this is the last buffer reply from server
      reply->setLastBuffer(TRUE);

      // Also reset any flag that indicates send more data, just incase.
      reply->setSendMoreData(FALSE);

      sendDataReply(udrGlobals_, *dataStream_, this);
    }

  // Free up any receive buffers no longer in use
  dataStream_->cleanupBuffers();

  //Reset internal buffers and flags and prepare for reinvoke.
  reset();

  currentRequest_ = NULL;

}  // SPInfo::workTM



NABoolean SPInfo::moveRSInfoIntoStream()
{
  const char *moduleName = "SPInfo::moveRSInfoIntoStream";

  NABoolean traceInvokeIPMS = false;
  if (udrGlobals_->verbose_ && udrGlobals_->showInvoke_ &&
      udrGlobals_->traceLevel_ >= TRACE_IPMS)
    traceInvokeIPMS = true;

  // We are using copy buffering model of the buffered stream to
  // construct the UdrRSInfo object instead of the "in-place" or
  // copyless buffering of buffered streams since it's not clear
  // if the copyless IPC would result in any significant performance
  // improvement.
  UdrRSInfoMsg *rsInfoMsg = new (udrGlobals_->getIpcHeap())
    UdrRSInfoMsg(getNumResultSets(), udrGlobals_->getIpcHeap());

  if (rsInfoMsg == NULL)
    return false;

  // Add the result sets information to the invoke reply message
  for (ComUInt32 i = 0; i < getNumResultSets(); i++)
  {
    UdrResultSet *udrRS = getUdrResultSetByIndex(i);
    UDR_ASSERT(udrRS, "UDR Result Set object is Null");

    // +++ [TBD]: This will change when the ResultSetInfo is updated
    // to send back more meaningful data for measure and debug.
    ResultSetInfo rsInfo(udrRS->getProxySyntax(),
                         udrRS->getStatementHandle(),
                         udrRS->getContextHandle(),
                         udrGlobals_->getIpcHeap());
    rsInfoMsg->setRSInfo(i, rsInfo);
  }

  if (traceInvokeIPMS)
  {
    ServerDebug("[UdrServ (%s)] Number of result sets returned %d",
                moduleName,
                (Lng32) rsInfoMsg->getNumResultSets());
    ServerDebug("Dump of result sets Data");

    for (ComUInt32 i = 0; i < rsInfoMsg->getNumResultSets(); i++)
    {
      ServerDebug("  Data in result set #%d", (Lng32) i+1);
      ServerDebug("    Proxy syntax = %s",
                  rsInfoMsg->getRSInfo(i).getProxySyntax());
      ServerDebug("    CLI statement ID pointer = %p",
                  rsInfoMsg->getRSInfo(i).getStmtID());
      ServerDebug("    CLI context handle = %u",
                  rsInfoMsg->getRSInfo(i).getContextID());
      ServerDebug("");
    }
  }

  *dataStream_ << *rsInfoMsg; 
  rsInfoMsg->decrRefCount();

  return true;

} // SPInfo::moveRSInfoIntoStream


void SPInfo::moveDiagsIntoStream(ComDiagsArea *diags,
                                 ControlInfo *replyControlInfo)
{
  if (diags && diags->getNumber() > 0)
  {
    if (replyControlInfo)
      replyControlInfo->setIsExtDiagsAreaPresent(TRUE);

    *dataStream_ << *diags;
  }

  return;
}

//***********************************************************************
// SPList constructors
//
//
//***********************************************************************

SPList::SPList(UdrGlobals *udrGlobals)
  : udrGlobals_(udrGlobals),
    spInfoElement_(NULL) // on system heap
{
  str_cpy_all( &eyeCatcher_[0], EYE_SPLIST + '\0' + '\0', 4 );
  spInfoElement_.resize(0);  // default size
} // SPList::SPList()

//***********************************************************************
// SPList methods
//
//***********************************************************************

void SPList::displaySPList(Lng32 indent)
{
  SPInfo *sp;

  Lng32 indmax = (indent > 99) ? 99 : indent;
  
  char ind[100];
  Lng32 indIdx = 0;
  for (indIdx = 0; indIdx < indmax; indIdx++)
    ind[indIdx] = ' ';
  ind[indIdx] = '\0';
  
  ServerDebug("");
  ServerDebug("%sSPList Data Structure", ind );
  ServerDebug("%s---------------------", ind );
  
  ComUInt32 maxEntries = spInfoElement_.entries();
  for (ComUInt32 i = 0; i < maxEntries; i++)
  {
    sp = spInfoElement_.at(i);
    if (sp->getUdrHandle() == (UdrHandle)0)
    {
      ServerDebug("%sSPList[%u]: NULL", ind, i );
    }
    else
    {
      ServerDebug("%sSPList[%u]:", ind, i);
      sp->displaySPInfo(indmax + 2);
    }
  }
} // SPList::displaySPList

void SPList::displaySPListId(Lng32 indent)
{
  SPInfo *sp;
  
  Lng32 indmax = (indent > 99) ? 99 : indent;
  
  char ind[100];
  Lng32 indIdx = 0;
  for (indIdx = 0; indIdx < indmax; indIdx++)
    ind[indIdx] = ' ';
  ind[indIdx] = '\0';
  
  ServerDebug("");
  ServerDebug("%sSPList Identifiers", ind );
  ServerDebug("%s---------------------", ind );
  
  ComUInt32 maxEntries = spInfoElement_.entries();
  for (ComUInt32 i = 0; i < maxEntries; i++)
  {
    sp = spInfoElement_.at(i);
    if (sp->getUdrHandle() == (UdrHandle)0)
    {
      ServerDebug("%sSPList[%u]: NULL", ind, i );
    }
    else
    {
      ServerDebug("%sSPList[%u]:", ind, i );
      sp->displaySPInfoId(indmax + 2);
    }
  }

  ServerDebug("");

} // SPList::displaySPListId


// Seach SPList to find SPInfo that matches the input udrHandle.
// Return SPInfo object or NULL.
SPInfo *SPList::spFind(const UdrHandle &udrHandle)
{
  const char *moduleName = "SPList::spFind";
  
  SPInfo *sp;
  
  doMessageBox(udrGlobals_, TRACE_SHOW_DIALOGS,
               udrGlobals_->showSPInfo_, moduleName);
  
  ComUInt32 maxEntries = spInfoElement_.entries();
  for (ComUInt32 i = 0; i < maxEntries; i++)
  {
    sp = spInfoElement_.at(i);
    if (sp != NULL)
    {
      if (sp->getUdrHandle() == udrHandle) {
        udrGlobals_->setCurrSP(sp);
        return sp;
      }
    }
  }
  
  return NULL;
  
} // SPList::spFind


// Find oldest, least used SPJ and free up all resources allocated
// and mark as unloaded.
// Used to recover from memory problems in UDR Server.
void SPList::releaseOldestSPJ(ComDiagsArea &d)
{
  const char *moduleName = "SPList::releaseOldestSPJ";

  doMessageBox(udrGlobals_, TRACE_SHOW_DIALOGS,
               udrGlobals_->showSPInfo_, moduleName);
  
  if (!spInfoElement_.isEmpty())
  {
    Int64 oldestTS;
    Int64 leastNumCalls;
    Int64 numCalls;
    Int64 lastTS;
    CollIndex releaseIdx;
    
    SPInfo *spi;
    
    spi = spInfoElement_.at(0);
    oldestTS = spi->getLastCallTs();
    leastNumCalls = spi->getNumCalls();
    releaseIdx = 0;
    
    ComUInt32 SPListMax = spInfoElement_.entries();
    
    // loop over SPList entries finding SP with least calls
    // having oldest last timestamp.
    
    for (ComUInt32 idx = 1; idx < SPListMax; idx++)
    {
      spi = spInfoElement_.at(idx);
      numCalls = spi->getNumCalls();
      lastTS = spi->getLastCallTs();
      if (numCalls < leastNumCalls)
      {
        leastNumCalls = numCalls;
        oldestTS = lastTS;
        releaseIdx = idx;
      }
      else
      {
        if (numCalls == leastNumCalls)
        {
          if (spi->getLastCallTs() <= oldestTS)
          {
            oldestTS = lastTS;
            releaseIdx = idx;
          }
        }
      }
    }
    
    // release oldest entry...
    spi = spInfoElement_.at(releaseIdx);
    
    spi->releaseSP(FALSE /* report no errors */, d);
    
  }
  
} // SPList::releaseOldestSPJ

void SPList::addToSPList(SPInfo *spinfo)
{
  spInfoElement_.resize(spInfoElement_.entries() + 1);
  spInfoElement_.insert(spinfo);

  udrGlobals_->numTotalSPs_++;
  udrGlobals_->numCurrSPs_++;

  if (udrGlobals_->verbose_ &&
      udrGlobals_->traceLevel_ >= TRACE_DETAILS &&
      udrGlobals_->showSPInfo_)
  {
    ServerDebug("[UdrServ (SPINFO)] Added Element to SPList. %d entries",
                (Lng32) spInfoElement_.entries());
    displaySPListId(2);
  }
} // SPList::addToSPList

void SPList::removeFromSPList(SPInfo *spinfo)
{
  udrGlobals_->numTotalSPs_--;
  udrGlobals_->numCurrSPs_--;

  // TBD: Ramana
  // For the following to be meaningful, we need to make sure that
  // numCurrRSets_ incremented after a UDR invocation. We do not have
  // code to do that right now.
  udrGlobals_->numCurrRSets_-= spinfo->getNumResultSets();

  spInfoElement_.remove(spinfo);
} // SPList::removeFromSPList

LmParameter &SPInfo::getLmParameter(ComUInt32 i)
{
  UDR_ASSERT(i < (numParameters_ + maxNumResultSets_),
             "An invalid index was passed to SPInfo::getLmParameter()");
  return lmParameters_[i];
}

void SPInfo::setNumTableInfo(ComUInt32 t)
{
  numTableInfo_ = t;
  if (numTableInfo_ > 0)
  {
    ComUInt32 inputTableBytes= numTableInfo_ * sizeof(LmTableInfo);

    tableInfo_ = (LmTableInfo *) udrHeapPtr_->allocateMemory(inputTableBytes);
    memset(tableInfo_, 0, inputTableBytes);
  }
}

void SPInfo::setTableInputInfo(const UdrTableInputInfo info[])
{
  for(ComUInt32 i = 0; i < numTableInfo_; i++)
  {
    LmTableInfo *tableInfo = &tableInfo_[info[i].getTabIndex()];
    tableInfo->tabIndex_ = info[i].getTabIndex();
    tableInfo->tableNameLen_ = info[i].getTableNameLen();
    tableInfo->rowLength_ = info[i].getRowLength();
    tableInfo->tableName_ = (char*)udrHeapPtr_->allocateMemory(tableInfo->tableNameLen_ + 1);
    strncpy(tableInfo->tableName_, info[i].getTableName(), tableInfo->tableNameLen_);
    tableInfo->tableName_[tableInfo->tableNameLen_] = '\0';

    // initialize individual column descriptors
    tableInfo->numInColumns_ = info[i].getNumColumns();
    if(tableInfo->inColumnParam_ == NULL)
    {
      ComUInt32 lmParamBytes = tableInfo->numInColumns_ * sizeof(LmParameter);
      tableInfo->inColumnParam_ = (LmParameter *) udrHeapPtr_->allocateMemory(lmParamBytes);
      memset(tableInfo->inColumnParam_, 0, lmParamBytes);
    }

    for(ComUInt32 j = 0; j < tableInfo->numInColumns_; j++)
    {
      const UdrParameterInfo &pInfo = info[i].getInTableColumnDesc(j);

      // Determine the encoding charset. We will use =_SQL_MX_ISO_MAPPING
      // define value if the param's charset is ISO88591.
      CharInfo::CharSet charset = (CharInfo::CharSet) pInfo.getEncodingCharSet();
      if (charset == CharInfo::ISO88591)
        charset = udrGlobals_->getIsoMapping();

      tableInfo->inColumnParam_[j].init((ComFSDataType) pInfo.getFSType(),
                                         pInfo.getPrec(),
                                         pInfo.getScale(),
                                         charset,
                                         (CharInfo::Collation) pInfo.getCollation(),
                                         COM_INPUT_COLUMN,
                                         pInfo.isLmObjType(),
                                         RS_NONE,
                                         pInfo.getDataOffset(),
                                         pInfo.getDataLength(),
                                         pInfo.getNullIndicatorOffset(),
                                         pInfo.getNullIndicatorLength(),
                                         pInfo.getVCLenIndOffset(),
                                         pInfo.getVCIndicatorLength(),
                                         0, 0, 0, 0, 0, 0, // output offsets and lengths
                                         pInfo.getParamName());
    }
  }
}

SqlBuffer* SPInfo::getReqSqlBuffer(ComSInt32 tableIndex)
{
  if(tableIndex < 0 ) return sqlBufferScalar_;

  return tableInfo_[tableIndex].getReqSqlBuffer();
}

SqlBuffer* SPInfo::getEmitSqlBuffer(ComSInt32 tableIndex)
{
  if (numTableInfo_ == 0)
    return sqlBufferTVF_;
  else
    return tableInfo_[tableIndex].getEmitSqlBuffer();
}

void SPInfo::setEmitSqlBuffer(SqlBuffer *buf, ComSInt32 tableIndex)
{
  if (numTableInfo_ == 0)
    sqlBufferTVF_ = buf;
  else
    tableInfo_[tableIndex].setEmitSqlBuffer(buf);
}

void SPInfo::reset(void)
{
   if(sqlBufferScalar_ != NULL)
   {
     sqlBufferScalar_->bufferFull();
     udrHeapPtr_->deallocateMemory(sqlBufferScalar_);
     sqlBufferScalar_ = NULL;
   }
   if(sqlBufferTVF_ != NULL)
   {
     sqlBufferTVF_->bufferFull();
     udrHeapPtr_->deallocateMemory(sqlBufferTVF_);
     sqlBufferTVF_ = NULL;
   }
   for(ComUInt32 i = 0; i < getNumTables(); i++)
   {
      tableInfo_[i].reset(udrHeapPtr_);
   }
   parentIndex_ = 0;

   setSPInfoState(SPInfo::LOADED);
}

ComUInt32 SPInfo::getInputRowLength(ComSInt32 tableIndex)
{
  return tableInfo_[tableIndex].getRequestRowSize();
}


void SPInfo::setReqSqlBufferCopy(SqlBuffer *sqlBufCopy, ComSInt32 tableIndex)
{
  if(tableIndex < 0)
  {
    //SQL Buffer containing Scalar values
    sqlBufferScalar_ = sqlBufCopy;
  }
  else
  {
    // check for error PV
    tableInfo_[tableIndex].setReqSqlBuffer(sqlBufCopy);
  }
}

NABoolean SPInfo::isLastReqSqlBuffer(ComSInt32 tableIndex)
{
  return tableInfo_[tableIndex].isLastReqSqlBuffer();
}

void SPInfo::setLastReqSqlBuffer(ComSInt32 tableIndex)
{
  if(tableIndex < 0 ) return; // do nothing.

  tableInfo_[tableIndex].setLastReqSqlBuffer();
}
