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; }