//
// Process a set status request
//
void XComputeSetStatusOverlapped::ProcessIO(DrError retval, UInt32 numBytes)
{
    //
    // If there was an error, log and fail
    //
    if (retval != DrError_OK)
    {
        DrLogA( "Completion port returned error. error %s %u bytes", DRERRORSTRING(retval), numBytes);
    }

    //
    // If there is no data, log and fail
    //
    if (numBytes != 0)
    {
        DrLogA( "Completion port returned non-zero. %u bytes", numBytes);
    }

    //
    // Handle other outcomes based on the operation state
    //
    m_request->Process(m_operationState);

    delete this;
}
//
// Handle response from xcompute
//
void DVertexXComputeSetStatus::Process(DrError err)
{
    //
    // If status successfully sent, log success and check on vertex status
    //
    if (err == DrError_OK)
    {
        DrLogI( "PN send succeeded. label %s", m_label.GetString());

        if (m_exitOnCompletion != DrExitCode_StillActive)
        {
            //
            // If vertex is not still active, report that it is exiting
            // this may kill this process if all verticies are complete
            //
            m_parentOuter->VertexExiting(m_exitOnCompletion);
        }

        return;
    }

    //
    // If there was a communication failure, retry up to 4 times
    //
    if (err == DrError_RemoteDisconnected ||
            err == DrError_LocalDisconnected ||
            err == DrError_ConnectionFailed)
    {
        if (m_sendCount < 4)
        {
            DrLogW( "Retrying PN send. error %s", DRERRORSTRING(err));

            m_parent->SendSetStatusRequest(this);

            return;
        }
    }

    //
    // If m_isAssert, just report warning, otherwise log and fail
    // todo: this seems backwards. I don't understand how m_isAssert is set.
    //
    if (m_isAssert)
    {
        DrLogW(
            "Send to PN failed: not asserting again. done %u sends, error %s",
            m_sendCount, DRERRORSTRING(err));
    }
    else
    {
        DrLogA(
            "Send to PN failed. done %u sends, error %s",
            m_sendCount, DRERRORSTRING(err));
    }
}
    bool DoInitialize()
    {  
        if (m_valid) {
            // We don't want perf counter files
            Counters::SetInitNoPerfFiles();
        }
        
        // Register ourselves as the singleton config manager
        if (!m_valid || !Configuration::PreInitialize(this)) {
            DrLogA( "DryadConfigurationManager",
                "Failed to preinitialize dryad configuration manager");
            m_valid = false;
        }

        if (m_valid) {
            if (!CommonInit(m_strIniFileName.GetString(), 0, -1 )) {
                DrLogA( "DryadConfigurationManager",
                    "Failed to initialize dryad configuration manager");
                m_valid = false;
            }
        }

        return m_valid;
    }
Exemple #4
0
unsigned __stdcall WorkQueue::ThreadFunc(void* arg)
{
    WorkQueue* self = (WorkQueue *) arg;

    LogAssert(self->m_completionPort != INVALID_HANDLE_VALUE);

    DrLogI("WorkQueue::ThreadFunc starting thread");

    bool finished = false;

    do
    {
        DWORD numBytes;
        ULONG_PTR completionKey;
        LPOVERLAPPED overlapped;

//         DrLogD(
//             "WorkQueue::ThreadFunc waiting for completion event");

        BOOL retval = ::GetQueuedCompletionStatus(self->m_completionPort,
                                                  &numBytes,
                                                  &completionKey,
                                                  &overlapped,
                                                  INFINITE);

//         DrLogD(
//             "WorkQueue::ThreadFunc received completion event",
//             "retval: %d", retval);

        if (retval != 0)
        {
            finished = (numBytes == DWORKQUEUE_EXIT);

            if (finished)
            {
                DrLogI("WorkQueue::ThreadFunc received shutdown event");
            }
        }
        else
        {
            DWORD errCode = GetLastError();
            DrLogA("WorkQueue::GetQueuedCompletionStatus. error code: 0x%08x", HRESULT_FROM_WIN32(errCode));
        }

        bool queueDrained = false;
        bool decrementedCount = false;
        do
        {
            WorkRequest* request = NULL;
            {
                AutoCriticalSection acs(&(self->m_baseCS));

                if (!decrementedCount)
                {
                    decrementedCount = true;
                    LogAssert(self->m_numQueuedWakeUps > 0);
                    --(self->m_numQueuedWakeUps);
//                     DrLogD(
//                         "WorkQueue::ThreadFunc decremented queued wakeups",
//                         "new val: %d", self->m_numQueuedWakeUps);
                }

                if (self->m_list.IsEmpty())
                {
                    queueDrained = true;
//                     DrLogD(
//                         "WorkQueue::ThreadFunc found empty work queue");
                }
                else
                {
                    request = self->m_list.CastOut(self->m_list.RemoveHead());
                    LogAssert(request != NULL);
//                     DrLogD(
//                         "WorkQueue::ThreadFunc removed work item to process");
                }
            }

            if (!queueDrained)
            {
                request->Process();
                delete request;
                request = NULL;
            }
        } while (!queueDrained);
    } while (!finished);

    DrLogI("WorkQueue::ThreadFunc exiting thread");

    return 0;
}
Exemple #5
0
//
// Put a work item in the queue
//
bool WorkQueue::EnQueue(WorkRequest* item)
{
    LogAssert(item != NULL);

    //
    // Enter a critical section to add work item to queue and notify any waiting worker threads
    //
    {
        AutoCriticalSection acs (&m_baseCS);

        if (m_state == WQS_Stopping)
        {
            //
            // If stopping, log rejection
            //
            DrLogI("WorkQueue::EnQueue rejecting stopping item");
            return false;
        }
        else
        {
            LogAssert(m_state == WQS_Running);
        }

        //
        // If item shouldn't be aborted, add it to list of work and make sure
        // worker threads are awake
        //
        if (!item->ShouldAbort())
        {
            m_list.InsertAsTail(m_list.CastIn(item));
            item = NULL;

            if (m_numQueuedWakeUps < m_numWorkerThreads)
            {
                //
                // If additional worker threads are availble, post queued work
                //
                ++m_numQueuedWakeUps;
                BOOL retval = ::PostQueuedCompletionStatus(m_completionPort,
                                                           DWORKQUEUE_CONTINUE,
                                                           NULL,
                                                           NULL);
                if (retval == 0)
                {
                    //
                    // Log any failure posting queued work item
                    //
                    DWORD errCode = GetLastError();
                    DrLogA("WorkQueue::EnQueue post completion status. error code:0x%08x", HRESULT_FROM_WIN32(errCode));
                }
            }
        }
    }

    //
    // If item is non-null, then ShouldAbort returned true above.
    // In this case, log, abort, and clean up
    //
    if (item != NULL)
    {
        DrLogD("WorkQueue::EnQueue processing aborting work item");

        item->Process();
        delete item;
    }

    return true;
}
Exemple #6
0
void WorkQueue::Stop()
{
    DrLogI("WorkQueue::Stop entered");

    {
        AutoCriticalSection acs(&m_baseCS);

        LogAssert(m_state == WQS_Running);

        m_state = WQS_Stopping;

        m_numQueuedWakeUps += m_numWorkerThreads;
    }

    DWORD i;
    for (i=0; i<m_numWorkerThreads; ++i)
    {
        BOOL retval = ::PostQueuedCompletionStatus(m_completionPort,
                                                   DWORKQUEUE_EXIT,
                                                   NULL,
                                                   NULL);
        if (retval == 0)
        {
            DWORD errCode = GetLastError();
            DrLogA("WorkQueue::Stop post completion status. error code: 0x%08x", HRESULT_FROM_WIN32(errCode));
        }
    }

    DrLogI("WorkQueue::Stop sent completion events");

    DWORD waitRet = ::WaitForMultipleObjects(m_numWorkerThreads,
                                             m_threadHandle,
                                             TRUE,
                                             INFINITE);
    LogAssert(/*waitRet >= WAIT_OBJECT_0 &&*/
              waitRet < (WAIT_OBJECT_0 + m_numWorkerThreads));

    DrLogI("WorkQueue::Stop all threads have terminated");

    {
        AutoCriticalSection acs(&m_baseCS);

        BOOL bRetval;

        LogAssert(m_numQueuedWakeUps == 0);
        LogAssert(m_list.IsEmpty());

        for (i=0; i<m_numWorkerThreads; ++i)
        {
            bRetval = ::CloseHandle(m_threadHandle[i]);
            if (bRetval == 0)
            {
                DWORD errCode = GetLastError();
                DrLogA("WorkQueue::Stop close thread handle. error code: 0x%08x", HRESULT_FROM_WIN32(errCode));
            }
            m_threadHandle[i] = INVALID_HANDLE_VALUE;
        }

        bRetval = ::CloseHandle(m_completionPort);
        if (bRetval == 0)
        {
            DWORD errCode = GetLastError();
            DrLogA("WorkQueue::Stop close completion port handle. error code: 0x%08x", HRESULT_FROM_WIN32(errCode));
        }

        m_completionPort = INVALID_HANDLE_VALUE;
        m_state = WQS_Stopped;
    }

    DrLogI("WorkQueue::Stop exiting");
}
//
// Send updated status to vertex service
//
void DVertexXComputePnController::
SendSetStatusRequest(DryadPnProcessPropertyRequest* r)
{
    //
    // Cast request to required type and make sure it's valid
    //
    DVertexXComputeSetStatus* request =
        dynamic_cast<DVertexXComputeSetStatus*>(r);
    LogAssert(request != NULL);

    //
    // Wrap request in XComputeSetStatusOverlapped
    //
    XComputeSetStatusOverlapped* overlapped =
        new XComputeSetStatusOverlapped(request);

    //
    // Create asynchronous execution information
    //
    XC_ASYNC_INFO asyncInfo;
    memset(&asyncInfo, 0, sizeof(asyncInfo));
    asyncInfo.cbSize = sizeof(asyncInfo);
    asyncInfo.pOperationState = overlapped->GetOperationState();
    asyncInfo.IOCP = g_dryadNativePort->GetCompletionPort();
    asyncInfo.pOverlapped = overlapped->GetOverlapped();

    //
    // Update request counters
    //
    request->IncrementSendCount();
    g_dryadNativePort->IncrementOutstandingRequests();

    //
    // Update process info
    //
    XCERROR err =
        XcSetAndGetProcessInfo(NULL,//GetProcessHandle(),
                               request->MarshalProperty(),
                               request->GetResults(),
                               &asyncInfo);

    LogAssert(err != DrError_OK);

    if (err != HRESULT_FROM_WIN32(ERROR_IO_PENDING))
    {
        //
        // If failed (other than due to pending IO) log failure and update request counter
        //
        g_dryadNativePort->DecrementOutstandingRequests();

        //
        // If request assertion true, report errors as warnings, otherwise report as error and fail
        // todo: this still seems backwards - need to figure out rational
        // request handles retries itself
        //
        if (request->IsAssert())
        {
            DrLogW(
                "Status request send failed synchronously during assert: not asserting again. done %u send tries, error %s",
                request->GetSendCount(), DRERRORSTRING(err));
        }
        else
        {
            DrLogA(
                "Status request send failed synchronously. done %u send tries, error %s",
                request->GetSendCount(), DRERRORSTRING(err));
        }

        delete overlapped;
    }
}