// CheckWaitingJobs //------------------------------------------------------------------------------ void Server::CheckWaitingJobs( const ToolManifest * manifest ) { // queue for start any jobs that may now be ready #ifdef ASSERTS_ENABLED bool atLeastOneJobStarted = false; #endif MutexHolder mhC( m_ClientListMutex ); const ClientState * const * end = m_ClientList.End(); for ( ClientState ** it = m_ClientList.Begin(); it!=end; ++it ) { // For each connected client... ClientState * cs = *it; MutexHolder mh2( cs->m_Mutex ); // .. check all jobs waiting for ToolManifests int32_t numJobs = (int32_t)cs->m_WaitingJobs.GetSize(); for ( int32_t i=( numJobs -1 ); i >= 0; --i ) { Job * job = cs->m_WaitingJobs[ i ]; ToolManifest * manifestForThisJob = job->GetToolManifest(); ASSERT( manifestForThisJob ); if ( manifestForThisJob == manifest ) { cs->m_WaitingJobs.EraseIndex( i ); JobQueueRemote::Get().QueueJob( job ); PROTOCOL_DEBUG( "Server: Job %x can now be started\n", job ); #ifdef ASSERTS_ENABLED atLeastOneJobStarted = true; #endif } } } // We should only have called this function when a ToolChain sync was complete // so at least 1 job should have been waiting for it ASSERT( atLeastOneJobStarted ); }
//------------------------------------------------------------------------------ /*virtual*/ void Server::OnDisconnected( const ConnectionInfo * connection ) { ASSERT( connection ); ClientState * cs = (ClientState *)connection->GetUserData(); ASSERT( cs ); // Unhook any jobs which are queued or in progress for this client // - deletes the queued jobs // - unhooks the UserData for in-progress jobs so the result is discarded on completion JobQueueRemote & jqr = JobQueueRemote::Get(); jqr.CancelJobsWithUserData( cs ); // check if any tool chain was being sync'd from this Client Array< ToolManifest * > cancelledManifests( 0, true ); { MutexHolder manifestMH( m_ToolManifestsMutex ); const ToolManifest * const * end = m_Tools.End(); ToolManifest ** it = m_Tools.Begin(); while ( it != end ) { // if synchronizing from connection that was just disconnected... ToolManifest * tm = *it; if ( ( tm->IsSynchronized() == false ) && ( tm->GetUserData() == connection ) ) { // ...flag any expected files as not synching tm->CancelSynchronizingFiles(); tm->SetUserData( nullptr ); cancelledManifests.Append( tm ); } ++it; } } // free the serverstate structure MutexHolder mh( m_ClientListMutex ); ClientState ** iter = m_ClientList.Find( cs ); ASSERT( iter ); m_ClientList.Erase( iter ); // because we cancelled manifest syncrhonization, we need to check if other // connections are waiting for the same manifest { ClientState ** it = m_ClientList.Begin(); const ClientState * const * end = m_ClientList.End(); for ( ; it != end; ++it ) { ClientState * otherCS = *it; MutexHolder mh2( otherCS->m_Mutex ); const Job * const * jEnd = otherCS->m_WaitingJobs.End(); for ( Job ** jIt = otherCS->m_WaitingJobs.Begin(); jIt != jEnd; ++jIt ) { Job * j = *jIt; ToolManifest * jMan = j->GetToolManifest(); if ( cancelledManifests.Find( jMan ) ) { RequestMissingFiles( otherCS->m_Connection, jMan ); } } } } // This is usually null here, but might need to be freed if // we had the connection drop between message and payload FREE( (void *)( cs->m_CurrentMessage ) ); // delete any jobs where we were waiting on Tool synchronization const Job * const * end = cs->m_WaitingJobs.End(); for ( Job ** it=cs->m_WaitingJobs.Begin(); it!=end; ++it ) { delete *it; } FDELETE cs; }