예제 #1
0
ex_expr::exp_return_type ExpLOBiud::insertDesc(char *op_data[],
					       CollHeap*h,
					       ComDiagsArea** diagsArea)
{
  Lng32 rc;

  Lng32 lobOperStatus = checkLobOperStatus();
  if (lobOperStatus == DO_NOTHING_)
    return ex_expr::EXPR_OK;

  char * result = op_data[0];

  // get the lob name where data need to be inserted
  char tgtLobNameBuf[100];
  char * tgtLobName = ExpGetLOBname(objectUID_, lobNum(), tgtLobNameBuf, 100);

  if (tgtLobName == NULL)
    return ex_expr::EXPR_ERROR;

  // call function with the lobname and source value
  // to insert it in the LOB.
  // Get back offset and len of the LOB.
  Int64 descSyskey = 0;

  char * lobHandle = NULL;
  Lng32 handleLen = 0;
  char lobHandleBuf[LOB_HANDLE_LEN];
  //  if (getExeGlobals()->lobGlobals()->getCurrLobOperInProgress())
  if (lobOperStatus == CHECK_STATUS_)
    {
      lobHandle = lobHandleSaved_;
      handleLen = lobHandleLenSaved_;
    }
  else
    {
      Int64 descTS = NA_JulianTimestamp();

      lobHandle = lobHandleBuf;
      ExpLOBoper::genLOBhandle(objectUID_, lobNum(), (short)lobStorageType(),
			       -1, descTS, -1,
			       descSchNameLen_, descSchName(),
			       handleLen, lobHandle);
    }

  LobsSubOper so = Lob_None;
  if (fromFile())
    so = Lob_File;
  else if (fromString() || fromLoad())
    so = Lob_Memory;
  else if (fromLob())
    so = Lob_Foreign_Lob;
  else if (fromBuffer())
    so = Lob_Buffer;

  

  Lng32 waitedOp = 0;
#ifdef __EID
  waitedOp = 0; // nowaited op from EID/TSE process
#else
  waitedOp = 1;
#endif

  //temptemp. Remove after ExLobsOper adds nowaited support.
  waitedOp = 1;

  // temp. Pass lobLen. When ExLobsOper fixes it so len is not needed during
  // lob desc update, then remove this.
  Int64 lobLen = getOperand(1)->getLength();

  blackBoxLen_ = 0;
  if (fromExternal())
    {
      blackBoxLen_ = getOperand(1)->getLength();
      str_cpy_and_null(blackBox_, op_data[1], (Lng32)blackBoxLen_,
		       '\0', ' ', TRUE);
    }

  Lng32 cliError = 0;
  char * lobData = NULL;
  lobData= new(h) char[lobLen];
  //send lobData only if it's a lob_file operation
  if (so == Lob_File)
    {
      str_cpy_and_null(lobData,op_data[1],lobLen,'\0',' ',TRUE);
      
    }
  if (so == Lob_Buffer)
    {
      memcpy(&lobLen, op_data[2],sizeof(Int64));
    }
  LobsOper lo ;
 
  if (lobOperStatus == CHECK_STATUS_)
    lo = Lob_Check_Status;
  else if (lobHandle == NULL)       
    lo = Lob_InsertDataSimple;
  else
    lo = Lob_InsertDesc;
  
    
  rc = ExpLOBInterfaceInsert
    (getExeGlobals()->lobGlobal(), 
     tgtLobName, 
     lobStorageLocation(),
     lobStorageType(),
     getLobHdfsServer(), getLobHdfsPort(),

     handleLen, lobHandle,
     &outHandleLen_, outLobHandle_,
     blackBoxLen_, blackBox_,
     requestTag_,
     getExeGlobals()->lobGlobals()->xnId(),
     descSyskey,
     lo,
     &cliError,
     so,
     waitedOp,
     lobData, lobLen, getLobMaxSize(), getLobMaxChunkMemSize(),getLobGCLimit());
  
  if (rc == LOB_ACCESS_PREEMPT)
    {
      // save the handle so it could be used after return from preempt
      lobHandleLenSaved_ = handleLen;
      str_cpy_all(lobHandleSaved_, lobHandle, handleLen);
      
      return ex_expr::EXPR_PREEMPT;
    }

  if (rc < 0)
    {
      Lng32 intParam1 = -rc;
      ExRaiseSqlError(h, diagsArea, 
		      (ExeErrorCode)(8442), NULL, &intParam1, 
		      &cliError, NULL, (char*)"ExpLOBInterfaceInsert",
		      getLobErrStr(intParam1));
      return ex_expr::EXPR_ERROR;
    }

  // extract and update lob handle with the returned values
  if (outHandleLen_ > 0)
    {
      ExpLOBoper::extractFromLOBhandle(NULL, NULL, NULL, NULL, &descSyskey,
				       NULL, NULL, NULL, outLobHandle_);
      
      ExpLOBoper::updLOBhandle(descSyskey, 0, lobHandle); 
    }

  str_cpy_all(result, lobHandle, handleLen);

  getOperand(0)->setVarLength(handleLen, op_data[-MAX_OPERANDS]);

  if (NOT fromExternal())
    {
      getExeGlobals()->lobGlobals()->lobLoadInfo()->
	setLobHandle(lobNum(), handleLen, lobHandle);
    }

  return ex_expr::EXPR_OK;
}
예제 #2
0
ex_expr::exp_return_type ExpLOBiud::insertData(Lng32 handleLen,
					       char * handle,
					       char *op_data[],
					       CollHeap*h,
					       ComDiagsArea** diagsArea)
{
  Lng32 rc = 0;

  Lng32 lobOperStatus = checkLobOperStatus();
  if (lobOperStatus == DO_NOTHING_)
    return ex_expr::EXPR_OK;

  Lng32 lobType;
  Int64 uid;
  Lng32 lobNum;
  Int64 lobLen;
  //  Lng32 flags;
  Int64 descSyskey = -1;
  //  Int64 descTS = -1;
  short numChunks = 0;
  //  short schNameLen = 0;
  //  char  schName[500];
  extractFromLOBhandle(NULL, &lobType, &lobNum, &uid,
		       &descSyskey, NULL, //&descTS, 
		       NULL, NULL, //&schNameLen, schName,
		       handle);
  
   // get the lob name where data need to be inserted
  char tgtLobNameBuf[100];
  char * tgtLobName = ExpGetLOBname(uid, lobNum, tgtLobNameBuf, 100);

  if (tgtLobName == NULL)
    return ex_expr::EXPR_ERROR;

  lobLen = getOperand(1)->getLength();
  
  char * lobData = NULL;
  if(fromFile())
    {
      lobData = new (h) char[lobLen];  
      str_cpy_and_null(lobData,op_data[1],lobLen,'\0',' ',TRUE);
    }
    else
      lobData = op_data[1];
  if (fromBuffer())
    {
      memcpy(&lobLen, op_data[2],sizeof(Int64)); // user specified buffer length
      memcpy(lobData,op_data[1],sizeof(Int64)); // user buffer address
    }
  LobsOper lo ;
 
  if (lobOperStatus == CHECK_STATUS_)
    lo = Lob_Check_Status;
  else if (handle == NULL)       
    lo = Lob_InsertDataSimple;
  else
    lo = Lob_InsertData;

  LobsSubOper so = Lob_None;
  if (fromFile())    
    so = Lob_File;       
  else if (fromString() || fromLoad())
    so = Lob_Memory;
  else if (fromLob())
    so = Lob_Foreign_Lob;
  else if(fromBuffer())
    so = Lob_Buffer;

 
  Lng32 waitedOp = 0;
#ifdef __EID
  waitedOp = 0; // nowaited op from EID/TSE process
#else
  waitedOp = 1;
#endif

  //temptemp. Remove after ExLobsOper adds nowaited support.
  waitedOp = 1;

  Lng32 cliError = 0;

  blackBoxLen_ = 0;

  if (fromLob())
    {
      Int64 srcDescKey = -1;
      Int64 srcDescTS = -1;
      char srcLobNameBuf[100];
      char * srcLobName = NULL;
      short srcSchNameLen = 0;
      char  srcSchName[500];
      extractFromLOBhandle(NULL, &lobType, &lobNum, &uid,
			   &srcDescKey, &srcDescTS, 
			   &srcSchNameLen, srcSchName,
			   op_data[1]);
      
      // get the lob name where data will be read from
      srcLobName = ExpGetLOBname(uid, lobNum, srcLobNameBuf, 100);
      if (srcLobName == NULL)
	return ex_expr::EXPR_ERROR;
    }
  else
    {
      rc = ExpLOBInterfaceInsert(getExeGlobals()->lobGlobal(), 
				 tgtLobName, 
				 lobStorageLocation(),
				 lobType,
				 getLobHdfsServer(), getLobHdfsPort(),

				 handleLen, handle,
				 &outHandleLen_, outLobHandle_,

				 blackBoxLen_, blackBox_,

				 requestTag_,
				 getExeGlobals()->lobGlobals()->xnId(),
				 
				 descSyskey, 
				 lo,
				 &cliError,
				 so,
				 waitedOp,				 
				 lobData,
				 lobLen,getLobMaxSize(),
                                 getLobMaxChunkMemSize(),
                                 getLobGCLimit());
    }

  if (rc == LOB_ACCESS_PREEMPT)
    {
      return ex_expr::EXPR_PREEMPT;
    }

  if (rc < 0)
    {
      Lng32 intParam1 = -rc;
      ExRaiseSqlError(h, diagsArea, 
		      (ExeErrorCode)(8442), NULL, &intParam1, 
		      &cliError, NULL, (char*)"ExpLOBInterfaceInsert",
		      getLobErrStr(intParam1));
      return ex_expr::EXPR_ERROR;
    }

  return ex_expr::EXPR_OK;
}
예제 #3
0
ex_expr::exp_return_type ExpLOBconvert::eval(char *op_data[],
					     CollHeap*h,
					     ComDiagsArea** diagsArea)
{
  Lng32 rc = 0;

  Lng32 lobOperStatus = checkLobOperStatus();
  if (lobOperStatus == DO_NOTHING_)
    return ex_expr::EXPR_OK;

  char * result = op_data[0];
  char * lobHandle = op_data[1];
  char *tgtFileName = NULL;
  Int32 handleLen = getOperand(1)->getLength(op_data[-MAX_OPERANDS+1]);

  Int64 uid;
  Lng32 lobType;
  Lng32 lobNum;
  Int64 descKey;
  Int64 descTS;
  Int16 flags;
  short schNameLen = 0;
  char schName[500];
  LobsSubOper so;
  Lng32 cliError = 0;

  Lng32 waitedOp = 0;
  Int64 lobLen = 0; 
  char *lobData = NULL;
#ifdef __EID
  waitedOp = 0; // nowaited op from EID/TSE process
#else
  waitedOp = 1;
#endif

  //temptemp. Remove after ExLobsOper adds nowaited support.
  waitedOp = 1;
  extractFromLOBhandle(&flags, &lobType, &lobNum, &uid,
			   &descKey, &descTS, 
			   &schNameLen, schName,
			   lobHandle);
  // get the lob name where data need to be inserted
  char lobNameBuf[100];
  char * lobName = ExpGetLOBname(uid, lobNum, lobNameBuf, 100);
      
 
  if(toFile())
    {
      so = Lob_File;
      tgtFileName = tgtFileName_;
      rc = ExpLOBInterfaceSelect(getExeGlobals()->lobGlobal(), 
				 lobName, 
				 lobStorageLocation(),
				 lobType,
				 getLobHdfsServer(), getLobHdfsPort(),

				 handleLen, lobHandle,
				 requestTag_,
                                 so,
				 getExeGlobals()->lobGlobals()->xnId(),
				 (lobOperStatus == CHECK_STATUS_ ? 1 : 0),
 				 waitedOp,

				 0, lobLen, lobLen, tgtFileName,getLobMaxChunkMemSize());
    }
  else if (toString())
    {
      so = Lob_Memory;
      
      if (lobName == NULL)
	return ex_expr::EXPR_ERROR;
      
      
      lobLen = getConvertSize(); 
      lobData = new(h) char[(Lng32)lobLen];
      rc = ExpLOBInterfaceSelect(getExeGlobals()->lobGlobal(), 
				 lobName, 
				 lobStorageLocation(),
				 lobType,
				 getLobHdfsServer(), getLobHdfsPort(),

				 handleLen, lobHandle,
				 requestTag_,
                                 so,
				 getExeGlobals()->lobGlobals()->xnId(),
				 (lobOperStatus == CHECK_STATUS_ ? 1 : 0),
 				 waitedOp,

				 0, lobLen, lobLen, lobData,getLobMaxChunkMemSize());

      if (rc == LOB_ACCESS_PREEMPT)
	{
	  return ex_expr::EXPR_PREEMPT;
	}
      
      if (rc < 0)
	{
	  Lng32 intParam1 = -rc;
	  ExRaiseSqlError(h, diagsArea, 
			  (ExeErrorCode)(8442), NULL, &intParam1, 
			  &cliError, NULL, (char*)"ExpLOBInterfaceSelect",
			  getLobErrStr(intParam1));
	  return ex_expr::EXPR_ERROR;
	}

      // store the length of substring in the varlen indicator.
      if (getOperand(0)->getVCIndicatorLength() > 0)
	{
	  getOperand(0)->setVarLength((UInt32)lobLen, op_data[-MAX_OPERANDS] );
	  if (lobLen > 0) 
	    str_cpy_all(op_data[0], lobData, (Lng32)lobLen);
	}
      else
	{
	  str_pad(result, getOperand(0)->getLength());
	  str_cpy_all(result, lobData, strlen(lobData));
	}
      NADELETEBASIC(lobData, h);
    }
  else
    return ex_expr::EXPR_ERROR;

  return ex_expr::EXPR_OK;
}
예제 #4
0
ex_expr::exp_return_type ExpLOBupdate::eval(char *op_data[],
					    CollHeap*h,
					    ComDiagsArea** diagsArea)
{
  Lng32 rc;

  Lng32 lobOperStatus = checkLobOperStatus();
  if (lobOperStatus == DO_NOTHING_)
    return ex_expr::EXPR_OK;

  char * result = op_data[0];

  char * lobHandle = NULL;
  Lng32 handleLen = 0;

  Lng32 sLobType;
  Int64 sUid;
  Lng32 sLobNum;
  Int64 sDescSyskey = -1;
  Int64 sDescTS = -1;
  Int16 sFlags;
  short sSchNameLen = 0;
  char sSchName[500];

  if (getOperand(2)->getNullFlag() &&
      nullValue_)
    {
      ex_expr::exp_return_type err = insertDesc(op_data, h, diagsArea);
      if (err == ex_expr::EXPR_ERROR)
	return err;
     
      char * handle = op_data[0];
      handleLen = getOperand(0)->getLength();
      err = insertData(handleLen, handle, op_data, h, diagsArea);
     
      return err;

    }
  else
    {
      lobHandle = op_data[2];

      handleLen = getOperand(2)->getLength(op_data[-MAX_OPERANDS+2]);
    }
     
  extractFromLOBhandle(&sFlags, &sLobType, &sLobNum, &sUid,
		       &sDescSyskey, &sDescTS, 
		       &sSchNameLen, sSchName,
		       lobHandle); //op_data[2]);

  // get the lob name where data need to be updated
  char tgtLobNameBuf[100];
  char * tgtLobName = ExpGetLOBname(sUid, sLobNum, tgtLobNameBuf, 100);

  if (tgtLobName == NULL)
    return ex_expr::EXPR_ERROR;

  char fromLobNameBuf[100];
  char * fromLobName = NULL;
  Int64 fromDescKey = 0;
  Int64 fromDescTS = 0;
  short fromSchNameLen = 0;
  char  fromSchName[500];
  if (0) // TBD. fromLob())
    {
      Lng32 fromLobType;
      Int64 fromLobUid;
      Lng32 fromLobNum;
      Int16 fromFlags;
      extractFromLOBhandle(&fromFlags, &fromLobType, &fromLobNum, &fromLobUid,
			   &fromDescKey, &fromDescTS, 
			   &fromSchNameLen, fromSchName,
			   op_data[1]);

      // get the lob name where data will be read from
      fromLobName = ExpGetLOBname(fromLobUid, fromLobNum, fromLobNameBuf, 100);
      if (fromLobName == NULL)
	return ex_expr::EXPR_ERROR;
    }

  LobsSubOper so = Lob_None;
  if (fromFile())
    so = Lob_File;
  else if (fromString())
    so = Lob_Memory;
  else if (fromLob())
    so = Lob_Foreign_Lob;
  else if (fromBuffer())
    so= Lob_Buffer;

  Lng32 waitedOp = 0;
#ifdef __EID
  waitedOp = 0; // nowaited op from EID/TSE process
#else
  waitedOp = 1;
#endif

  //temptemp. Remove after ExLobsOper adds nowaited support.
  waitedOp = 1;

  Lng32 cliError = 0;

  // call function with the lobname and source value
  // to update it in the LOB.
  // Get back offset and len of the LOB.
  //  Int64 offset = 0;
  Int64 lobLen = getOperand(1)->getLength();
  char * data = op_data[1];
  if (fromBuffer())
    {
      memcpy(&lobLen, op_data[3],sizeof(Int64)); // user specified buffer length
      memcpy(data,op_data[1],sizeof(Int64)); // user buffer address
    }
  if (isAppend())
    {
      rc = ExpLOBInterfaceUpdateAppend
	(getExeGlobals()->lobGlobal(), 
	 getLobHdfsServer(),
	 getLobHdfsPort(),
	 tgtLobName, 
	 lobStorageLocation(),
	 handleLen, lobHandle,
	 &outHandleLen_, outLobHandle_,
	 requestTag_,
	 getExeGlobals()->lobGlobals()->xnId(),
	 
	 (lobOperStatus == CHECK_STATUS_ ? 1 : 0),
	 waitedOp,
	 so,
	 sDescSyskey,
	 lobLen, 
	 data,
	 fromLobName, fromSchNameLen, fromSchName,
	 fromDescKey, fromDescTS,
	 getLobMaxSize(), getLobMaxChunkMemSize(),getLobGCLimit());
    }
  else
    {
      rc = ExpLOBInterfaceUpdate
	(getExeGlobals()->lobGlobal(), 
	 getLobHdfsServer(),
	 getLobHdfsPort(),
	 tgtLobName, 
	 lobStorageLocation(),
	 handleLen, lobHandle,
	 &outHandleLen_, outLobHandle_,
	 requestTag_,
	 getExeGlobals()->lobGlobals()->xnId(),
	 
	 (lobOperStatus == CHECK_STATUS_ ? 1 : 0),
	 waitedOp,
	 so,
	 sDescSyskey,
	 lobLen, 
	 data,
	 fromLobName, fromSchNameLen, fromSchName,
	 fromDescKey, fromDescTS,
	 getLobMaxSize(), getLobMaxChunkMemSize(),getLobGCLimit());
    }

  if (rc < 0)
    {
      Lng32 intParam1 = -rc;
      ExRaiseSqlError(h, diagsArea, 
		      (ExeErrorCode)(8442), NULL, &intParam1, 
		      &cliError, NULL, (char*)"ExpLOBInterfaceUpdate",
		      getLobErrStr(intParam1));
      return ex_expr::EXPR_ERROR;
    }

  // update lob handle with the returned values
  str_cpy_all(result, lobHandle, handleLen);
  //     str_cpy_all(result, op_data[2], handleLen);
  //     ExpLOBoper::updLOBhandle(sDescSyskey, 0, result); 
  getOperand(0)->setVarLength(handleLen, op_data[-MAX_OPERANDS]);

  return ex_expr::EXPR_OK;
}
예제 #5
0
ex_expr::exp_return_type ExpLOBdelete::eval(char *op_data[],
					    CollHeap*h,
					    ComDiagsArea** diagsArea)
{
  Lng32 rc = 0;

  Lng32 lobOperStatus = checkLobOperStatus();
  if (lobOperStatus == DO_NOTHING_)
    return ex_expr::EXPR_OK;

  char * result = op_data[0];

  Lng32 lobType;
  Int64 uid;
  Lng32 lobNum;
  Int64 descSyskey;
  Int64 descTS = -1;
  extractFromLOBhandle(NULL, &lobType, &lobNum, &uid,
		       &descSyskey, NULL, //descTS, 
		       NULL, NULL,
		       op_data[1]);
  
  Lng32 handleLen = getOperand(1)->getLength(op_data[-MAX_OPERANDS+1]);

  // get the lob name where data need to be deleted
  char lobNameBuf[100];
  char * lobName = ExpGetLOBname(uid, lobNum, lobNameBuf, 100);
  if (lobName == NULL)
    return ex_expr::EXPR_ERROR;

  Lng32 waitedOp = 0;
#ifdef __EID
  waitedOp = 0; // nowaited op from EID/TSE process
#else
  waitedOp = 1;
#endif

  //temptemp. Remove after ExLobsOper adds nowaited support.
  waitedOp = 1;

  Lng32 cliError = 0;

  // call function with the lobname and offset to delete it.
  rc = ExpLOBInterfaceDelete
    (getExeGlobals()->lobGlobal(),
     getLobHdfsServer(),
     getLobHdfsPort(),
     lobName, 
     lobStorageLocation(),
     handleLen, op_data[1],
     requestTag_,
     getExeGlobals()->lobGlobals()->xnId(),
     descSyskey,
     //     (getExeGlobals()->lobGlobals()->getCurrLobOperInProgress() ? 1 : 0),
     (lobOperStatus == CHECK_STATUS_ ? 1 : 0),
     waitedOp);
  
  if (rc == LOB_ACCESS_PREEMPT)
    {
      return ex_expr::EXPR_PREEMPT;
    }

  if (rc < 0)
    {
      Lng32 intParam1 = -rc;
      ExRaiseSqlError(h, diagsArea, 
		      (ExeErrorCode)(8442), NULL, &intParam1, 
		      &cliError, NULL, (char*)"ExpLOBInterfaceDelete",
		      getLobErrStr(intParam1));
      return ex_expr::EXPR_ERROR;
    }

  return ex_expr::EXPR_OK;
}
예제 #6
0
//////////////////////////////////////////////////////
// work() for ExExeUtilHiveTruncateLegacyTcb
//////////////////////////////////////////////////////
short ExExeUtilHiveTruncateLegacyTcb::work()
{
  short rc = 0;
  Lng32 cliRC = 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);

  while (1)
  {
    switch (step_)
    {
      case INITIAL_:
      {
         step_ = EMPTY_DIRECTORY_;
      }
      break;
      case EMPTY_DIRECTORY_:
      {
        cliRC = ExpLOBinterfaceEmptyDirectory(
             lobGlob_,
             (char*)"",                  //name is empty
             (htTdb().getPartnLocation() ? 
              htTdb().getPartnLocation() : 
              htTdb().getTableLocation()),
             Lob_HDFS_File,
             htTdb().getHdfsHost(),
             htTdb().getHdfsPort(),
             0 ,
             1 ,
             0);
        if (cliRC != 0)
        {
          Lng32 cliError = 0;
          
          Lng32 intParam1 = -cliRC;
          ExRaiseSqlError(getHeap(), &diagsArea_, 
                          (ExeErrorCode)(EXE_ERROR_FROM_LOB_INTERFACE),
                          NULL, &intParam1, 
                          &cliError, 
                          NULL, 
                          "HDFS",
                          (char*)"ExpLOBInterfaceEmptyDirectory",
                          getLobErrStr(intParam1));

          char reason[200];
          
          strcpy(reason, " ");
          if (intParam1 == LOB_DIR_NAME_ERROR)
            {
              if (htTdb().getPartnLocation())
                strcpy(reason, "Reason: specified partition does not exist");
              else
                strcpy(reason, "Reason: specified table location does not exist");
            }
          else if (intParam1 == LOB_DATA_FILE_DELETE_ERROR)
            {
              strcpy(reason, "Reason: error occurred during deletion of one or more files at the specified location");
            }
          
          ExRaiseSqlError(getHeap(), &diagsArea_, 
                          (ExeErrorCode)(EXE_HIVE_TRUNCATE_ERROR), NULL,
                          NULL, NULL, NULL,
                          reason,
                          NULL, NULL);
          step_ = ERROR_;
        }
        else
        {
          step_= DONE_;
        }
      }
      break;

      case ERROR_:
      {
        if (handleError())
           return WORK_OK;
        step_ = DONE_;
      }
      break;

      case DONE_:
      {
        if (handleDone())
           return WORK_OK;
        step_ = INITIAL_;

        return WORK_OK;
      }
      break;

    } // switch
  } // while

}
ExWorkProcRetcode ExHdfsFastExtractTcb::work()
{
#ifdef __EID 
  // This class should not be instantiated in EID.
  return WORK_BAD_ERROR;
#else
  Lng32 retcode = 0;
  SFW_RetCode sfwRetCode = SFW_OK;
  ULng32 recSepLen = strlen(myTdb().getRecordSeparator());
  ULng32 delimLen = strlen(myTdb().getDelimiter());
  ULng32 nullLen = 
    (myTdb().getNullString() ? strlen(myTdb().getNullString()) : 0);
  if (myTdb().getIsHiveInsert())
  {
    recSepLen = 1;
    delimLen = 1;
  }
  if (getEmptyNullString()) //covers hive null case also
    nullLen = 0;

  ExOperStats *stats = NULL;
  ExFastExtractStats *feStats = getFastExtractStats();

  while (TRUE)
  {
    // if no parent request, return
    if (qParent_.down->isEmpty())
      return WORK_OK;

    ex_queue_entry *pentry_down = qParent_.down->getHeadEntry();
    const ex_queue::down_request request = pentry_down->downState.request;
    const Lng32 value = pentry_down->downState.requestValue;
    ExFastExtractPrivateState &pstate = *((ExFastExtractPrivateState *) pentry_down->pstate);
    switch (pstate.step_)
    {
    case EXTRACT_NOT_STARTED:
    {
      pstate.step_= EXTRACT_CHECK_MOD_TS;
    }
    break;

    case EXTRACT_CHECK_MOD_TS:
    {
      if ((! myTdb().getTargetFile()) ||
          (myTdb().getModTSforDir() == -1))
        {
          pstate.step_ = EXTRACT_INITIALIZE;
          break;
        }

      numBuffers_ = 0;

      memset (hdfsHost_, '\0', sizeof(hdfsHost_));
      strncpy(hdfsHost_, myTdb().getHdfsHostName(), sizeof(hdfsHost_));
      hdfsPort_ = myTdb().getHdfsPortNum();
      memset (fileName_, '\0', sizeof(fileName_));
      memset (targetLocation_, '\0', sizeof(targetLocation_));
      snprintf(targetLocation_,999, "%s", myTdb().getTargetName());

      retcode = lobInterfaceDataModCheck();
      if (retcode < 0)
      {
        Lng32 cliError = 0;
        
        Lng32 intParam1 = -retcode;
        ComDiagsArea * diagsArea = NULL;
        ExRaiseSqlError(getHeap(), &diagsArea, 
                        (ExeErrorCode)(EXE_ERROR_FROM_LOB_INTERFACE),
                        NULL, &intParam1, 
                        &cliError, 
                        NULL, 
                        "HDFS",
                        (char*)"ExpLOBInterfaceDataModCheck",
                        getLobErrStr(intParam1));
        pentry_down->setDiagsArea(diagsArea);
        pstate.step_ = EXTRACT_ERROR;
        break;
      }
      
      if (retcode == 1) // check failed
      {
        ComDiagsArea * diagsArea = NULL;
        ExRaiseSqlError(getHeap(), &diagsArea, 
                        (ExeErrorCode)(EXE_HIVE_DATA_MOD_CHECK_ERROR));
        pentry_down->setDiagsArea(diagsArea);
        pstate.step_ = EXTRACT_ERROR;
        break;
      }
      
      pstate.step_= EXTRACT_INITIALIZE;
    }
    break;
    
    case EXTRACT_INITIALIZE:
    {
      pstate.processingStarted_ = FALSE;
      errorOccurred_ = FALSE;

      //Allocate writeBuffers.
      numBuffers_ = 1;
      for (Int16 i = 0; i < numBuffers_; i++)
      {
        bool done = false;
        Int64 input_datalen = myTdb().getHdfsIoBufferSize();
        char * buf_addr = 0;
        while ((!done) && input_datalen >= 32 * 1024)
        {
          buf_addr = 0;
          buf_addr = (char *)((NAHeap *)heap_)->allocateAlignedHeapMemory((UInt32)input_datalen, 512, FALSE);
          if (buf_addr)
          {
            done = true;
            bufferPool_[i] = new (heap_) IOBuffer((char*) buf_addr, (Int32)input_datalen);
          }
          else
          {
            bufferAllocFailuresCount_++;
            input_datalen = input_datalen / 2;
          }
        }
        if (!done)
        {
          numBuffers_ = i;
          break ; // if too few buffers have been allocated we will raise
        }         // an error later
      }

      if (feStats)
      {
        feStats->setBufferAllocFailuresCount(bufferAllocFailuresCount_);
        feStats->setBuffersCount(numBuffers_);
      }


      ComDiagsArea *da = NULL;

      if (!myTdb().getSkipWritingToFiles())
        if (myTdb().getTargetFile() )
        {
          Lng32 fileNum = getGlobals()->castToExExeStmtGlobals()->getMyInstanceNumber();
          memset (hdfsHost_, '\0', sizeof(hdfsHost_));
          strncpy(hdfsHost_, myTdb().getHdfsHostName(), sizeof(hdfsHost_));
          hdfsPort_ = myTdb().getHdfsPortNum();
          memset (fileName_, '\0', sizeof(fileName_));
          memset (targetLocation_, '\0', sizeof(targetLocation_));

          time_t t;
          time(&t);
          char pt[30];
          struct tm * curgmtime = gmtime(&t);
          strftime(pt, 30, "%Y%m%d%H%M%S", curgmtime);
          srand(getpid());
          snprintf(targetLocation_,999, "%s", myTdb().getTargetName());

          if (myTdb().getIsHiveInsert())
            snprintf(fileName_,999, "%s%d-%s-%d", myTdb().getHiveTableName(), fileNum, pt,rand() % 1000);
          else
            snprintf(fileName_,999, "%s%d-%s-%d", "file", fileNum, pt,rand() % 1000);

          if ((isSequenceFile() || myTdb().getBypassLibhdfs()) &&
              !sequenceFileWriter_)
          {
            sequenceFileWriter_ = new(getHeap())
                                     SequenceFileWriter((NAHeap *)getHeap());
            sfwRetCode = sequenceFileWriter_->init();
            if (sfwRetCode != SFW_OK)
            {
              createSequenceFileError(sfwRetCode);
              pstate.step_ = EXTRACT_ERROR;
              break;
            }
          }

          if (isSequenceFile()  ||  myTdb().getBypassLibhdfs())
          {
            strcat(targetLocation_, "//");
            strcat(targetLocation_, fileName_);
            if (isSequenceFile())
              sfwRetCode = sequenceFileWriter_->open(targetLocation_, SFW_COMP_NONE);
            else
              sfwRetCode = sequenceFileWriter_->hdfsCreate(targetLocation_, isHdfsCompressed());
            if (sfwRetCode != SFW_OK)
            {
              createSequenceFileError(sfwRetCode);
              pstate.step_ = EXTRACT_ERROR;
              break;
            }
          }
          else
          {
            retcode = 0;
            retcode = lobInterfaceCreate();
            if (retcode < 0)
            {
              Lng32 cliError = 0;

              Lng32 intParam1 = -retcode;
              ComDiagsArea * diagsArea = NULL;
              ExRaiseSqlError(getHeap(), &diagsArea,
                  (ExeErrorCode)(8442), NULL, &intParam1,
                  &cliError, NULL, (char*)"ExpLOBinterfaceCreate",
                  getLobErrStr(intParam1));
              pentry_down->setDiagsArea(diagsArea);
              pstate.step_ = EXTRACT_ERROR;
              break;
            }
          }
            
          if (feStats)
          {
            feStats->setPartitionNumber(fileNum);
          }
        }
        else
        {
          updateWorkATPDiagsArea(__FILE__,__LINE__,"sockets are not supported");
          pstate.step_ = EXTRACT_ERROR;
          break;
        }

      for (UInt32 i = 0; i < myTdb().getChildTuple()->numAttrs(); i++)
      {
        Attributes * attr = myTdb().getChildTableAttr(i);
        Attributes * attr2 = myTdb().getChildTableAttr2(i);

        ex_conv_clause tempClause;
        int convIndex = 0;
        sourceFieldsConvIndex_[i] =
            tempClause.find_case_index(
                attr->getDatatype(),
                0,
                attr2->getDatatype(),
                0,
                0);

      }

      pstate.step_= EXTRACT_PASS_REQUEST_TO_CHILD;
    }
    break;

    case EXTRACT_PASS_REQUEST_TO_CHILD:
    {
      // pass the parent request to the child downqueue
      if (!qChild_.down->isFull())
      {
        ex_queue_entry * centry = qChild_.down->getTailEntry();

        if (request == ex_queue::GET_N)
          centry->downState.request = ex_queue::GET_ALL;
        else
          centry->downState.request = request;

        centry->downState.requestValue = pentry_down->downState.requestValue;
        centry->downState.parentIndex = qParent_.down->getHeadIndex();
        // set the child's input atp
        centry->passAtp(pentry_down->getAtp());
        qChild_.down->insert();
        pstate.processingStarted_ = TRUE;
      }
      else
        // couldn't pass request to child, return
        return WORK_OK;

      pstate.step_ = EXTRACT_RETURN_ROWS_FROM_CHILD;
    }
    break;
    case EXTRACT_RETURN_ROWS_FROM_CHILD:
    {
      if ((qChild_.up->isEmpty()))
      {
        return WORK_OK;
      }

      if (currBuffer_ == NULL)
      {
        currBuffer_ = bufferPool_[0];
        memset(currBuffer_->data_, '\0',currBuffer_->bufSize_);
        currBuffer_->bytesLeft_ = currBuffer_->bufSize_;
      }

      ex_queue_entry * centry = qChild_.up->getHeadEntry();
      ComDiagsArea *cda = NULL;
      ex_queue::up_status child_status = centry->upState.status;

      switch (child_status)
      {
      case ex_queue::Q_OK_MMORE:
      {
        // for the very first row retruned from child
        // include the header row if necessary
        if ((pstate.matchCount_ == 0) && myTdb().getIncludeHeader())
        {
          if (!myTdb().getIsAppend())
          {
            Int32 headerLength = strlen(myTdb().getHeader());
            char * target = currBuffer_->data_;
            if (headerLength + 1 < currBuffer_->bufSize_)
            {
              strncpy(target, myTdb().getHeader(),headerLength);
              target[headerLength] = '\n' ;
              currBuffer_->bytesLeft_ -= headerLength+1 ;
            }
            else
            {
              updateWorkATPDiagsArea(__FILE__,__LINE__,"header does not fit in buffer");
              pstate.step_ = EXTRACT_ERROR;
              break;
            }
          }
        }

        tupp_descriptor *dataDesc = childOutputTD_;
        ex_expr::exp_return_type expStatus = ex_expr::EXPR_OK;
        if (myTdb().getChildDataExpr())
        {
          UInt32 childTuppIndex = myTdb().childDataTuppIndex_;

          workAtp_->getTupp(childTuppIndex) = dataDesc;

          // Evaluate the child data expression. If diags are generated they
          // will be left in the down entry ATP.
          expStatus = myTdb().getChildDataExpr()->eval(centry->getAtp(), workAtp_);
          workAtp_->getTupp(childTuppIndex).release();

          if (expStatus == ex_expr::EXPR_ERROR)
          {
            updateWorkATPDiagsArea(centry);
            pstate.step_ = EXTRACT_ERROR;
            break;
          }
        } // if (myTdb().getChildDataExpr())
        ///////////////////////
        char * targetData = currBuffer_->data_ + currBuffer_->bufSize_ - currBuffer_->bytesLeft_;
        if (targetData == NULL)
        {
          updateWorkATPDiagsArea(__FILE__,__LINE__,"targetData is NULL");
          pstate.step_ = EXTRACT_ERROR;
          break;
        }
        NABoolean convError = FALSE;
        convertSQRowToString(nullLen, recSepLen, delimLen, dataDesc,
            targetData, convError);
        ///////////////////////////////
        pstate.matchCount_++;
        if (!convError)
        {
          if (feStats)
          {
            feStats->incProcessedRowsCount();
          }
          pstate.successRowCount_ ++;
        }
        else
        {
          if (feStats)
          {
            feStats->incErrorRowsCount();
          }
          pstate.errorRowCount_ ++;
        }
        if (currBuffer_->bytesLeft_ < (Int32) maxExtractRowLength_)
        {
          pstate.step_ = EXTRACT_DATA_READY_TO_SEND;
        }
      }
      break;

      case ex_queue::Q_NO_DATA:
      {
        pstate.step_ = EXTRACT_DATA_READY_TO_SEND;
        endOfData_ = TRUE;
        pstate.processingStarted_ = FALSE ; // so that cancel does not
        //wait for this Q_NO_DATA
      }
      break;
      case ex_queue::Q_SQLERROR:
      {
        pstate.step_ = EXTRACT_ERROR;
      }
      break;
      case ex_queue::Q_INVALID:
      {
        updateWorkATPDiagsArea(__FILE__,__LINE__,
            "ExFastExtractTcb::work() Invalid state returned by child");
        pstate.step_ = EXTRACT_ERROR;
      }
      break;

      } // switch
      qChild_.up->removeHead();
    }
    break;

    case EXTRACT_DATA_READY_TO_SEND:
    {
      ssize_t bytesToWrite = currBuffer_->bufSize_ - currBuffer_->bytesLeft_;

      if (!myTdb().getSkipWritingToFiles())
        if (isSequenceFile())
        {
          sfwRetCode = sequenceFileWriter_->writeBuffer(currBuffer_->data_, bytesToWrite, myTdb().getRecordSeparator());
          if (sfwRetCode != SFW_OK)
          {
            createSequenceFileError(sfwRetCode);
            pstate.step_ = EXTRACT_ERROR;
            break;
          }
        }
        else  if (myTdb().getBypassLibhdfs())
        {
          sfwRetCode = sequenceFileWriter_->hdfsWrite(currBuffer_->data_, bytesToWrite);
          if (sfwRetCode != SFW_OK)
          {
            createSequenceFileError(sfwRetCode);
            pstate.step_ = EXTRACT_ERROR;
            break;
          }
        }
        else
        {
          retcode = 0;
          retcode = lobInterfaceInsert(bytesToWrite);
          if (retcode < 0)
          {
            Lng32 cliError = 0;

            Lng32 intParam1 = -retcode;
            ComDiagsArea * diagsArea = NULL;
            ExRaiseSqlError(getHeap(), &diagsArea,
                (ExeErrorCode)(8442), NULL, &intParam1,
                &cliError, NULL, (char*)"ExpLOBInterfaceInsert",
                getLobErrStr(intParam1));
            pentry_down->setDiagsArea(diagsArea);
            pstate.step_ = EXTRACT_ERROR;
            break;
          }
        }
      if (feStats)
      {
        feStats->incReadyToSendBuffersCount();
        feStats->incReadyToSendBytes(currBuffer_->bufSize_ - currBuffer_->bytesLeft_);
      }
      currBuffer_ = NULL;

      if (endOfData_)
      {
        pstate.step_ = EXTRACT_DONE;
      }
      else
      {
        pstate.step_ = EXTRACT_RETURN_ROWS_FROM_CHILD;
      }
    }
    break;

    case EXTRACT_ERROR:
    {
      // If there is no room in the parent queue for the reply,
      // try again later.
      //Later we may split this state into 2 one for cancel and one for query
      if (qParent_.up->isFull())
        return WORK_OK;
      // Cancel the child request - there must be a child request in
      // progress to get to the ERROR state.
      if (pstate.processingStarted_)
      {
        qChild_.down->cancelRequestWithParentIndex(qParent_.down->getHeadIndex());
        //pstate.processingStarted_ = FALSE;
      }
      while (pstate.processingStarted_ && pstate.step_ == EXTRACT_ERROR)
      {
        if (qChild_.up->isEmpty())
          return WORK_OK;
        ex_queue_entry * childEntry = qChild_.up->getHeadEntry();
        ex_queue::up_status childStatus = childEntry->upState.status;

        if (childStatus == ex_queue::Q_NO_DATA)
        {
          pstate.step_ = EXTRACT_DONE;
          pstate.processingStarted_ = FALSE;
        }
        qChild_.up->removeHead();
      }
      ex_queue_entry *pentry_up = qParent_.up->getTailEntry();
      pentry_up->copyAtp(pentry_down);
      // Construct and return the error row.
      //
      if (workAtp_->getDiagsArea())
      {
        ComDiagsArea *diagsArea = pentry_up->getDiagsArea();
        if (diagsArea == NULL)
        {
          diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap());
          pentry_up->setDiagsArea(diagsArea);
        }
        pentry_up->getDiagsArea()->mergeAfter(*workAtp_->getDiagsArea());
        workAtp_->setDiagsArea(NULL);
      }
      pentry_up->upState.status = ex_queue::Q_SQLERROR;
      pentry_up->upState.parentIndex
      = pentry_down->downState.parentIndex;
      pentry_up->upState.downIndex = qParent_.down->getHeadIndex();
      pentry_up->upState.setMatchNo(pstate.matchCount_);
      qParent_.up->insert();
      //
      errorOccurred_ = TRUE;
      pstate.step_ = EXTRACT_DONE;
    }
    break;

    case EXTRACT_DONE:
    {
      // If there is no room in the parent queue for the reply,
      // try again later.
      //
      if (qParent_.up->isFull())
        return WORK_OK;

      if (!myTdb().getSkipWritingToFiles())
        if (isSequenceFile())
        {
          sfwRetCode = sequenceFileWriter_->close();
          if (!errorOccurred_ && sfwRetCode != SFW_OK )
          {
            createSequenceFileError(sfwRetCode);
            pstate.step_ = EXTRACT_ERROR;
            break;
          }
        }
        else  if (myTdb().getBypassLibhdfs())
        {
          if (sequenceFileWriter_)
            {
              sfwRetCode = sequenceFileWriter_->hdfsClose();
              if (!errorOccurred_ && sfwRetCode != SFW_OK )
                {
                  createSequenceFileError(sfwRetCode);
                  pstate.step_ = EXTRACT_ERROR;
                  break;
                }
            }
        }
        else
        {
          retcode = lobInterfaceClose();
          if (! errorOccurred_ && retcode < 0)
          {
            Lng32 cliError = 0;

            Lng32 intParam1 = -retcode;
            ComDiagsArea * diagsArea = NULL;
            ExRaiseSqlError(getHeap(), &diagsArea,
                (ExeErrorCode)(8442), NULL, &intParam1,
                &cliError, NULL,
                (char*)"ExpLOBinterfaceCloseFile",
                getLobErrStr(intParam1));
            pentry_down->setDiagsArea(diagsArea);

            pstate.step_ = EXTRACT_ERROR;
            break;
          }
        }
      //insertUpQueueEntry will insert Q_NO_DATA into the up queue and
      //remove the head of the down queue
      insertUpQueueEntry(ex_queue::Q_NO_DATA, NULL, TRUE);
      errorOccurred_ = FALSE;

      endOfData_ = FALSE;

      //we need to set the next state so that the query can get re-executed
      //and we start from the beginning again. Not sure if pstate will be
      //valid anymore because insertUpQueueEntry() might have cleared it
      //already.
      pstate.step_ = EXTRACT_NOT_STARTED;

      //exit out now and not break.
      return WORK_OK;
    }
    break;

    default:
    {
      ex_assert(FALSE, "Invalid state in  ExHdfsFastExtractTcb ");
    }

    break;

    } // switch(pstate.step_)
  } // while

  return WORK_OK;
#endif
}//ExHdfsFastExtractTcb::work()