예제 #1
0
// print MDFWriter errors to cout
void SQLJFile::printMDFWriterErrors(char *errFileName)
{
  char args[1024], EorW[10];
  Int32  errNum;
  FILE *errFile = fopen(errFileName, "r");
  if (errFile) {
    // accommodate case of MDFWriter dumping more entries into its errFile
    // than can fit into the fixed-size diags area. Do this by feeding
    // and then dumping diags one entry at a time.
    ComDiagsArea *myDiags = ComDiagsArea::allocate(mxCUMptr->heap());
    while (fscanf(errFile, "%s %d ", EorW, &errNum) != EOF) {
      size_t sLen = 0;
      if (fgets(args, 1024, errFile) == NULL) { // fgets got EOF or an error
        args[0] = 0; // empty string
        *mxCUMptr << FAIL;
      }
      else { // fgets got something
        sLen = strlen(args);
        // chop off terminating newline
        if (args[sLen-1] == '\n') {
          args[sLen-1] = 0;
        }
        if (sLen >= 1023) { // diagnostic msg is too long
          // toss rest of line
          Int32 nxtCh;
          do {
            nxtCh = fgetc(errFile);
          } while (nxtCh != '\n' && nxtCh != EOF);
        }
      }
      if (!myDiags) { // no diags
        *mxCUMptr << FAIL;
        if (sLen >= 1023) { // diagnostic msg is too long
          cerr << "Diagnostic message is over 1023 characters long." << endl;
        }
        // echo error file entry to cerr
        cerr << EorW << " " << errNum << " " << args << endl;
      }
      else {
        if (sLen >= 1023) { // diagnostic msg is too long
          *mxCUMptr << WARNING;
          *myDiags << DgSqlCode(2237);
        }
        switch (errNum) {
        case 2224:
        case 2225:
        case 2226:
          *mxCUMptr << FAIL; 
          *myDiags << DgSqlCode(-errNum);
          break;
        case 2227:
        case 2228:
        case 2230:
          *mxCUMptr << FAIL;
          *myDiags << DgSqlCode(-errNum) << DgString0(args);
          break;
        case 2229:
          *mxCUMptr << ERROR;
          *myDiags << DgSqlCode(-errNum) << DgString0(args);
          break;
        default:
          *mxCUMptr << (EorW[0]=='E' ? ERROR :
                        (EorW[0]=='W' ? WARNING : FAIL));
          *myDiags << DgSqlCode(-2231) << DgInt0(errNum) 
                   << DgString0(EorW) << DgString1(args);
          break;
        } // end switch
        NADumpDiags(cerr, myDiags, TRUE);
        myDiags->clear();
      } // end if
    } // end while
    if (myDiags) {
      myDiags->decrRefCount();
    }
    fclose(errFile);
  }
  else {
    *mxCUMptr << FAIL << DgSqlCode(-2218) << DgString0(errFileName);
  }
  // clean up temporary file (MDFWriter errors)
  remove(errFileName);
}
예제 #2
0
void processALoadMessage(UdrGlobals *UdrGlob,
                         UdrServerReplyStream &msgStream,
                         UdrLoadMsg &request,
                         IpcEnvironment &env)
{
  const char *moduleName = "processALoadMessage";
  char errorText[MAXERRTEXT];

  ComDiagsArea *diags = ComDiagsArea::allocate(UdrGlob->getIpcHeap());

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

  NABoolean showLoadLogic = (UdrGlob->verbose_ &&
                             UdrGlob->traceLevel_ >= TRACE_IPMS &&
                             UdrGlob->showLoad_);

  if (showLoadLogic)
  {
    ServerDebug("[UdrServ (%s)] Processing load request", moduleName);
  }

  // UDR_LOAD message always comes with transaction and they are out
  // side Enter Tx and Exit Tx pair. Make sure we are under correct
  // transaction.
  msgStream.activateCurrentMsgTransaction();

  //
  // Check to see if the incoming UDR handle has already been seen
  //
  NABoolean handleAlreadyExists = FALSE;
  SPInfo *sp = UdrGlob->getSPList()->spFind(request.getHandle());
  if (sp)
  {
    handleAlreadyExists = TRUE;
    if (showLoadLogic)
    {
      ServerDebug("    Duplicate handle arrived");
      ServerDebug("    SPInfoState is %s", sp->getSPInfoStateString());
    }

    if (sp->getSPInfoState() != SPInfo::UNLOADING)
    {
      //
      // An SPInfo exists but it is not one of the token instances to
      // represent an out-of-sequence LOAD/UNLOAD. This is an internal
      // error. Something has been botched in the message protocol.
      //
      char buf[100];
      convertInt64ToAscii(request.getHandle(), buf);
      *diags << DgSqlCode(-UDR_ERR_DUPLICATE_LOADS);
      *diags << DgString0(buf);
    }
    else
    {
      // The LOAD/UNLOAD requests for this handle arrived
      // out-of-sequence. Nothing to do at this point. An empty reply
      // will be generated later in this function.
    }
  }

  if (!handleAlreadyExists)
  {
    if (!UdrHandleIsValid(request.getHandle()))
    {
      *diags << DgSqlCode(-UDR_ERR_MISSING_UDRHANDLE);
      *diags << DgString0("Load Message");
    }
    else
    {
      //
      // First process the metadata in the LOAD requests and then
      // contact Language Manager to load the SP.
      //
      sp = processLoadParameters(UdrGlob, request, *diags);
      
      if (showLoadLogic)
      {
        ServerDebug("[UdrServ (%s)]  About to call LM::getRoutine",
                    moduleName);
      }
      
      if (sp == NULL)
      {
        *diags << DgSqlCode(-UDR_ERR_UNABLE_TO_ALLOCATE_MEMORY);
        *diags << DgString0("SPInfo");
      }
      else
      {
        UdrGlob->setCurrSP(sp);
        LmRoutine *lmRoutine;
        LmResult lmResult;
        LmLanguageManager *lm =
          UdrGlob->getOrCreateLM(lmResult, sp->getLanguage(), diags);
        LmHandle emitRowFuncPtr;

        if (sp->getParamStyle() == COM_STYLE_CPP_OBJ)
          emitRowFuncPtr = (LmHandle)&SpInfoEmitRowCpp;
        else
          emitRowFuncPtr = (LmHandle)&SpInfoEmitRow;
        
        if (lm)
        {
          if (sp->getParamStyle() == COM_STYLE_JAVA_OBJ ||
              sp->getParamStyle() == COM_STYLE_CPP_OBJ)
            {
              lmResult = lm->getObjRoutine(
                   request.getUDRSerInvocationInfo(),
                   request.getUDRSerInvocationInfoLen(),
                   request.getUDRSerPlanInfo(),
                   request.getUDRSerPlanInfoLen(),
                   sp->getLanguage(),
                   sp->getParamStyle(),
                   sp->getExternalName(),
                   sp->getContainerName(),
                   sp->getExternalPathName(),
                   sp->getLibrarySqlName(),
                   &lmRoutine,
                   diags);

              if (lmRoutine)
                {
                  LmRoutineCppObj *objRoutine =
                    static_cast<LmRoutineCppObj *>(lmRoutine);

                  if (sp->getParamStyle() == COM_STYLE_CPP_OBJ)
                    // set function pointers for functions provided
                    // by tdm_udrserv
                    objRoutine->setFunctionPtrs(SpInfoGetNextRow,
                                                SpInfoEmitRowCpp);

                  // add items to the UDRInvocationInfo that are not
                  // known at compile time (total # of instances is
                  // kind of known, but we want to give the executor a
                  // chance to change it)
                  lmRoutine->setRuntimeInfo(request.getParentQid(),
                                            request.getNumInstances(),
                                            request.getInstanceNum());

#ifndef NDEBUG
                  int debugLoop = 2;

                  if (objRoutine->getInvocationInfo()->getDebugFlags() &
                      tmudr::UDRInvocationInfo::DEBUG_LOAD_MSG_LOOP)
                    debugLoop = 1;
                  // go into a loop to allow the user to attach a debugger,
                  // if requested, set debugLoop = 2 in the debugger to get out
                  while (debugLoop < 2)
                    debugLoop = 1-debugLoop;
#endif

                }
            }
          else
            lmResult = lm->getRoutine(sp->getNumParameters(),
                                      sp->getLmParameters(),
                                      sp->getNumTables(),
                                      sp->getLmTables(),
                                      sp->getReturnValue(),
                                      sp->getParamStyle(),
                                      sp->getTransactionAttrs(),
                                      sp->getSQLAccessMode(),
                                      sp->getParentQid(),
                                      sp->getRequestRowSize(),
                                      sp->getReplyRowSize(),
                                      sp->getSqlName(),
                                      sp->getExternalName(),
                                      sp->getRoutineSig(),
                                      sp->getContainerName(),
                                      sp->getExternalPathName(),
                                      sp->getLibrarySqlName(),
                                      UdrGlob->getCurrentUserName(),
                                      UdrGlob->getSessionUserName(),
                                      sp->getExternalSecurity(),
                                      sp->getRoutineOwnerId(),
                                      &lmRoutine,
                                      (LmHandle)&SpInfoGetNextRow,
                                      emitRowFuncPtr,
                                      sp->getMaxNumResultSets(),
                                      diags);
        }
        
        if (lmResult == LM_OK)
        {
          if (lmRoutine == NULL)
          {
            *diags << DgSqlCode(-UDR_ERR_MISSING_LMROUTINE);
            *diags << DgString0("error: returned a null LM handle");
            *diags << DgInt1((Int32)0);
          }
          else
          {
            sp->setLMHandle(lmRoutine);

	    // Retrieve any optional data from UdrLoadMsg.
	    copyRoutineOptionalData(request, sp);

            reportLoadResults(UdrGlob, sp, lmRoutine);
            sp->setSPInfoState(SPInfo::LOADED);
          }

        } // lmResult == LM_OK

        if (showLoadLogic)
        {
          if (lmResult == LM_OK)
          {
            sprintf(errorText,
                    "[UdrServ (%.30s)]  LM::getRoutine was successful.",
                    moduleName);
          }
          else
          {
            sprintf(errorText,
                    "[UdrServ (%.30s)]  LM::getRoutine resulted in error.",
                    moduleName);
          }
          ServerDebug(errorText);
          doMessageBox(UdrGlob, TRACE_SHOW_DIALOGS,
                       UdrGlob->showMain_, errorText);
        }

        if (sp && !(sp->isLoaded()))
        {
          sp->setSPInfoState(SPInfo::LOAD_FAILED);
        }

      } // if (sp == NULL) else ...
    } // if (handle is not valid) else ...
  } // !handleAlreadyExists

  // build a reply and send it
  msgStream.clearAllObjects();

  UdrLoadReply *reply = new (UdrGlob->getIpcHeap())
    UdrLoadReply(UdrGlob->getIpcHeap());

  if (reply == NULL)
  {  // no reply buffer build...
    controlErrorReply(UdrGlob, msgStream, UDR_ERR_MESSAGE_PROCESSING,
                      INVOKE_ERR_NO_REPLY_BUFFER, NULL);
    return;
  }

  // Only return a valid UDR Handle if diagnostics are not present and
  // no LM errors occurred. We also return a valid handle if this LOAD
  // arrived out-of-sequence after the UNLOAD and no diagnostics have
  // been generated yet.
  if (diags && diags->getNumber() > 0)
  {
    reply->setHandle(INVALID_UDR_HANDLE);
  }
  else if (sp)
  {
    if (sp->isLoaded() || handleAlreadyExists)
    {
      reply->setHandle(sp->getUdrHandle());
    }
    else
    {
      reply->setHandle(INVALID_UDR_HANDLE);
    }
  }

  msgStream << *reply;

  if (diags && diags->getNumber() > 0)
  {
    msgStream << *diags;
    UdrGlob->numErrUDR_++;
    UdrGlob->numErrSP_++;
    UdrGlob->numErrLoadSP_++;
    if (showLoadLogic)
      dumpDiagnostics(diags, 2);
  }

  if (showLoadLogic)
  {
    ServerDebug("[UdrServ (%s)] About to send LOAD reply", moduleName);
  }

#ifdef NA_DEBUG_C_RUNTIME
  if (UdrGlob && UdrGlob->getJavaLM())
  {
    sleepIfPropertySet(*(UdrGlob->getJavaLM()),
                       "MXUDR_LOAD_DELAY", diags);
  }
#endif // NA_DEBUG_C_RUNTIME

  sendControlReply(UdrGlob, msgStream, sp);

  if (diags)
  {
    diags->decrRefCount();
  }

  reply->decrRefCount();

} // processALoadMessage
예제 #3
0
void EspNewIncomingConnectionStream::actOnReceive(IpcConnection *connection)
{
  // check for OS errors
  if (getState() == ERROR_STATE)
  {
    ex_assert(FALSE,"Error while receiving first message from client");
  }

  // check for protocol errors
  bool willPassTheAssertion = 
             (getType() == IPC_MSG_SQLESP_DATA_REQUEST OR
              getType() == IPC_MSG_SQLESP_CANCEL_REQUEST) AND
              getVersion() == CurrEspRequestMessageVersion AND
              moreObjects();
  if (!willPassTheAssertion)
  {
    char *doCatchBugCRx = getenv("ESP_BUGCATCHER_CR_NONUMBER");
    if (!doCatchBugCRx ||
        *doCatchBugCRx != '0')
    {
      connection->dumpAndStopOtherEnd(true, false);
      environment_->getControlConnection()->
        castToGuaReceiveControlConnection()->
        getConnection()->dumpAndStopOtherEnd(true, false);
    }
  }

  ex_assert((getType() == IPC_MSG_SQLESP_DATA_REQUEST OR
             getType() == IPC_MSG_SQLESP_CANCEL_REQUEST) AND
	    getVersion() == CurrEspRequestMessageVersion AND
	    moreObjects(),
	    "Invalid first message from client");

  // take a look at the type of the first object in the message
  IpcMessageObjType nextObjType = getNextObjType();
  switch (nextObjType)
  {
    case ESP_OPEN_HDR:
    case ESP_LATE_CANCEL_HDR:
      {
        ExFragKey key;
        Lng32 remoteInstNum;
        NABoolean isParallelExtract = false; 

        // peek at the message header to see for whom it is
        if (nextObjType == ESP_OPEN_HDR)
        {
          ExEspOpenReqHeader reqHdr((NAMemory *) NULL);
	   
	  *this >> reqHdr;
	  key = reqHdr.key_;
	  remoteInstNum = reqHdr.myInstanceNum_;
	  if (reqHdr.getOpenType() == ExEspOpenReqHeader::PARALLEL_EXTRACT) 
          {
            isParallelExtract = true;
	  }
	}
        else
	{
          // note that the late cancel request may or may not
	  // arrive as the first request (only in the former case
	  // will we reach here)
	  ExEspLateCancelReqHeader reqHdr((NAMemory *) NULL);
	   
	  *this >> reqHdr;
	  key = reqHdr.key_;
	  remoteInstNum = reqHdr.myInstanceNum_;
	}

        if (!isParallelExtract) 
        {
          ExFragInstanceHandle handle =
	    espFragInstanceDir_->findHandle(key);

	  if (handle != NullFragInstanceHandle)
	  {
            // the send bottom node # myInstanceNum of this downloaded fragment
            // is the true recipient of this open request
            ex_split_bottom_tcb * receivingTcb =
              espFragInstanceDir_->getTopTcb(handle);
            ex_send_bottom_tcb *receivingSendTcb =
              receivingTcb->getSendNode(remoteInstNum);

            // Check the connection for a co-located client, and if so,
            // tell the split bottom, because it may prefer this send 
            // bottom when using skew buster uniform distribution.
            if (espFragInstanceDir_->
                  getEnvironment()->
                  getMyOwnProcessId(IPC_DOM_GUA_PHANDLE).match(
                    connection->getOtherEnd().getNodeName(),
                    connection->getOtherEnd().getCpuNum()))
              receivingTcb->setLocalSendBottom(remoteInstNum);

            // Portability note for the code above: we pass IPC_DOM_GUA_PHANDLE
            // for IpcEnvironment::getMyOwnProcessId, even though that method
            // can be called with the default param (IpcNetworkDomain 
            // IPC_DOM_INVALID).  In fact it would  probably be better 
            // to call the object without specifying the IpcNetworkDomain so
            // that it can decide for itself what domain it is using.
            // But there is a problem with the Windows implementation
            // of IpcEnvironment::getMyOwnProcessId, it seems to assume
            // that its domain is IPC_DOM_INTERNET and so this will 
            // cause the botch of an assertion that its control connection 
            // (which is type EspGuaControlConnection) can be cast to a 
            // SockControlConnection.  When this problem is fixed, the 
            // IPC_DOM_GUA_PHANDLE param above can be removed.  Also,
            // when this code is ported to run it a domain other than
            // "guardian", it will be necessary to fix this and to
            // fix IpcEnvironment::getMyOwnProcessId to work properly on
            // windows.

            receivingSendTcb->setClient(connection);
            receivingSendTcb->routeMsg(*this);
          }
	  else
	  {
            connection->dumpAndStopOtherEnd(true, false);
	    ex_assert(FALSE,"entry not found, set diagnostics area and reply");
	  }

        } // normal case, not parallel extract

        else 
        {
          // The OPEN request is from a parallel extract consumer. The
          // incoming request contains a user ID which we will compare
          // against the current user ID for this ESP.

          // NOTE: The user ID for the extract security check is
          // currently sent and compared as a C string. On Linux it is
          // possible to send and compare integers which would lead to
          // simpler code. The code to send/compare strings is still
          // used because it works on all platforms.

          char errorStr[150];

	  // check if next msg is of securityInfo type. 
          ex_assert(moreObjects(), "expected object not received");
          ex_assert(getNextObjType() == ESP_SECURITY_INFO,
	            "received message for unknown message type");
          
	  // unpack security info
	  ExMsgSecurityInfo secInfo(environment_->getHeap());
	  *this >> secInfo;

          // Get the auth ID of this ESP in text form and compare it
          // to the auth ID that arrived in the message. Skip this
          // step in the debug build if an environment variable is
          // set.
          NABoolean doAuthIdCheck = TRUE;
          Int32 status = 0;
#ifdef _DEBUG
          const char *envvar = getenv("NO_EXTRACT_AUTHID_CHECK");
          if (envvar && envvar[0])
            doAuthIdCheck = FALSE;
#endif
          if (doAuthIdCheck)
          {
            // Get user ID from ExMsgSecurityInfo -> (secUserID)
            // the user ID is the integer value made into a string
            // Convert it back into its integer value
            short userIDLen = (short) str_len(secInfo.getAuthID());
            Int32 secUserID = str_atoi(secInfo.getAuthID(), userIDLen);

            // Get the current user ID
            Int32 curUserID = ComUser::getSessionUser(); 

            // Report an error if the user ID is not valid
            if (curUserID == NA_UserIdDefault || secUserID == NA_UserIdDefault)
            {
              str_cpy_c(errorStr,
                        "Producer ESP could not authenticate the consumer, "
                        "no valid current user.");
              status = -1;
            }

            // Make sure user id passed in ExMsgSecurityInfo matches
            // the user id associated with the current session

#if defined(_DEBUG)
            NABoolean doDebug = (getenv("DBUSER_DEBUG") ? TRUE : FALSE);
            if (doDebug)
              printf("[DBUSER:%d] ESP extract user ID: "
                     "local [%d], msg [%d]\n",
                     (int) getpid(), curUserID, secUserID);
#endif

              // Compare user ID, Report an error, if comparison fails
              if (curUserID != secUserID)
              {
                str_cpy_c(errorStr,
                          "Producer ESP could not authenticate the consumer, "
                          "user named passed in ExMsgSecurityInfo is not the "
                          "current user");
                status = -1;
              }

          } // if (doAuthIdCheck)
		   
          // get the split bottom TCB that matches the securityKey
          ex_split_bottom_tcb *receivingTcb = NULL;
          if (status == 0) 
          {
            receivingTcb = espFragInstanceDir_->getExtractTop(secInfo.getSecurityKey());
            if (receivingTcb == NULL) 
            {
              str_cpy_c(errorStr, "Producer ESP could not locate extract node");
              status = -1;
            }
          }

	  // get the sendBottom TCB if not already connected to a client
	  ex_send_bottom_tcb *receivingSendTcb = NULL;
	  if (status == 0)
	  {
	    receivingSendTcb = receivingTcb->getConsumerSendBottom();
	    if (receivingSendTcb == NULL) 
	    {
	      str_cpy_c(errorStr, "Producer ESP already connected to a client");
	      status = -1;
	    }
	  }

          // send the error message to the consumer 
	  if (status != 0) 
	  {
            clearAllObjects();
            setType(IPC_MSG_SQLESP_DATA_REPLY);

            NAMemory *heap = environment_->getHeap();

	    IpcMessageObj* baseObj =
	      new(heap)IpcMessageObj(IPC_SQL_DIAG_AREA, CurrEspReplyMessageVersion);
	    *this << *baseObj;

	    // prepare proper error message
	    char phandle[100];
	    MyGuaProcessHandle myHandle;
            myHandle.toAscii(phandle, 100);

	    ComDiagsArea *diags = ComDiagsArea::allocate(heap);
            *diags << DgSqlCode(-EXE_PARALLEL_EXTRACT_OPEN_ERROR)
                   << DgString0(phandle)
                   << DgString1(errorStr);
	    *this  << *diags;

	    diags->decrRefCount();

            send(TRUE /* TRUE indicates waited */);
          }

          // if everything okay, then make the connection
	  if (status == 0) 
          {
            receivingSendTcb->setClient(connection);
            receivingSendTcb->routeMsg(*this);
          }
        } // parallel extract case
      } // open or cancel header
예제 #4
0
ExWorkProcRetcode ExCancelTcb::work()
{

  ExMasterStmtGlobals *masterGlobals = 
     getGlobals()->castToExExeStmtGlobals()->castToExMasterStmtGlobals();

  CliGlobals *cliGlobals = masterGlobals->getCliGlobals();

  while ((qparent_.down->isEmpty() == FALSE) && 
         (qparent_.up->isFull() == FALSE))
  {
    ex_queue_entry *pentry_down = qparent_.down->getHeadEntry();
  
    switch (step_)
    {
      case NOT_STARTED:
      {
        if (pentry_down->downState.request == ex_queue::GET_NOMORE)
          step_ = DONE;
        else
        {
          retryCount_ = 0;
          // Priv checking is done during compilation. To support 
          // REVOKE, prevent a prepared CANCEL/SUSPEND/ACTIVATE
          // that was compiled more than 1 second ago from executing 
          // by raising the 8734 error to force an AQR. 
          Int64 microSecondsSinceCompile = NA_JulianTimestamp() - 
              masterGlobals->getStatement()->getCompileEndTime();

          if (microSecondsSinceCompile > 1000*1000)
          {

            ComDiagsArea *diagsArea =
              ComDiagsArea::allocate(getGlobals()->getDefaultHeap());
            *diagsArea << DgSqlCode(-CLI_INVALID_QUERY_PRIVS);
            reportError(diagsArea);
            step_ = DONE;
            break;
          }
          
          // Figure out which MXSSMP broker to use.
          if (cancelTdb().getAction() == ComTdbCancel::CancelByPname)
          {
            int nid = -1;
            int rc = msg_mon_get_process_info(cancelTdb().getCancelPname(),
                                &nid, &pid_);
            switch (rc)
            {
              case XZFIL_ERR_OK:
                cpu_ = (short) nid;
                break;
              case XZFIL_ERR_NOTFOUND:
              case XZFIL_ERR_BADNAME:
              case XZFIL_ERR_NOSUCHDEV:
                {
                  ComDiagsArea *diagsArea =
                    ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

                  *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND);
                  *diagsArea << DgString0(cancelTdb().getCancelPname());
                  reportError(diagsArea);

                  step_ = DONE;
                  break;
                }
              default:
                {
                  char buf[200];
                  str_sprintf(buf, "Unexpected error %d returned from "
                                   "msg_mon_get_process_info", rc);
                  ex_assert(0, buf);
                }
            }
            if (step_ != NOT_STARTED)
              break;
          }
          else if  (cancelTdb().getAction() == ComTdbCancel::CancelByNidPid)
          {
            cpu_ = (short) cancelTdb().getCancelNid();
            pid_ = cancelTdb().getCancelPid();

            // check that process exists, if not report error.
            char processName[MS_MON_MAX_PROCESS_NAME];
            int rc = msg_mon_get_process_name(cpu_, pid_, processName);
            if (XZFIL_ERR_OK == rc)
              ; // good. nid & pid are valid.
            else
            {
              if ((XZFIL_ERR_NOTFOUND  != rc) &&
                  (XZFIL_ERR_BADNAME   != rc) &&
                  (XZFIL_ERR_NOSUCHDEV != rc))
              {
                // Log rc in case it needs investigation later.
               char buf[200];
               str_sprintf(buf, "Unexpected error %d returned from "
                                "msg_mon_get_process_name", rc);
               SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__,
                                               buf, 0);
              }
              char nid_pid_str[32];
              str_sprintf(nid_pid_str, "%d, %d", cpu_, pid_);
              ComDiagsArea *diagsArea =
                    ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

              *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND);
              *diagsArea << DgString0(nid_pid_str);
              reportError(diagsArea);

              step_ = DONE;
              break;
            }
          }
          else
          {
            char * qid = cancelTdb().qid_;
            Lng32 qid_len = str_len(qid);

            // This static method is defined in SqlStats.cpp.  It side-effects
            // the nodeName and cpu_ according to the input qid.
            if (getMasterCpu(
                  qid, qid_len, nodeName_, sizeof(nodeName_) - 1, cpu_) == -1)
            {
              ComDiagsArea *diagsArea =
                ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

              *diagsArea << DgSqlCode(-EXE_RTS_INVALID_QID);

              reportError(diagsArea);

              step_ = DONE;
              break;
            }
          }

          // Testpoints for hard to reproduce problems:
          bool fakeError8028 = false;
          fakeError8028 = (getenv("HP_FAKE_ERROR_8028") != NULL);
          if ((cliGlobals->getCbServerClass() == NULL) || fakeError8028)
          {
            ComDiagsArea *diagsArea = 
              ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

            *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND);
            *diagsArea << DgString0("$ZSM000");

            reportError(diagsArea);

            step_ = DONE;
            break;
          }

          ComDiagsArea *diagsArea = NULL;
          bool fakeError2024 = false;
          fakeError2024 = (getenv("HP_FAKE_ERROR_2024") != NULL);
        
          if (fakeError2024)
          {
            cbServer_ = NULL;
            diagsArea =
                  ComDiagsArea::allocate(getGlobals()->getDefaultHeap());
            if (getenv("HP_FAKE_ERROR_8142"))
            {
               *diagsArea << DgSqlCode(-8142);
               *diagsArea << DgString0(__FILE__);
               *diagsArea << DgString1("cbServer_ is NULL");
            }
            else
               *diagsArea << DgSqlCode(-2024);
          }
          else
            cbServer_ = cliGlobals->getCbServerClass()->allocateServerProcess(
                      &diagsArea, 
                      cliGlobals->getEnvironment()->getHeap(),
                      nodeName_,
                      cpu_,
                      IPC_PRIORITY_DONT_CARE,
                      FALSE,  // usesTransactions 
                      TRUE,   // waitedCreation
                      2       // maxNowaitRequests -- cancel+(1 extra).
                      );


          if (cbServer_ == NULL || cbServer_->getControlConnection() == NULL)
          {
            ex_assert(diagsArea != NULL, 
                      "allocateServerProcess failed, but no diags");

            // look for SQLCode 2024 
            // "*** ERROR[2024] Server Process $0~string0 
            // is not running or could not be created. Operating System 
            // Error $1~int0 was returned."
            // Remap to cancel-specfic error 8028.
            if (diagsArea->contains(-2024)  &&
                cancelTdb().actionIsCancel())
            {
              diagsArea->deleteError(diagsArea->returnIndex(-2024));
              reportError(diagsArea, true, EXE_CANCEL_PROCESS_NOT_FOUND, 
                          nodeName_, cpu_);
            }
            else
              reportError(diagsArea);

            step_ = DONE;
            break;
          }

          // the reportError method was not called -- see break above.
          if (diagsArea != NULL)
            diagsArea->decrRefCount();

          //Create the stream on the IpcHeap, since we don't dispose 
          // of it immediately.  We just add it to the list of completed 
          // messages in the IpcEnv, and it is disposed of later.

          cancelStream_  = new (cliGlobals->getIpcHeap())
                CancelMsgStream(cliGlobals->getEnvironment(), this);

          cancelStream_->addRecipient(cbServer_->getControlConnection());

        }

        step_ = SEND_MESSAGE;

        break;
      }  // end case NOT_STARTED

#pragma warning (disable : 4291)

      case SEND_MESSAGE:
      {
        RtsHandle rtsHandle = (RtsHandle) this;

        if (cancelTdb().actionIsCancel())
        {
          Int64 cancelStartTime = JULIANTIMESTAMP();

          Lng32 firstEscalationInterval = cliGlobals->currContext()->
                    getSessionDefaults()->getCancelEscalationInterval();

          Lng32 secondEscalationInterval = cliGlobals->currContext()->
                    getSessionDefaults()->getCancelEscalationMxosrvrInterval();

          NABoolean cancelEscalationSaveabend = cliGlobals->currContext()->
                    getSessionDefaults()->getCancelEscalationSaveabend();

          bool cancelLogging = (TRUE == cliGlobals->currContext()->
                    getSessionDefaults()->getCancelLogging());

          CancelQueryRequest *cancelMsg = new (cliGlobals->getIpcHeap()) 
            CancelQueryRequest(rtsHandle, cliGlobals->getIpcHeap(), 
                      cancelStartTime,
                      firstEscalationInterval,
                      secondEscalationInterval,
                      cancelEscalationSaveabend,
                      cancelTdb().getCommentText(),
                      str_len(cancelTdb().getCommentText()),
                      cancelLogging,
                      cancelTdb().action_ != ComTdbCancel::CancelByQid,
                      pid_,
                      cancelTdb().getCancelPidBlockThreshold());

#pragma warning (default : 4291)

          *cancelStream_ << *cancelMsg;

          cancelMsg->decrRefCount();
        }
        else if (ComTdbCancel::Suspend == cancelTdb().action_)
        {

          bool suspendLogging = (TRUE == cliGlobals->currContext()->
                    getSessionDefaults()->getSuspendLogging());

#pragma warning (disable : 4291)
          SuspendQueryRequest * suspendMsg = new (cliGlobals->getIpcHeap()) 
            SuspendQueryRequest(rtsHandle, cliGlobals->getIpcHeap(),
                                ComTdbCancel::Force ==
                                cancelTdb().forced_,
                                suspendLogging);
#pragma warning (default : 4291)

          *cancelStream_ << *suspendMsg;

          suspendMsg->decrRefCount();
        }
        else
        {
          ex_assert(
            ComTdbCancel::Activate == cancelTdb().action_,
            "invalid action for ExCancelTcb");

          bool suspendLogging = (TRUE == cliGlobals->currContext()->
                    getSessionDefaults()->getSuspendLogging());

#pragma warning (disable : 4291)
          ActivateQueryRequest * activateMsg = new (cliGlobals->getIpcHeap()) 
            ActivateQueryRequest(rtsHandle, cliGlobals->getIpcHeap(),
                                 suspendLogging);
#pragma warning (default : 4291)

          *cancelStream_ << *activateMsg;

          activateMsg->decrRefCount();
        }

        if ((cancelTdb().getAction() != ComTdbCancel::CancelByPname) &&
            (cancelTdb().getAction() != ComTdbCancel::CancelByNidPid))
        {
          char * qid = cancelTdb().qid_;
          Lng32 qid_len = str_len(qid);

#pragma warning (disable : 4291)
          RtsQueryId *rtsQueryId = new (cliGlobals->getIpcHeap())
                           RtsQueryId( cliGlobals->getIpcHeap(), qid, qid_len);
#pragma warning (default : 4291)

          *cancelStream_ << *rtsQueryId;
          rtsQueryId->decrRefCount();
        }

        // send a no-wait request to the cancel broker.
        cancelStream_->send(FALSE);

        step_ = GET_REPLY;    
        // Come back when I/O completes.
        return WORK_OK; 

        break;
      }  // end case SEND_MESSAGE

      case GET_REPLY:
      {

        // Handle general IPC error.
        bool fakeError201 = false;
        fakeError201 = (getenv("HP_FAKE_ERROR_201") != NULL);
        if ((cbServer_->getControlConnection()->getErrorInfo() != 0) ||
            fakeError201)
        {
          ComDiagsArea *diagsArea = 
            ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

          cbServer_->getControlConnection()->
              populateDiagsArea( diagsArea, getGlobals()->getDefaultHeap());

          if (fakeError201)
          {
            *diagsArea << DgSqlCode(-2034) << DgInt0(201)
                       << DgString0("I say") << DgString1("control broker");
          }

          if (diagsArea->contains(-8921))
          {
            // Should not get timeout error 8921. Get a core-file
            // of the SSMP and this process too so that this can be
            // debugged.
            cbServer_->getControlConnection()->
              dumpAndStopOtherEnd(true, false);
            genLinuxCorefile("Unexpected timeout error");
          }

          reportError(diagsArea);

          step_ = DONE;
          break;
        }

        // See if stream has the reply yet.
        if (!cancelStream_->moreObjects())
          return WORK_OK; 

#pragma warning (disable : 4291)

        ControlQueryReply *reply = new (cliGlobals->getIpcHeap()) 
              ControlQueryReply(INVALID_RTS_HANDLE, cliGlobals->getIpcHeap());

#pragma warning (default : 4291)

        *cancelStream_ >> *reply;

        if (reply->didAttemptControl())
        {
          // yeaah!
          cancelStream_->clearAllObjects();
        }
        else
        {
          if (cancelStream_->moreObjects() &&
              cancelStream_->getNextObjType() == IPC_SQL_DIAG_AREA)
          {
            ComDiagsArea *diagsArea = 
              ComDiagsArea::allocate(getGlobals()->getDefaultHeap());

            *cancelStream_ >> *diagsArea;
            cancelStream_->clearAllObjects();

            if ( retryQidNotActive_ &&
                (diagsArea->mainSQLCODE() == -EXE_SUSPEND_QID_NOT_ACTIVE) &&
                (++retryCount_ <= 60))
            {
              SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, 
                                             "Retrying error 8672.", 0);
              DELAY(500);
              diagsArea->decrRefCount();
              step_ = SEND_MESSAGE;
              break;
            }

            reportError(diagsArea);
          }
          else 
            ex_assert(0, "Control failed, but no diagnostics.");
        }

        step_ = DONE;
        break;
      }
      case DONE: 
      {
        if (cancelStream_)
        {
          cancelStream_->addToCompletedList();
          cancelStream_ = NULL;
        }
        if (cbServer_)
        {
          cbServer_->release();
          cbServer_ = NULL;
        }

        ex_queue_entry * up_entry = qparent_.up->getTailEntry();
        up_entry->copyAtp(pentry_down);
        up_entry->upState.parentIndex = pentry_down->downState.parentIndex;
        up_entry->upState.downIndex = qparent_.down->getHeadIndex();     
        up_entry->upState.setMatchNo(1);
        up_entry->upState.status = ex_queue::Q_NO_DATA;
        qparent_.up->insert();

        qparent_.down->removeHead();

        step_ = NOT_STARTED;
        break;
      }
      default:
        ex_assert( 0, "Unknown step_.");
    }