// Open //------------------------------------------------------------------------------ bool FileStream::Open( const char * fileName, uint32_t fileMode ) { ASSERT( !IsOpen() ); #if defined( __WINDOWS__ ) DWORD desiredAccess( 0 ); DWORD shareMode( 0 ); DWORD creationDisposition( 0 ); DWORD flags( FILE_ATTRIBUTE_NORMAL ); // access mode if ( ( fileMode & READ_ONLY ) != 0 ) { ASSERT( fileMode == READ_ONLY ); // no extra flags allowed desiredAccess |= GENERIC_READ; shareMode |= FILE_SHARE_READ; // allow other readers creationDisposition |= OPEN_EXISTING; } else if ( ( fileMode & WRITE_ONLY ) != 0 ) { desiredAccess |= GENERIC_WRITE; shareMode |= FILE_SHARE_READ; // allow other readers creationDisposition |= CREATE_ALWAYS; // overwrite existing } else { ASSERT( false ); // must specify an access mode } // extra flags if ( ( fileMode & TEMP ) != 0 ) { flags |= FILE_ATTRIBUTE_TEMPORARY; // don't flush to disk if possible } // for sharing violations, we'll retry a few times as per http://support.microsoft.com/kb/316609 size_t retryCount = 0; while ( retryCount < 5 ) { HANDLE h = CreateFile( fileName, // _In_ LPCTSTR lpFileName, desiredAccess, // _In_ DWORD dwDesiredAccess, shareMode, // _In_ DWORD dwShareMode, nullptr, // _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, creationDisposition, // _In_ DWORD dwCreationDisposition, flags, // _In_ DWORD dwFlagsAndAttributes, nullptr ); // _In_opt_ HANDLE hTemplateFile if ( h != INVALID_HANDLE_VALUE ) { // file opened ok m_Handle = (void *)h; FSDEBUG( DEBUGSPAM( "Open file OK: %x - '%s' on %x\n", m_Handle, fileName, Thread::GetCurrentThreadId() ); ) return true; }
// DoBuild //------------------------------------------------------------------------------ /*static*/ Node::BuildResult JobQueueRemote::DoBuild( Job * job, bool racingRemoteJob ) { Timer timer; // track how long the item takes ObjectNode * node = job->GetNode()->CastTo< ObjectNode >(); // remote tasks must output to a tmp file if ( job->IsLocal() == false ) { // file name should be the same as on host const char * fileName = ( job->GetRemoteName().FindLast( NATIVE_SLASH ) + 1 ); AStackString<> tmpFileName; WorkerThread::CreateTempFilePath( fileName, tmpFileName ); node->ReplaceDummyName( tmpFileName ); #ifdef DEBUG DEBUGSPAM( "REMOTE: %s (%s)\n", fileName, job->GetRemoteName().Get() ); #endif } ASSERT( node->IsAFile() ); // make sure the output path exists if ( Node::EnsurePathExistsForFile( node->GetName() ) == false ) { // error already output by EnsurePathExistsForFile return Node::NODE_RESULT_FAILED; } // Delete any left over PDB from a previous run (to be sure we have a clean pdb) if ( node->IsUsingPDB() && ( job->IsLocal() == false ) ) { AStackString<> pdbName; node->GetPDBName( pdbName ); FileIO::FileDelete( pdbName.Get() ); } Node::BuildResult result; { PROFILE_SECTION( racingRemoteJob ? "RACE" : "LOCAL" ); result = ((Node *)node )->DoBuild2( job, racingRemoteJob ); } uint32_t timeTakenMS = uint32_t( timer.GetElapsedMS() ); if ( result == Node::NODE_RESULT_OK ) { // record new build time only if built (i.e. if failed, the time // does not represent how long it takes to create this resource) node->SetLastBuildTime( timeTakenMS ); node->SetStatFlag( Node::STATS_BUILT ); //FLOG_INFO( "-Build: %u ms\t%s", timeTakenMS, node->GetName().Get() ); #ifdef DEBUG if ( job->IsLocal() ) { // record new file time for remote job we built locally ASSERT( node->m_Stamp == FileIO::GetFileLastWriteTime(node->GetName()) ); } #endif } if ( result == Node::NODE_RESULT_FAILED ) { // build of file failed - if there is a file.... if ( FileIO::FileExists( node->GetName().Get() ) ) { // ... it is invalid, so try to delete it if ( FileIO::FileDelete( node->GetName().Get() ) == false ) { // failed to delete it - this might cause future build problems! FLOG_ERROR( "Post failure deletion failed for '%s'", node->GetName().Get() ); } } } else { // build completed ok, or retrieved from cache... ASSERT( result == Node::NODE_RESULT_OK ); // TODO:A Also read into job if cache is being used if ( job->IsLocal() == false ) { // read results into memory to send back to client if ( ReadResults( job ) == false ) { result = Node::NODE_RESULT_FAILED; } } } // if compiling to a tmp file, do cleanup if ( job->IsLocal() == false ) { // Cleanup obj file FileIO::FileDelete( node->GetName().Get() ); // Cleanup PDB file if ( node->IsUsingPDB() ) { AStackString<> pdbName; node->GetPDBName( pdbName ); FileIO::FileDelete( pdbName.Get() ); } } // log processing time node->AddProcessingTime( timeTakenMS ); return result; }