///////////////////////////////////////////////////////////////////////////
// This method is used to retrieve input rows from the input buffer
// that is sent from Executor to Arkcmp.
//
// Returns the 'current' row and increments the internal rownum.
//
// Also returns control information associated with this input row.
// Caller needs to pass this control info pointer to ExSPPutReplyRow 
// when the reply buffer (sent from Arkcmp to Executor) is being filled
// in. All reply(output) rows that correspond to this input row have
// the same control info.
//
// RETURNS: 0, if all is Ok. 1, if all rows have been returned.
//          -1, in case of error.
////////////////////////////////////////////////////////////////////////////
SQLCLI_LIB_FUNC
short ExSPGetInputRow(void * inputBuffer,   // IN:  input sql buffer
		      void* &controlInfo,   // OUT: control info 
		      char* &rowPtr,        // OUT: pointer to the row
		      ULng32 &rowLen)// OUT: length of returned row
{
  SqlBuffer * ib = (SqlBuffer *)inputBuffer;
  if ( !ib )
	  return -1;

  tupp tp;
  ControlInfo * ci = NULL;
  up_state us;
  ComDiagsArea* diags;
  if (ib->moveOutSendOrReplyData(TRUE, // send (input) value
				 &us,
				 tp,
				 &ci, &diags) == TRUE)
    return 1; // No more input rows.
  
  controlInfo = ci;
  
  rowPtr = tp.getDataPointer();
  rowLen = tp.getAllocatedSize();
  
  return 0;
}
Esempio n. 2
0
void backoutTupps(SqlBuffer &b, Lng32 numTuppsBefore)
{
  while (b.getTotalTuppDescs() > numTuppsBefore)
  {
    b.remove_tuple_desc();
  }
}
/////////////////////////////////////////////////////////////////
// Positions to the first row in input buffer. This proc MUST be
// called before retrieving input rows from it.
// RETURNS: 0, if all ok. -1, in case of an error.
/////////////////////////////////////////////////////////////////
short ExSPPosition(void * inputBuffer)
{
  SqlBuffer * ib = (SqlBuffer *)inputBuffer;
  if (ib == NULL)
    return -1;
  
  ib->position();

  return 0;
}
///////////////////////////////////////////////////////////////
// Prepares the input buffer so input rows could be retrieved
// from it. Unpacks sql buffer which would convert offsets to
// pointers. To be called after receiving the input buffer
// from Executor and before retrieving rows from it.
///////////////////////////////////////////////////////////////
short ExSPPrepareInputBuffer(void * inputBuffer)
{
  SqlBuffer * ib = (SqlBuffer *)inputBuffer;
  if (ib == NULL)
    return -1;

  ib->driveUnpack();
  
  return 0;
}
/////////////////////////////////////////////////////////////////
// Initializes the reply buffer.
// Caller must allocate contiguous space of length replyBufLen
// and then call this proc. 
// This proc MUST be called BEFORE moving any reply rows to it.
// Once the reply buffer is sent from Arkcmp to Executor, it
// must be re-initialized by calling this proc again.
/////////////////////////////////////////////////////////////////
short ExSPInitReplyBuffer(void * replyBuffer, 
			  ULng32 replyBufLen)
{
  SqlBuffer * rb = (SqlBuffer *)replyBuffer;
  if ((rb == NULL) || (replyBufLen == 0))
    return -1;
  
  rb->driveInit(replyBufLen, FALSE, SqlBuffer::NORMAL_);
  
  return 0;
}
///////////////////////////////////////////////////////////
// Prepares the reply buffer so it could be sent back
// from Arkcmp to Executor.
// Packs sql buffer which would convert pointers to
// offsets. To be called before sending the reply buffer to
// Executor.
///////////////////////////////////////////////////////////
short ExSPPrepareReplyBuffer(void * replyBuffer)
{
  SqlBuffer * rb = (SqlBuffer *)replyBuffer;
  if (rb == NULL)
    return -1;
  
  rb->drivePack();

  // this reply buffer needs to be sent back to executor.
  // Mark it as being in use.
  rb->bufferInUse();
  
  return 0;
}
Esempio n. 7
0
void UdrServerDataStream::actOnReceive(IpcConnection *conn)
{
  const char *moduleName = "UdrServerDataStream::actOnReceive()";

  IpcMessageObjType t;
  NABoolean somethingArrived = FALSE;

  //
  // A note about control flow in this method. It was originally
  // written under the assumption that only one message arrives at a
  // time. It would call getNextReceiveMsg() only once, then process
  // incoming objects, then return. It turns out this creates a memory
  // leak. Internally within the stream, the incoming message buffer
  // never moved from the "receive" list to the "in use" list and
  // never got cleaned up. Now this method calls getNextReceiveMsg()
  // until it returns FALSE. The result is that after the incoming
  // message has been processed, the next getNextReceiveMsg() call
  // will move the request buffer to the "in use" list where it later
  // gets cleaned up by a call to cleanupBuffers() or
  // releaseBuffers().
  //

  while (getNextReceiveMsg(t))
  {
    somethingArrived = TRUE;

    while (getNextObjType(t))
    {
      switch (t)
      {
        case UDR_MSG_DATA_HEADER:
        {
          // Do nothing for now except extract the object from the stream
          UdrDataHeader *h = new (receiveMsgObj()) UdrDataHeader(this);
          
        } // case UDR_MSG_DATA_HEADER
        break;
        
        case UDR_MSG_CONTINUE_REQUEST:
        {
          // Extract the object from the stream and call SPInfo's work()
          UdrContinueMsg *m = new (receiveMsgObj()) UdrContinueMsg(this);
          
          if(spinfo_->getParamStyle() == COM_STYLE_TM)
            spinfo_->workTM();
          else
            spinfo_->work();
          
        } // case UDR_MSG_CONTINUE_REQUEST
        break;
        
        case UDR_MSG_DATA_REQUEST:
        {
          UdrDataBuffer *request = new (receiveMsgObj()) UdrDataBuffer(this);
          
          if (udrGlob_->verbose_ &&
              udrGlob_->traceLevel_ >= TRACE_DETAILS &&
              udrGlob_->showMain_)
          {
            ServerDebug( "");
            ServerDebug("[UdrServ (%s)] Invoke Request has %ld tupps.",
                        moduleName,
                        request->getSqlBuffer()->getTotalTuppDescs());
            ServerDebug("[UdrServ (%s)] Invoke Request SQL Buffer",
                        moduleName);
            displaySqlBuffer(request->getSqlBuffer(),
                             (Lng32) request->getSqlBufferLength());
          }
          
          udrGlob_->numReqInvokeSP_++;
          
          // Let the SPInfo process the request
	  spinfo_->setCurrentRequest(request);
	  spinfo_->work();

        } // case UDR_MSG_DATA_REQUEST
        break;

        case UDR_MSG_TMUDF_DATA_HEADER:
	{
	  // Extract the object. UDR Handle and RS Handle are
	  // interesting things in this message.
          UdrTmudfDataHeader *h = new (receiveMsgObj()) UdrTmudfDataHeader(this);
	  UdrHandle udrHandle = h->getHandle();

          NABoolean anyMore = getNextObjType(t);
          UDR_ASSERT(anyMore, "DATA_REQUEST must follow TMUDF DATA_HEADER");
          UDR_ASSERT(t == UDR_MSG_DATA_REQUEST,
                     "DATA_REQUEST must follow TMUDF DATA_HEADER");

          UdrDataBuffer *request = new (receiveMsgObj()) 
                                    UdrDataBuffer(this,
                                                  FALSE); //Avoid unpack.

          // Let the SPInfo process the request
	  spinfo_->setCurrentRequest(request);
	  spinfo_->workTM();
	}
        break;

        case UDR_MSG_RS_DATA_HEADER:
	{
	  // Extract the object. UDR Handle and RS Handle are
	  // interesting things in this message.
          UdrRSDataHeader *h = new (receiveMsgObj()) UdrRSDataHeader(this);
	  UdrHandle udrHandle = h->getHandle();
	  RSHandle rsHandle = h->getRSHandle();

          NABoolean anyMore = getNextObjType(t);
          UDR_ASSERT(anyMore, "DATA_REQUEST must follow RS_DATA_HEADER");
          UDR_ASSERT(t == UDR_MSG_DATA_REQUEST,
                     "DATA_REQUEST must follow RS_DATA_HEADER");

          UdrDataBuffer *request = new (receiveMsgObj()) UdrDataBuffer(this);

	  udrGlob_->numReqRSFetch_++;
	  processAnRSFetchMessage(udrGlob_, *this, udrHandle,
                                  rsHandle, request);

          // 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.
          SqlBuffer *sqlBuf = request->getSqlBuffer();
          UDR_ASSERT(sqlBuf,
                     "UDR request buffer is corrupt or contains no data");
          sqlBuf->bufferFull();
	}
        break;

        case UDR_MSG_RS_CONTINUE:
	{
	  UdrRSContinueMsg *rsContinue =
            new (receiveMsgObj()) UdrRSContinueMsg(this);

	  udrGlob_->numReqRSContinue_++;
	  processAnRSContinueMessage(udrGlob_, *this, *rsContinue);
	}
	break;

        default:
        {
          UDR_ASSERT(FALSE,
                     "Unknown message type arrived on UDR data stream");
        } // default
        break;
        
      } // switch (t)
      
    } // while (getNextObjType(t))
  } // while (getNextReceiveMsg(t))

  // Make sure all reply buffers have been given to the connection. If
  // the only objects that arrived during this callback were continue
  // requests, then this action allows reply buffers associated with
  // those continue requests to propagate out of the stream and onto
  // the connection.
  //
  // If numOfInputBuffers() is > 0 then we do not need to do anything
  // at this point. This callback will be invoked again when the
  // incoming message is complete and ready to be processed.
  Lng32 numInputBuffers = numOfInputBuffers();
  if (somethingArrived && numInputBuffers == 0 &&
      spinfo_->getCurrentRequest() == NULL)
  {
    responseDone();

    if (udrGlob_->verbose_ &&
        udrGlob_->traceLevel_ >= TRACE_IPMS &&
        udrGlob_->showMain_)
    {
      ServerDebug("[UdrServ (%s)] All messages marked as replied", moduleName);
    }

    // Cleanup any unpacked message buffers containing only objects
    // that are no longer in use, as determined by the virtual method
    // IpcMessageObj::msgObjIsFree()
    releaseBuffers();  // Do final garbage collection
  }
  
} // UdrServerDataStream::actOnReceive()
/////////////////////////////////////////////////////////////////
// Copies the row pointer by rowPtr for rowLen inside sqlBuffer.
// The controlInfo must be the same pointer that was returned by
// proc ExSPGetInputRow along with the input row that corresponds
// to the reply rows.
// If replyRow is NULL, that that indicates that all reply rows
// for this input have been returned. A NULL replyRow MUST be
// passed in to this proc to end the request.
//
// This proc returns a value of 1, if replyBuffer is full.
// The reply row that was passed in in that call is NOT moved
// in to the replyBuffer. Caller must call this proc again with
// the replyRow. This applies to both non-null and null reply row.
//
// Returns 1, if buffer is full. 0, if row moved in.
//        -1, in case of error.
//         2 in case of warning. 
/////////////////////////////////////////////////////////////////
SQLCLI_LIB_FUNC
short ExSPPutReplyRow(void * replyBuffer,     // IN: the reply buffer
		      void * controlInfo,     // IN: control info
		      char * replyRow,        // IN: pointer to reply row
		      ULng32 rowLen,   // IN: length of reply row
		      ComDiagsArea* diagsDesc)// IN: pointer to diags
{
  if ((replyBuffer == NULL) || (controlInfo == NULL))
    return -1;

  SqlBuffer  * rb = (SqlBuffer *)replyBuffer;
  ControlInfo * ci = (ControlInfo *)controlInfo;
  
  short rc = 0;
  up_state us;
  us.parentIndex = ci->getDownState().parentIndex;
  us.downIndex = 0;
  us.setMatchNo(0);
      
  if (replyRow == NULL)  // indicate end of reply rows
    {
      if (diagsDesc != NULL) 
	{
	  if (diagsDesc->getNumber(DgSqlCode::ERROR_) > 0)
	    us.status = ex_queue::Q_SQLERROR;
	  else
	    if (diagsDesc->getNumber(DgSqlCode::WARNING_) > 0)
	      {
		us.status = ex_queue::Q_NO_DATA;
		rc = 2;
	      }
	 
	}
      else
	us.status = ex_queue::Q_NO_DATA;

      tupp_descriptor* dDesc = 0;
      
      if (rb->moveInSendOrReplyData(FALSE,  // reply
				    TRUE,   // do move EOD indication 
				    FALSE,  // don't move data.
				    (void *)&us,
				    sizeof(ControlInfo),
				    0,
				    0,
				    0, 
				    diagsDesc,
				    &dDesc) == SqlBuffer::MOVE_SUCCESS)
	{
	  if (diagsDesc)
	    diagsDesc->packObjIntoMessage(dDesc->getTupleAddress());
	}
      else
	{
	  rc = 1; // buffer is full
	}
    }
  else
    {
      tupp_descriptor * tdesc = NULL;
      us.status = ex_queue::Q_OK_MMORE;
      if (rb->moveInSendOrReplyData(FALSE, // reply
				    FALSE, // don't move control,if not needed.
				    TRUE,  // do move data.
				    (void *)&us,
				    sizeof(ControlInfo),
				    0,
				    rowLen,
				    &tdesc,
				    0,
				    0) == SqlBuffer::MOVE_SUCCESS)
	{
#pragma nowarn(1506)   // warning elimination 
	  str_cpy_all(tdesc->getTupleAddress(), replyRow, rowLen);
#pragma warn(1506)  // warning elimination 
	}
      else
	{
	  rc = 1;// buffer is full.
	}
    }

  return rc;
}
Esempio n. 9
0
NABoolean allocateReplyRow(UdrGlobals *UdrGlob,
  SqlBuffer &replyBuffer,       // [IN]  A reply buffer
  queue_index parentIndex,      // [IN]  Identifies the request queue entry
  Int32 replyRowLen,              // [IN]  Length of reply row
  char *&newReplyRow,           // [OUT] The allocated reply row
  ControlInfo *&newControlInfo, // [OUT] The allocated ControlInfo entry
  ex_queue::up_status upStatus  // [IN]  Q_OK_MMORE, Q_NO_DATA, Q_SQLERROR
  )
{
  const char *moduleName = "allocateReplyRow";

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

  NABoolean result = FALSE;
  SqlBufferBase::moveStatus status;
  up_state upState;
  upState.parentIndex = parentIndex;
  upState.downIndex = 0;
  upState.setMatchNo(0);

  upState.status = upStatus;

  tupp_descriptor *tdesc = NULL, **tuppDesc;
  ControlInfo **ctrlInfo;
  NABoolean moveCtrlInfo, moveDataInfo;

  switch (upStatus)
  {
    case ex_queue::Q_OK_MMORE :
    {
      ctrlInfo = &newControlInfo;
      moveCtrlInfo = TRUE;
      moveDataInfo = TRUE;
      tuppDesc = &tdesc;
      break;
    }

    case ex_queue::Q_SQLERROR :
    {
      ctrlInfo = &newControlInfo;
      moveCtrlInfo = TRUE;
      moveDataInfo = FALSE;
      tuppDesc = NULL;
      break;
    }

    case ex_queue::Q_NO_DATA :
    {
      ctrlInfo = NULL;
      moveCtrlInfo = TRUE;
      moveDataInfo = FALSE;
      tuppDesc = NULL;
      break;
    }

    default:
    {
      UDR_ASSERT(FALSE, "Unknown ex_queue::up_status value.");
      return FALSE;
    }
  }

  status = replyBuffer.moveInSendOrReplyData(
    FALSE,                           // [IN] sending? (vs. replying)
    moveCtrlInfo,                    // [IN] force move of ControlInfo?
    moveDataInfo,                    // [IN] move data?
    (void *) &upState,               // [IN] queue state
    sizeof(ControlInfo),             // [IN] length of ControlInfo
    ctrlInfo,                        // [OUT] new ControlInfo
    replyRowLen,                     // [IN] data row length
    tuppDesc,                        // [OUT] new data tupp_desc
    NULL,                            // [IN] diags area
    0                                // [OUT] new diags tupp_desc
    );

  if (status == SqlBufferBase::MOVE_SUCCESS)
  {
    if (upStatus == ex_queue::Q_OK_MMORE)
    {
       newReplyRow = tdesc->getTupleAddress();
       memset(newReplyRow, 0, replyRowLen);
    }
    result = TRUE;
  }
  else
  {
    result = FALSE;
  }
  return result;
}