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