ex_expr::exp_return_type ExExeUtilTcb::evalScanExpr(char * ptr, Lng32 len,
                                                    NABoolean copyToVCbuf)
{
  ex_expr::exp_return_type exprRetCode = ex_expr::EXPR_OK;

  if (exeUtilTdb().scanExpr_)
    {
      ex_queue_entry * pentry_down = qparent_.down->getHeadEntry();

      char * exprPtr = ptr;
      if (copyToVCbuf)
        {
          exprPtr = new(getGlobals()->getDefaultHeap())
            char[SQL_VARCHAR_HDR_SIZE + len];
          short shortLen = (short)len;
          str_cpy_all((char*)exprPtr, (char*)&shortLen, SQL_VARCHAR_HDR_SIZE);
          str_cpy_all(&exprPtr[SQL_VARCHAR_HDR_SIZE], ptr, shortLen);
        }

      workAtp_->getTupp(exeUtilTdb().workAtpIndex())
	.setDataPointer(exprPtr);

      exprRetCode =
	exeUtilTdb().scanExpr_->eval(pentry_down->getAtp(), workAtp_);

      if (exprPtr != ptr)
        NADELETEBASIC(exprPtr, getGlobals()->getDefaultHeap());
    }

  return exprRetCode;
}
short ExExeUtilTcb::moveRowToUpQueue(const char * row, Lng32 len, 
				     short * rc, NABoolean isVarchar)
{
  short retcode = ex_tcb::moveRowToUpQueue(&qparent_, exeUtilTdb().tuppIndex_,
                                           row, len, rc, isVarchar);
  return  retcode;
}
short ExExeUtilTcb::createServer(char *serverName,
				 const char * inPName,
				 IpcServerTypeEnum serverType,
				 IpcServerAllocationMethod servAllocMethod,
				 char *nodeName,
				 short cpu,
				 const char *partnName,
				 Lng32 priority,
				 IpcServer* &ipcServer,
				 NABoolean logError,
				 const char * operation)
{
  short error = 0;

 // Get the globals stucture of the master executor.
  ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals();
  ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals();

  IpcEnvironment * env = masterGlob->getCliGlobals()->getEnvironment(); 
  NAHeap *ipcHeap = masterGlob->getCliGlobals()->getIpcHeap();


  IpcServerClass * sc =
    new (ipcHeap) IpcServerClass(env, serverType,
				     servAllocMethod, //IPC_LAUNCH_GUARDIAN_PROCESS,
				     COM_VERS_MXV, nodeName);
  if (!sc)
    {
      if (logError)
        {
          char emsText[400+ComMAX_3_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES];
          str_sprintf(emsText, "Failure creating IpcServerClass on \\%s cpu %d to %s %s for %s.", 
		      nodeName, cpu, operation, partnName, 
		      (char *)exeUtilTdb().getTableName());
          SQLMXLoggingArea::logExecRtInfo(NULL, 0, emsText, 0);
        }
      return -1;
    }

  const char * pName = NULL;
  char pNameBuf[20];
  short pNameLen = 0;

  if (inPName)
    pName = inPName;
  else
    {
      pName = pNameBuf;

      pNameBuf[pNameLen] = 0;
    }

  ipcServer =
    sc->allocateServerProcess(&diagsArea_,
			      ipcHeap,
			      nodeName,
			      cpu,
			      priority, 
			      1, // espLevel (not relevent)
			      FALSE, // no Xn
			      TRUE, // waited creation
			      0, // maxNowaitRequests
			      serverName,
			      pName
			      );
  if (!ipcServer)
    {
      if (logError && diagsArea_)
        {
          char emsText[400+ComMAX_3_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES];
          str_sprintf(emsText, "allocateServerProcess() failed with error %d on \\%s cpu %d to %s %s for %s.", 
		      diagsArea_->mainSQLCODE(), nodeName, cpu, operation,
		      partnName, (char *)exeUtilTdb().getTableName());
          SQLMXLoggingArea::logExecRtInfo(NULL, 0, emsText, 0);
        }
      NADELETE(sc, IpcServerClass, ipcHeap);
      return -3;
    }

  return 0;
}
//////////////////////////////////////////////////////
// work() for ExExeUtilLongRunningTcb
//////////////////////////////////////////////////////
short ExExeUtilLongRunningTcb::work()
{
  short rc = 0;
  Lng32 cliRC = 0;
  Int64 rowsDeleted = 0;
  Int64 transactions = 0;

  // if no parent request, return
  if (qparent_.down->isEmpty())
    return WORK_OK;
  
  // if no room in up queue, won't be able to return data/status.
  // Come back later.
  if (qparent_.up->isFull())
    return WORK_OK;
  
  ex_queue_entry * pentry_down = qparent_.down->getHeadEntry();
  ExExeUtilPrivateState & pstate =
    *((ExExeUtilPrivateState*) pentry_down->pstate);

  // Get the globals stucture of the ESP if this is an ESP
  ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals();
  ExEspStmtGlobals *espGlob = exeGlob->castToExEspStmtGlobals();


  Int32 espNum = 1;
 
  // this is an ESP?
  if (espGlob != NULL)
  {
     espNum = (Int32) espGlob->getMyInstanceNumber();
  }

  while (1)
    {
      switch (step_)
	{
	case INITIAL_:
	  {
	    step_ = LONG_RUNNING_;
	  }
	break;

	
	case LONG_RUNNING_:
	  {
	    rc = doLongRunning();
	    if ((rc < 0) || (rc == 100)) 
	      {
		finalizeDoLongRunning();
		if (rc <0)
		  step_ = ERROR_;
		else                       // rc == 100 - done with all the transactions.
		  step_ = DONE_;
	      }

            // continue in LONG_RUNNING_ state if (rc >= 0) - success and warning.
	  }
	break;

	
	case DONE_:
	  {
 
	    if (qparent_.up->isFull())
	      return WORK_OK;

	    // Return EOF.
	    ex_queue_entry * up_entry = qparent_.up->getTailEntry();
	    
	    up_entry->upState.parentIndex = 
	      pentry_down->downState.parentIndex;
	    
	    up_entry->upState.setMatchNo(0);
	    up_entry->upState.status = ex_queue::Q_NO_DATA;

	    // before sending the Q_NO_DATA, send the rowcount as well thro'
	    // the diagsArea.
	    
	    getDiagsArea()->setRowCount(getRowsDeleted());

            ComDiagsArea *diagsArea = getDiagAreaFromUpQueueTail();
            if (lrTdb().longRunningQueryPlan())
            {
               (*diagsArea) << DgSqlCode(8450)
                            << DgString0((char*)exeUtilTdb().getTableName())
                            << DgInt0(espNum)
                            << DgInt1((Lng32)getTransactionCount());
            }
	    
	    // insert into parent
	    qparent_.up->insert();
	    
	    //pstate.matches_ = 0;
	    // reset the parameters.
	    step_ = INITIAL_;
	    transactions_ = 0;
	    rowsDeleted_ = 0;
	    initial_ = 1;
	    
	    // clear diags if any
            if (getDiagsArea())
            {
                getDiagsArea()->clear();
            }
    
	    qparent_.down->removeHead();
 
	    return WORK_OK;
	  }
	break;

	case ERROR_:
	  {
	    if (qparent_.up->isFull())
	      return WORK_OK;

	    // Return EOF.
	    ex_queue_entry * up_entry = qparent_.up->getTailEntry();
	    
	    up_entry->upState.parentIndex = 
	      pentry_down->downState.parentIndex;
	    
	    up_entry->upState.setMatchNo(0);
	    up_entry->upState.status = ex_queue::Q_SQLERROR;
	    // get rows deleted so far.
	    getDiagsArea()->setRowCount(getRowsDeleted());
	    ComDiagsArea *diagsArea = up_entry->getDiagsArea();
	    
	    if (diagsArea == NULL)
	      diagsArea = 
		ComDiagsArea::allocate(this->getGlobals()->getDefaultHeap());
            else
              diagsArea->incrRefCount (); // setDiagsArea call below will decr ref count
	    
	    if (getDiagsArea())
	      diagsArea->mergeAfter(*getDiagsArea());
	    
	    up_entry->setDiagsArea (diagsArea);
	    
	    // insert into parent
	    qparent_.up->insert();

	    // clear diags if any, since we already sent the information
	    // up and don't want to send it again as part of DONE_
            if (getDiagsArea())
            {
	      rowsDeleted_ = 0;
	      getDiagsArea()->clear();
            }
	    step_ = DONE_;
	  }
	break;

	} // switch
    } // while

}
short ExExeUtilLongRunningTcb::doLongRunning()
{
  Lng32 cliRC =0;
  short retcode = 0;
  NABoolean xnAlreadyStarted = FALSE;
     
  // Get the globals stucture of the master executor.
  ExExeStmtGlobals *exeGlob = getGlobals()->castToExExeStmtGlobals();
  ExMasterStmtGlobals *masterGlob = exeGlob->castToExMasterStmtGlobals();

  ex_queue_entry * pentry_down = qparent_.down->getHeadEntry();
  ExExeUtilPrivateState & pstate =
    *((ExExeUtilPrivateState*) pentry_down->pstate);


  CliGlobals *cliGlobals = 0;
  cliGlobals = GetCliGlobals();

  ex_assert(cliGlobals != NULL, "Cli globals is NULL - should have been allocated already");

  if (cliGlobals->isESPProcess())
  {
     if (!currTransaction_)
        currTransaction_ = new (getHeap()) ExTransaction (cliGlobals, getHeap());
  }
  else  // in master executor
  {
     currTransaction_ = masterGlob->getStatement()->getContext()->getTransaction();
  }


  if (currTransaction_->xnInProgress())
  {
     xnAlreadyStarted = TRUE;
  }

  // cannot run LRU when a user transaction is in progress
  if (xnAlreadyStarted)
  {
     ExHandleErrors(qparent_,
         pentry_down,
         0,
         getGlobals(),
         NULL,
         (ExeErrorCode)(-8603),
         NULL,
         exeUtilTdb().getTableName()
         );
     return (-8603);
  }

  SQL_EXEC_ClearDiagnostics(NULL);

  // no Xn in progress. Start one.
  cliRC = currTransaction_->beginTransaction ();

  if (cliRC < 0)
  {
      ExHandleErrors(qparent_,
        pentry_down,
        0,
        getGlobals(),
        NULL,
        (ExeErrorCode)(cliRC),
        NULL,
        exeUtilTdb().getTableName()
        );
       return (short) cliRC;
  }

  retcode = executeLongRunningQuery();

  // Rollback the transaction, if there is an error.
  if (retcode < 0)
  {
     // rollback the transaction
     cliRC = currTransaction_->rollbackTransaction ();

     return retcode;
  }
  else 
  {
    // commit the transaction
    cliRC = currTransaction_->commitTransaction ();

    if (cliRC < 0)
    {
       ExHandleErrors(qparent_,
           pentry_down,
           0,
           getGlobals(),
           NULL,
          (ExeErrorCode)(cliRC),
           NULL,
           exeUtilTdb().getTableName()
           );

       return short(cliRC);
    }

    addTransactionCount();
  }

  return retcode;
}