/////////////////////////////////////////////////////////////////////
//
// Contents:
//    
//   RelStoredProc::codeGen()
//
//////////////////////////////////////////////////////////////////////
short generateSPIOExpr(RelInternalSP * sp,
		       Generator * generator,
		       ExSPInputOutput * &inputExpr,
		       ExSPInputOutput * &outputExpr)
{
  ExpGenerator * expGen = generator->getExpGenerator();
  Space * genSpace = generator->getSpace();

  // Generate input(extract) expr
  FragmentDir * compFragDir = generator->getFragmentDir();

  // create the fragment (independent code space) for this expression
  CollIndex myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER);
  Space * space = generator->getSpace();

  // Start generation by creating the ExSPInputOutput class.
  //It will be initialized later.
  ExSPInputOutput * lInputExpr = new(space) ExSPInputOutput();

  ULng32 recordLen;
  ExpTupleDesc * tupleDesc = NULL;

  if (expGen->processValIdList(sp->procTypes(),
			       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
			       recordLen,
			       0, 1,
			       &tupleDesc, 
			       ExpTupleDesc::LONG_FORMAT) == -1)
    return -1;

  ConvInstruction * cia = 
    (ConvInstruction *)space->allocateMemory(sp->procTypes().entries() * 
					    sizeof(ConvInstruction));

  ULng32 totalLen = space->getAllocatedSpaceSize();
 
  lInputExpr->initialize(tupleDesc, totalLen, cia);

  ExSPInputOutputPtr(lInputExpr).pack(space);

  // the generated expr is generated in chunks internally by
  // the space class. Make it contiguous by allocating and
  // moving it to a contiguous area.
  char * expr = new(generator->wHeap()) char[totalLen];
  space->makeContiguous((char *)expr, totalLen);
  inputExpr =
    (ExSPInputOutput *)(genSpace->allocateAndCopyToAlignedSpace((char *)expr, totalLen, 0));

  compFragDir->removeFragment();

  // Delete expr
  NADELETEBASIC(expr, generator->wHeap());
  expr = NULL;

  // Now generate the move to output row expr
  myFragmentId = compFragDir->pushFragment(FragmentDir::MASTER);
  space = generator->getSpace();

  ExSPInputOutput * lOutputExpr = new(space) ExSPInputOutput();

  if (expGen->processValIdList(sp->getTableDesc()->getColumnList(),
			       ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
			       recordLen,
			       0, 1,
			       &tupleDesc, 
			       ExpTupleDesc::LONG_FORMAT) == -1)
    return -1;

  cia = 
    (ConvInstruction *)space->allocateMemory(sp->getTableDesc()->getColumnList().entries() * 
					    sizeof(ConvInstruction));

  for (short i = 0; i < (short) tupleDesc->numAttrs(); i++)
    {
      ex_conv_clause tempClause;

      cia[i] = tempClause.findInstruction(REC_BYTE_V_ASCII, 
					  -1, // no op 
					  tupleDesc->getAttr(i)->getDatatype(), 
					  tupleDesc->getAttr(i)->getLength(),
					  0);
      
    }

  totalLen = space->getAllocatedSpaceSize();
 
  lOutputExpr->initialize(tupleDesc, totalLen, cia);

  ExSPInputOutputPtr(lOutputExpr).pack(space);

  expr = new(generator->wHeap()) char[totalLen];
  space->makeContiguous((char *)expr, totalLen);
  outputExpr =
    (ExSPInputOutput *)(genSpace->allocateAndCopyToAlignedSpace((char *)expr, totalLen, 0));

  compFragDir->removeFragment();

  // Delete expr
  NADELETEBASIC(expr, generator->wHeap());
  expr = NULL;
  
  return 0;
}
Esempio n. 2
0
queue_index ex_queue::resize(ex_tcb *    tcb,
			     queue_index newSize)
{
  queue_index          sizeDelta;
  Space                *space = tcb->getSpace();
  ex_queue_entry       *newQueue;
  queue_index          newMask;
  Int32                  queueWasFull = isFull();
  NABoolean            needAtps = needsAtps();
  Int32                  atpSize = 0;
  atp_struct           *atps = NULL;
  queue_index          numAllocatedAtps = 0;
  ex_tcb_private_state *pstates = NULL;
  Lng32                 numAllocatedPstates = 0;
  Lng32                 pstateLength = 0;
  queue_index          qi;
  queue_index          lastEntryToCopy;
  ex_queue_entry       *oldQueue = queue_;
  const queue_index    oldSize = size_;
  const queue_index    oldMask = mask_;
  
  // the new size must be a power of 2, round up to the next power of 2
  queue_index p2 = size_;
  while (p2 < newSize && p2 != 0)
    p2 = p2 << 1;
  // p2 is now a power of 2 that is >= newSize, except that
  // it is 0 in some unsupported cases, like size_ being 0 or newSize
  // being too large to be rounded up to a power of 2
  newSize = p2;

  // can't resize to a smaller size
  if (newSize <= size_)
    return size_;

  sizeDelta = newSize - size_;
  newMask   = newSize - 1;

  // try to allocate the needed memory first and give up if that's not
  // possible

  // allocate new array of ex_queue_entry structs
  newQueue = (ex_queue_entry *) (space->allocateMemory(
       newSize * sizeof(ex_queue_entry),FALSE));
  if (newQueue == NULL)
    return size_; // out of memory

  // allocate array of ATPs if needed
  if (needAtps)
    {
      atps = allocateAtpArray(criDesc_, sizeDelta, &atpSize, space, FALSE);

      // for now, give up if it wasn't possible to allocate the ATPs in
      // one piece (one could try to allocate them one by one)
      if (atps == NULL)
	return size_; 

      numAllocatedAtps = sizeDelta;
    }

  // allocate an array of pstate objects if needed
  if (needsPstates_)
    {
      numAllocatedPstates = sizeDelta;
      pstates = tcb->allocatePstates(numAllocatedPstates,pstateLength);
      if (pstates == NULL)
	{
	  // either the TCB doesn't support the allocatePstates()
	  // method yet (it would be a dumb thing for a TCB not to
	  // support this AND to call the resize method) or we don't
	  // have enough memory. Give up without changing the size.
	  return size_;
	}
    }

  // at this point we have allocated everything we need, so we
  // should be in good shape from now on

  // initialize the new queue
  for(qi = 0; qi < newSize; qi++)
    {
      // Initialize private state pointer
      newQueue[qi].pstate = NULL;
      
      // initialize the public state
      newQueue[qi].initializeState(upDown_);
      
      // Initialize the pointer to the atp_struct
      newQueue[qi].atp_ = NULL;
    }

  // calculate last entry to copy (the addition here may wrap around
  // such that <lastEntryToCopy> is actually smaller than <head_>)
  lastEntryToCopy = head_ + size_;

  // Copy all queue entries (whether they are in use or not) over to
  // the new queue. Do this in such a way that the used entries move
  // to the new queue entry that corresponds to their index. Note
  // that we will start copying the used entries (if any) first, and
  // that those are the first entries until (but not including) the
  // entry where qi is equal to <tail_>.
  for (qi = head_; qi != lastEntryToCopy; qi++)
    {
      newQueue[qi & newMask] = queue_[qi & mask_];
    }

  // At this point, <size_> elements of the new queue are initialized
  // with actual queue entries, while <sizeDelta> entries may still
  // need ATPs and/or pstates (if applicable). These sizeDelta entries
  // will be taken care of next by using the regular allocation methods
  // for new queues. Note that the ATPs and PSTATEs of the remaining
  // entries may or may not be contiguous.

  // reset counter that counts empty/full transitions
  resizePoints_ = 0;
  needsResize_ = FALSE;

  // set the data member to point to the newly allocated structures
  queue_ = newQueue;
  size_  = newSize;
  mask_  = newMask;

  NABoolean finalAllocSucceeded = TRUE;

  // initialize the uninitialized ATPs if required to do so
  if (needAtps)
    finalAllocSucceeded = allocateAtps(space,
				       atps,
				       numAllocatedAtps,
				       atpSize,
				       FALSE);

  // allocate PSTATEs for the uninitialized queue entries if this
  // queue needs PSTATEs
  if (needsPstates_ && finalAllocSucceeded)
    {
      finalAllocSucceeded = allocatePstate(tcb,
					   pstates,
					   numAllocatedPstates,
					   pstateLength,
					   FALSE);
    }

  if (finalAllocSucceeded)
    {
      // schedule the unblock subtask of the queue if the queue was full
      // before the resize and now is no longer full (a deadlock could
      // occur if we wouldn't schedule the unblock task for a full to
      // not full transition of a queue)
      if (queueWasFull)
	unblockSubtask_->schedule();
    }
  else
    {
      // We failed during allocation of ATPs or PStates. Undo the switch
      // to the new, resized queue and restore the queue to its old state.
      queue_ = oldQueue;
      size_  = oldSize;
      mask_  = oldMask;
    }

  return size_;
}