DrError RChannelReader::GetTerminationStatus(DryadMetaDataRef* pErrorData) { DrError status; RChannelItemRef writerTermination; RChannelItemRef readerTermination; GetTerminationItems(&writerTermination, &readerTermination); LogAssert(readerTermination.Ptr() != NULL); if (writerTermination.Ptr() != NULL && writerTermination->GetType() != RChannelItem_EndOfStream) { status = writerTermination->GetErrorFromItem(); *pErrorData = writerTermination->GetMetaData(); } else if (readerTermination->GetType() == RChannelItem_EndOfStream) { status = DrError_EndOfStream; *pErrorData = readerTermination->GetMetaData(); } else { status = DryadError_ProcessingInterrupted; *pErrorData = readerTermination->GetMetaData(); } return status; }
void DryadSubGraphVertex::VertexInfo::DrainChannels() { if (m_virtual || m_vertexProgram == NULL) { return; } DrLogI( "Vertex draining channels. Vertex ID %u", m_id); UInt32 i; for (i=0; i<m_inputPortCount; ++i) { if (m_inputExternal[i]) { DrLogI( "Vertex not draining external input. Vertex ID %u port %u", m_id, i); } else if (m_inputChannel[i] != NULL) { m_inputChannel[i]->Drain(); DrLogI( "Vertex drained internal input. Vertex ID %u port %u", m_id, i); } } bool errorCondition = false; for (i=0; i<m_outputPortCount; ++i) { if (m_outputExternal[i]) { DrLogI( "Vertex not draining external output. Vertex ID %u port %u", m_id, i); } else if (m_outputChannel[i] != NULL) { RChannelItemRef writeTermination; m_outputChannel[i]->Drain(DrTimeInterval_Zero, &writeTermination); if (writeTermination != NULL) { if (writeTermination->GetType() != RChannelItem_EndOfStream) { DrLogI( "Vertex internal output write error. Vertex ID %u port %u type %u", m_id, i, writeTermination->GetType()); errorCondition = true; } } DrLogI( "Vertex drained internal output. Vertex ID %u port %u", m_id, i); } } if (errorCondition && m_vertexProgram->NoError()) { m_vertexProgram->ReportError(DryadError_ChannelWriteError); } }
// // Interrupt an input channel for provided reason // void RChannelReaderImpl::Interrupt(RChannelItem* interruptItemBase) { RChannelItemRef interruptItem = interruptItemBase; bool doInterrupt; bool startedSupplier = false; BOOL bRet; // // Enter a critical section and update state from "Running" to "Interrupting" // { AutoCriticalSection acs(&m_baseDR); if (m_state == RS_Running) { doInterrupt = true; bRet = ::ResetEvent(m_interruptEvent); LogAssert(bRet != 0); m_state = RS_InterruptingSupplier; startedSupplier = m_startedSupplier; } else { doInterrupt = false; } } // // If already interrupting, wait for interrupt event to be handled // if (doInterrupt == false) { bRet = ::WaitForSingleObject(m_interruptEvent, INFINITE); LogAssert(bRet == WAIT_OBJECT_0); return; } ChannelProcessRequestList handlerDispatch; ChannelUnitList unitDispatch; DrBListEntry* listEntry; RChannelInterruptHandler* interruptHandler = NULL; if (startedSupplier) { // // startedSupplier just means that we (potentially in another // thread) have called or are about to call StartSupplier, // outside the lock. We'll wait here until it really gets // called before calling InterruptSupplier // bRet = ::WaitForSingleObject(m_startedSupplierEvent, INFINITE); LogAssert(bRet == WAIT_OBJECT_0); // // when this returns the buffer reader will not be generating // any new buffers and the parser will not be generating any // new items. // m_supplier->InterruptSupplier(); } { AutoCriticalSection acs(&m_baseDR); if (interruptItem == NULL) { if (m_writerTerminationItem == NULL) { interruptItem.Attach(RChannelMarkerItem:: Create(RChannelItem_Abort, false)); } else { RChannelItemType interruptType = m_writerTerminationItem->GetType(); interruptItem.Attach(RChannelMarkerItem:: Create(interruptType, false)); interruptItem->ReplaceMetaData(m_writerTerminationItem-> GetMetaData()); } } else { RChannelItemType interruptType = interruptItem->GetType(); LogAssert(RChannelItem::IsTerminationItem(interruptType)); } LogAssert(m_state == RS_InterruptingSupplier); /* sanity check that nobody accidentally started the supplier while we were getting here */ LogAssert(startedSupplier == m_startedSupplier); m_state = RS_Stopping; if (m_unitList.IsEmpty()) { /* gather up any handlers which haven't been given an item yet */ FillEmptyHandlers(&handlerDispatch); } else { LogAssert(m_handlerList.IsEmpty()); /* gather up any units which have been put on the queue but don't have a handler waiting */ bool gotTermination = (m_writerTerminationItem != NULL); while (m_unitList.IsEmpty() == false) { RChannelUnit* unit = m_unitList.CastOut(m_unitList.GetHead()); if (unit->GetType() == RChannelUnit_Item) { /* sanity check that the item sequence is correct */ RChannelItemUnit* itemUnit = (RChannelItemUnit *) unit; RChannelItemArray* itemArray = itemUnit->GetItemArray(); UInt32 nItems = itemArray->GetNumberOfItems(); LogAssert(nItems > 0); RChannelItemRef* a = itemArray->GetItemArray(); UInt32 i; for (i=0; i<nItems; ++i) { RChannelItem* item = a[i]; RChannelItemType itemType = item->GetType(); LogAssert(gotTermination == false); if (RChannelItem::IsTerminationItem(itemType)) { gotTermination = true; } } itemUnit->DiscardItems(); } unitDispatch.TransitionToTail(unitDispatch.CastIn(unit)); } } /* prepare to trigger any interrupt handler the application sent in earlier */ if (m_interruptHandler != NULL) { interruptHandler = m_interruptHandler; m_interruptHandler = NULL; } m_unitLatch.AcceptList(&unitDispatch); } /* these are handlers which had been submitted but not assigned an item */ listEntry = handlerDispatch.GetHead(); while (listEntry != NULL) { RChannelProcessRequest* request = handlerDispatch.CastOut(listEntry); listEntry = handlerDispatch.GetNext(listEntry); handlerDispatch.Remove(handlerDispatch.CastIn(request)); /* call the process event (which calls back into RChannelReaderImpl::ProcessUnit) instead of just calling the handler in case there is a thread blocked on a cancellation which needs to be woken up. */ request->Process(); delete request; } ReturnUnits(&unitDispatch); if (startedSupplier) { /* assuming we ever started it, wait for the buffer reader to process all its returned buffers and tell us whether we can restart or not */ m_supplier->DrainSupplier(interruptItem); } if (interruptHandler != NULL) { interruptHandler->ProcessInterrupt(interruptItem); } { AutoCriticalSection acs(&m_baseDR); /* sanity check that nobody accidentally started the supplier while we were getting here */ LogAssert(startedSupplier == m_startedSupplier); LogAssert(m_unitList.IsEmpty()); LogAssert(m_handlerList.IsEmpty()); LogAssert(m_interruptHandler == NULL); LogAssert(m_readerTerminationItem == NULL); m_readerTerminationItem = interruptItem; m_startedSupplier = false; } bRet = ::SetEvent(m_interruptEvent); LogAssert(bRet != 0); }