Пример #1
0
// ReadOnly
//------------------------------------------------------------------------------
void TestFileIO::ReadOnly() const
{
	// generate a process unique file path
	AStackString<> path;
	GenerateTempFileName( path );

	// create it
	FileStream f;
	TEST_ASSERT( f.Open( path.Get(), FileStream::WRITE_ONLY ) == true );
	f.Close();

	// should not be read only
	TEST_ASSERT( FileIO::GetReadOnly( path ) == false );

	// set readonly
	TEST_ASSERT( FileIO::SetReadOnly( path.Get(), true ) == true );

	// should be read only
	TEST_ASSERT( FileIO::GetReadOnly( path ) == true );

	// delete should fail
	TEST_ASSERT( FileIO::FileDelete( path.Get() ) == false );

	// clean up
	TEST_ASSERT( FileIO::SetReadOnly( path.Get(), false ) == true );
    TEST_ASSERT( FileIO::GetReadOnly( path ) == false );
	TEST_ASSERT( FileIO::FileDelete( path.Get() ) == true );
}
Пример #2
0
	int LaunchSubProcess( const AString & args )
	{
		// try to make a copy of our exe
		AStackString<> exeName;
		Env::GetExePath( exeName );
		AStackString<> exeNameCopy( exeName );
		exeNameCopy += ".copy";
		Timer t;
		while ( FileIO::FileCopy( exeName.Get(), exeNameCopy.Get() ) == false )
		{
			if ( t.GetElapsed() > 5.0f )
			{
				AStackString<> msg;
				msg.Format( "Failed to make sub-process copy - error: %u (0x%x)\n\nSrc: %s\nDst: %s\n", Env::GetLastErr(), Env::GetLastErr(), exeName.Get(), exeNameCopy.Get() );
				ShowMsgBox( msg.Get() );
				return -2;
			}
			Thread::Sleep( 100 );
		}
	
		AStackString<> argsCopy( args );
		argsCopy += " -subprocess";
	
		// allow subprocess to access the mutex
		g_OneProcessMutex.Unlock();
	
		Process p;
	    #if defined( __WINDOWS__ )
	        p.DisableHandleRedirection(); // TODO:MAC TODO:LINUX is this needed?
	    #endif
		p.Spawn( exeNameCopy.Get(), argsCopy.Get(), nullptr, nullptr );
		p.Detach();
	
		return 0;
	}
Пример #3
0
REGISTER_TESTS_END

// FileExists
//------------------------------------------------------------------------------
void TestFileIO::FileExists() const
{
	// generate a process unique file path
	AStackString<> path;
	GenerateTempFileName( path );

	// ensure doesn't exist
	FileIO::FileDelete( path.Get() ); // delete in case left over from previous test run
	TEST_ASSERT( FileIO::FileExists( path.Get() ) == false );

	// create it
	FileStream f;
	TEST_ASSERT( f.Open( path.Get(), FileStream::WRITE_ONLY ) == true );
	f.Close();

	// ensure exists
	TEST_ASSERT( FileIO::FileExists( path.Get() ) == true );

	// clean up
	TEST_ASSERT( FileIO::FileDelete( path.Get() ) == true );
	TEST_ASSERT( FileIO::FileExists( path.Get() ) == false );
}
Пример #4
0
// FileMove
//------------------------------------------------------------------------------
void TestFileIO::FileMove() const
{
	// generate a process unique file path
	AStackString<> path;
	GenerateTempFileName( path );

	// generate copy file name
	AStackString<> pathCopy( path );
	pathCopy += ".copy";

	// make sure nothing is left from previous runs
	FileIO::FileDelete( path.Get() );
	FileIO::FileDelete( pathCopy.Get() );

	// create it
	FileStream f;
	TEST_ASSERT( f.Open( path.Get(), FileStream::WRITE_ONLY ) == true );
	f.Close();

	// move it
	TEST_ASSERT( FileIO::FileMove( path, pathCopy ) );
	TEST_ASSERT( FileIO::FileExists( path.Get() ) == false );
	TEST_ASSERT( FileIO::FileExists( pathCopy.Get() ) == true );

	// cleanup
	VERIFY( FileIO::FileDelete( pathCopy.Get() ) );
}
Пример #5
0
// StoreVariableString
//------------------------------------------------------------------------------
bool BFFParser::StoreVariableString( const AString & name,
									 const BFFIterator & valueStart, const BFFIterator & valueEnd,
									 const BFFIterator & operatorIter,
									 BFFStackFrame * frame )
{
	// unescape and subsitute embedded variables
	AStackString< 2048 > value;
	if ( PerformVariableSubstitutions( valueStart, valueEnd, value ) == false )
	{
		return false;
	}

	// are we concatenating?
	const BFFVariable * varToConcat = nullptr;
	if ( *operatorIter == BFF_VARIABLE_CONCATENATION )
	{
		// find existing
		varToConcat = BFFStackFrame::GetVar( name, frame );
		if ( varToConcat == nullptr )
		{
			Error::Error_1026_VariableNotFoundForConcatenation( operatorIter, name );
			return false;
		}

		// make sure types are compatible
		if ( varToConcat->IsString() )
		{
			// OK - can concat String to String
			AStackString< 1024 > finalValue( varToConcat->GetString() );
			finalValue += value;

			BFFStackFrame::SetVarString( name, finalValue, frame );
			FLOG_INFO( "Appended '%s' to <String> variable '%s' with result '%s'", value.Get(), name.Get(), finalValue.Get() );
			return true;
		}
		else if ( varToConcat->IsArrayOfStrings() )
		{
			// OK - can concat String to ArrayOfStrings
			Array< AString > finalValues( varToConcat->GetArrayOfStrings().GetSize() + 1, false );
			finalValues = varToConcat->GetArrayOfStrings();
			finalValues.Append( value );

			BFFStackFrame::SetVarArrayOfStrings( name, finalValues, frame );
			FLOG_INFO( "Appended '%s' to <ArrayOfStrings> variable '%s' with result of %i items", value.Get(), name.Get(), finalValues.GetSize() );
			return true;
		}
		else
		{
			Error::Error_1027_CannotConcatenate( operatorIter, name, varToConcat->GetType(), BFFVariable::VAR_STRING );
			return false;
		}
	}

	// handle regular assignment of string
	BFFStackFrame::SetVarString( name, value, frame );
	FLOG_INFO( "Registered <string> variable '%s' with value '%s'", name.Get(), value.Get() );
	return true;
}
Пример #6
0
// GetOtherLibrary
//------------------------------------------------------------------------------
bool LinkerNode::GetOtherLibrary( NodeGraph & nodeGraph,
                                  const BFFIterator & iter,
                                  const Function * function,
                                  Dependencies & libs,
                                  const AString & path,
                                  const AString & lib,
                                  bool & found ) const
{
    found = false;

    AStackString<> potentialNodeName( path );
    if ( !potentialNodeName.IsEmpty() )
    {
        PathUtils::EnsureTrailingSlash( potentialNodeName );
    }
    potentialNodeName += lib;
    AStackString<> potentialNodeNameClean;
    NodeGraph::CleanPath( potentialNodeName, potentialNodeNameClean );

    // see if a node already exists
    Node * node = nodeGraph.FindNode( potentialNodeNameClean );
    if ( node )
    {
        // aliases not supported - must point to something that provides a file
        if ( node->IsAFile() == false )
        {
            Error::Error_1103_NotAFile( iter, function, ".LinkerOptions", potentialNodeNameClean, node->GetType() );
            return false;
        }

        // found existing node
        libs.Append( Dependency( node ) );
        found = true;
        return true; // no error
    }

    // see if the file exists on disk at this location
    if ( FileIO::FileExists( potentialNodeNameClean.Get() ) )
    {
        node = nodeGraph.CreateFileNode( potentialNodeNameClean );
        libs.Append( Dependency( node ) );
        found = true;
        FLOG_INFO( "Additional library '%s' assumed to be '%s'\n", lib.Get(), potentialNodeNameClean.Get() );
        return true; // no error
    }

    return true; // no error
}
Пример #7
0
// DoToggleSection
//------------------------------------------------------------------------------
void Report::DoToggleSection( size_t numMore )
{
	static int tableId = 0;
	++tableId;
	AStackString<> tableIdStr;
	tableIdStr.Format( "table%u", tableId );

	DoTableStop();
	AStackString<> more;
	if ( numMore )
	{
		more.Format( "%u ", (uint32_t)numMore );
	}
	Write( "<a href='javascript:toggleTable(\"%s\");'>%sMore...</a>\n", tableIdStr.Get(), more.Get() );
	DoTableStart( DEFAULT_TABLE_WIDTH, tableIdStr.Get(), true ); // hide table
}
Пример #8
0
// Generate
//------------------------------------------------------------------------------
void Report::Generate( const FBuildStats & stats )
{
	Timer t;

	// pre-allocate a large string for output
	m_Output.SetReserved( MEGABYTE );
	m_Output.SetLength( 0 );

	// generate some common data used in reporting
	GetLibraryStats( stats );

	// build the report
	CreateHeader();

	CreateTitle();

	CreateOverview( stats );

	DoCPUTimeByType( stats );
	DoCacheStats( stats );
	DoCPUTimeByLibrary();
	DoCPUTimeByItem( stats );

	DoIncludes();

	CreateFooter();

	// patch in time take
	const float time = t.GetElapsed();
	AStackString<> timeTakenBuffer;
	stats.FormatTime( time, timeTakenBuffer );
	char * placeholder = m_Output.Find( "^^^^    " );
	memcpy( placeholder, timeTakenBuffer.Get(), timeTakenBuffer.GetLength() );
	
}
Пример #9
0
// Format
//------------------------------------------------------------------------------
void TestAString::Format() const
{
    // Create a really long input string
    AStackString<> longInput;
    const size_t longStringLen( 1024 * 1024 );
    for ( size_t i=0; i<longStringLen; ++i )
    {
        longInput += 'A';
    }

    // Make sure we correctly handle formatting large strings
    AStackString<> buffer;
    buffer.Format( "%s", longInput.Get() );
    TEST_ASSERT( buffer.GetLength() == longStringLen );
    TEST_ASSERT( AString::StrLen( buffer.Get() ) == longStringLen );
}
Пример #10
0
// Load
//------------------------------------------------------------------------------
/*static*/ Object * ReflectionInfo::Load( const char * scopedName )
{
	AStackString<> fullPath;
	fullPath.Format( "Reflection\\%s.obj", scopedName );

	FileStream fs;
	if ( fs.Open( fullPath.Get(), FileStream::READ_ONLY ) == false )
	{
		return nullptr;
	}

	const size_t fileSize = (size_t)fs.GetFileSize();
	AutoPtr< char > mem( (char *)Alloc( fileSize + 1 ) );
	if ( fs.Read( mem.Get(), fileSize ) != fileSize )
	{
		return nullptr;
	}
	mem.Get()[ fileSize ] = 0;

	ConstMemoryStream ms( mem.Get(), fileSize + 1 );
	TextReader tr( ms );
	RefObject * refObject = tr.Read();
	ASSERT( !refObject || DynamicCast< Object >( refObject ) );

	return (Object *)refObject;
}
Пример #11
0
// StartBuild
//------------------------------------------------------------------------------
/*static*/ void FLog::StartBuild()
{
    if ( FBuild::Get().GetOptions().m_EnableMonitor )
    {
        // TODO:B Change the monitoring log path
        //  - it's not uniquified per instance
        //  - we already have a .fbuild.tmp folder we should use
        AStackString<> fullPath;
        FileIO::GetTempDir( fullPath );
        fullPath += "FastBuild/FastBuildLog.log";

        ASSERT( g_MonitorFileStream == nullptr );
        MutexHolder lock( g_MonitorMutex );
        g_MonitorFileStream = new FileStream();
        if ( g_MonitorFileStream->Open( fullPath.Get(), FileStream::WRITE_ONLY ) == false )
        {
            delete g_MonitorFileStream;
            g_MonitorFileStream = nullptr;
        }

        Monitor( "START_BUILD %u %u\n", FBUILD_MONITOR_VERSION, Process::GetCurrentId() );
    }

    Tracing::AddCallbackOutput( &TracingOutputCallback );
}
Пример #12
0
// Load
//------------------------------------------------------------------------------
void WorkerSettings::Load()
{
    AStackString<> settingsPath;
    Env::GetExePath( settingsPath );
    settingsPath += ".settings";

    FileStream f;
    if ( f.Open( settingsPath.Get(), FileStream::READ_ONLY ) )
    {
        char header[ 4 ] = { 0 };
        f.Read( &header, 4 );
        if ( ( header[ 3 ] < FBUILDWORKER_SETTINGS_MIN_VERSION ) ||
             ( header[ 3 ] > FBUILDWORKER_SETTINGS_CURRENT_VERSION ) )
        {
            return; // version is too old, or newer, and cannot be read
        }

        // settings
        uint32_t mode;
        f.Read( mode );
        m_Mode = (Mode)mode;
        f.Read( m_NumCPUsToUse );
        f.Read( m_StartMinimized );
    }
}
Пример #13
0
// GetNumProcessors
//------------------------------------------------------------------------------
/*static*/ uint32_t Env::GetNumProcessors()
{
    #if defined( __WINDOWS__ )
        // Default to NUMBER_OF_PROCESSORS
        uint32_t numProcessors = 1;

		AStackString< 32 > var;
		if ( GetEnvVariable( "NUMBER_OF_PROCESSORS", var ) )
		{
            if ( sscanf_s( var.Get(), "%u", &numProcessors ) != 1 )
            {
                numProcessors = 1;
            }
        }

        return numProcessors;
    #elif defined( __LINUX__ ) || defined( __APPLE__ )
        long numCPUs = sysconf( _SC_NPROCESSORS_ONLN );
        if ( numCPUs <= 0 )
        {
            ASSERT( false ); // this should never fail
            numCPUs = 1;
        }
        return ( uint32_t )numCPUs;
	#else
        #error Unknown platform
    #endif
}
Пример #14
0
// Lock
//------------------------------------------------------------------------------
bool SystemMutex::TryLock()
{ 
    #if defined( __WINDOWS__ )
		void * handle = (void *)CreateMutex( nullptr, TRUE, m_Name.Get() );
		if ( GetLastError() == ERROR_ALREADY_EXISTS )
		{
			if ( ( handle != INVALID_HANDLE_VALUE ) && ( handle != 0 ) )
			{
				CloseHandle( handle );
			}
			return false;
		}
		m_Handle = handle;
		return true;
    #elif defined( __LINUX__ ) || defined( __APPLE__ )
        AStackString<> tempFileName;
        tempFileName.Format( "/var/run/%s.lock", m_Name.Get() );
        m_Handle = open( tempFileName.Get(), O_CREAT | O_RDWR, 0666 );
        int rc = flock( m_Handle, LOCK_EX | LOCK_NB );
        if ( rc )
        {
            if ( errno == EWOULDBLOCK )
            {
                return false; // locked by another process
            }
        }
        return true; // we own it now
    #else
        #error Unknown platform
    #endif
}
Пример #15
0
// WriteNestedProjects
//------------------------------------------------------------------------------
void SLNGenerator::WriteNestedProjects( const Array< AString > & solutionProjectsToFolder,
                                        const Array< AString > & solutionFolderPaths )
{
    if ( solutionProjectsToFolder.GetSize() == 0 &&
            solutionFolderPaths.GetSize() == 0 )
    {
        return; // skip global section
    }

    Write( "\tGlobalSection(NestedProjects) = preSolution\r\n" );

    // Write every project to solution folder relationships
    const AString * const solutionProjectsToFolderEnd = solutionProjectsToFolder.End();
    for( const AString * it = solutionProjectsToFolder.Begin() ; it != solutionProjectsToFolderEnd ; ++it )
    {
        Write( it->Get() );
    }

    // Write every intermediate path
    const AString * const solutionFolderPathsEnd = solutionFolderPaths.End();
    for( const AString * it = solutionFolderPaths.Begin() ; it != solutionFolderPathsEnd ; ++it )
    {
        // parse solution folder parent path
        AStackString<> solutionFolderParentGuid;
        const char * lastSlash = it->FindLast( NATIVE_SLASH );
        if ( lastSlash )
        {
            AStackString<> solutionFolderParentPath( it->Get(), lastSlash );
            VSProjectGenerator::FormatDeterministicProjectGUID( solutionFolderParentGuid, solutionFolderParentPath );
        }

        if ( solutionFolderParentGuid.GetLength() > 0 )
        {
            // generate a guid for the solution folder
            AStackString<> solutionFolderGuid;
            VSProjectGenerator::FormatDeterministicProjectGUID( solutionFolderGuid, *it );

            solutionFolderGuid.ToUpper();
            solutionFolderParentGuid.ToUpper();

            // write parent solution folder relationship
            Write( "\t\t%s = %s\r\n", solutionFolderGuid.Get(), solutionFolderParentGuid.Get() );
        }
    }

    Write( "\tEndGlobalSection\r\n" );
}
Пример #16
0
// ReadRef
//------------------------------------------------------------------------------
bool TextReader::ReadRef()
{
    // Name
    AStackString<> name;
    if ( !GetToken( name ) )
    {
        Error( "Missing ref name" );
        return false;
    }

    AStackString<> value;
    if ( !GetString( value ) )
    {
        Error( "Missing ref value" );
        return false;
    }

    Ref< RefObject > ref;
    if ( value != "null" )
    {
        ref = (RefObject *)ReflectionInfo::CreateObject( value );
        if ( ref.Get() == nullptr )
        {
            Error( "Unable to create sub-object" );
            ASSERT( false ); // TODO: Handle failure/skipping gracefully
            return false;
        }
    }

    const StackFrame & sf = m_DeserializationStack.Top();

    if ( sf.m_ArrayProperty )
    {
        void * arrayBase = (void *)( (size_t)sf.m_Base + (size_t)sf.m_ArrayProperty->GetOffset() );
        Array< Ref< RefObject > > *array = ( Array< Ref< RefObject > > *)( arrayBase );
        array->Append( ref );
    }
    else
    {
        sf.m_Reflection->SetProperty( sf.m_Base, name.Get(), ref );
    }

    // do sub-object properties if needed
    if ( ref.Get() )
    {
        StackFrame newFrame;
        newFrame.m_Base = (void *)ref.Get();
        newFrame.m_Reflection = ref->GetReflectionInfoV();
        newFrame.m_ArrayProperty = nullptr;
        #ifdef DEBUG
            newFrame.m_RefObject = ref.Get();
            newFrame.m_Struct = nullptr;
        #endif
        m_DeserializationStack.Append( newFrame );
    }

    return true;
}
Пример #17
0
// CreateThreadLocalTmpDir
//------------------------------------------------------------------------------
/*static*/ void WorkerThread::CreateThreadLocalTmpDir()
{
	// create isolated subdir
	AStackString<> tmpFileName;
	CreateTempFilePath( ".tmp", tmpFileName );
	char * lastSlash = tmpFileName.FindLast( NATIVE_SLASH );
	tmpFileName.SetLength( (uint32_t)( lastSlash - tmpFileName.Get() ) );
	FileIO::EnsurePathExists( tmpFileName );
}
Пример #18
0
// TestValidExeWithDLL
//------------------------------------------------------------------------------
void TestDLL::TestValidExeWithDLL() const
{
	const AStackString<> exe( "../../../../tmp/Test/DLL/exe.exe" );

	Process p;
	p.Spawn( exe.Get(), nullptr, nullptr, nullptr );
	int ret = p.WaitForExit();
	TEST_ASSERT( ret == 99 );
}
Пример #19
0
// Work
//------------------------------------------------------------------------------
int Worker::Work()
{
	// start listening
	if ( m_ConnectionPool->Listen( Protocol::PROTOCOL_PORT ) == false )
	{
		ShowMessageBox( "Failed to listen on port %u.  Check port is not in use.", Protocol::PROTOCOL_PORT );
		return -1;
	}

	// Special folder for Orbis Clang
	// We just create this folder whether it's needed or not
	{
		AStackString<> tmpPath;
		VERIFY( FileIO::GetTempDir( tmpPath ) );
        #if defined( __WINDOWS__ )
            tmpPath += ".fbuild.tmp\\target\\include";
        #else
            tmpPath += "_fbuild.tmp/target/include";
        #endif
		if ( !FileIO::EnsurePathExists( tmpPath ) )
		{
			ShowMessageBox( "Failed to initialize tmp folder.  Error: 0x%x", Env::GetLastErr() );
			return -2;
		}
        #if defined( __WINDOWS__ )
            tmpPath += "\\.lock";
        #else
            tmpPath += "/_lock";
        #endif
		if ( !m_TargetIncludeFolderLock.Open( tmpPath.Get(), FileStream::WRITE_ONLY ) )
		{
			ShowMessageBox( "Failed to lock tmp folder.  Error: 0x%x", Env::GetLastErr() );
			return -2;
		}
	}

	while ( WorkerWindow::Get().WantToQuit() == false )
	{
		UpdateAvailability();

		UpdateUI();

		CheckForExeUpdate();

		PROFILE_SYNCHRONIZE

		Thread::Sleep( 100 );
	}

	// allow to UI to shutdown
	// the application MUST NOT try to update the UI from this point on
	m_MainWindow->SetAllowQuit();

	m_WorkerBrokerage.SetAvailability( false );

	return 0;
}
Пример #20
0
// FileDelete
//------------------------------------------------------------------------------
void TestFileIO::FileDelete() const
{
	// generate a process unique file path
	AStackString<> path;
	GenerateTempFileName( path );

	// create it
	FileStream f;
	TEST_ASSERT( f.Open( path.Get(), FileStream::WRITE_ONLY ) == true );
	f.Close();

	// ensure exists
	TEST_ASSERT( FileIO::FileExists( path.Get() ) == true );

	// delete
	TEST_ASSERT( FileIO::FileDelete( path.Get() ) == true );
	TEST_ASSERT( FileIO::FileExists( path.Get() ) == false );
}
Пример #21
0
PRAGMA_DISABLE_POP_MSVC // warning C6262: Function uses '262212' bytes of stack

// DoPieChart
//------------------------------------------------------------------------------
void Report::DoPieChart( const Array< PieItem > & items, const char * units )
{
	AStackString<> buffer;

	uint32_t height = Math::Max< uint32_t >( 140, 40 + 25 * (uint32_t)items.GetSize() );

	m_NumPieCharts++;

	Write( "<section>\n" );
	Write( "<div>\n" );
	Write( "<canvas id=\"canvas%u\" width=\"500\" height=\"%u\">\n", m_NumPieCharts, height );
	Write( "HTML5 Canvas support required.\n" );
	Write( "</canvas>\n" );
	Write( "</div>\n" );

	Write( "<script type=\"text/javascript\">\n" );
	Write( "	var myData = [" );
	for ( size_t i=0; i<items.GetSize(); ++i )
	{
		if ( i > 0 )
		{
			Write( "," );
		}
		buffer.Format( "%2.3f", items[ i ].value );
		Write( buffer.Get() );
	}
	Write( "];\n" );
	Write( "	var myLabels = [" );
	for ( size_t i=0; i<items.GetSize(); ++i )
	{
		if ( i > 0 )
		{
			Write( "," );
		}
		Write( "\"%s\"", items[ i ].label );
	}
	Write( "];\n" );
	Write( "	var myColors = [" );
	for ( size_t i=0; i<items.GetSize(); ++i )
	{
		if ( i > 0 )
		{
			Write( "," );
		}
		Write( "\"#%x\"", items[ i ].color );
	}
	Write( "];\n" );

	Write( "	plotData(\"canvas%u\",myData,myLabels,myColors,\"%s\");\n", m_NumPieCharts, units );
	Write( "</script>\n" );
	Write( "</section>\n" );
}
Пример #22
0
// StopBuild
//------------------------------------------------------------------------------
/*static*/ void FLog::StopBuild()
{
	Tracing::RemoveCallbackOutput( &TracingOutputCallback );

	if ( s_ShowProgress )
	{
		fputs( g_ClearLineString.Get(), stdout );
		m_ProgressText.Clear();
	}
}
Пример #23
0
// Commit
//------------------------------------------------------------------------------
/*virtual*/ bool FunctionSettings::Commit( NodeGraph & /*nodeGraph*/, const BFFIterator & funcStartIter ) const
{
    // using a cache plugin?
    AStackString<> cachePluginDLL;
    if ( !GetString( funcStartIter, cachePluginDLL, ".CachePluginDLL" ) )
    {
        return false;
    }
    FBuild::Get().SetCachePluginDLL( cachePluginDLL );
    if ( !cachePluginDLL.IsEmpty() )
    {
        FLOG_INFO( "CachePluginDLL: '%s'", cachePluginDLL.Get() );
    }

    // try to get the cache path from the config
    const BFFVariable * cachePathVar;
    if ( !GetString( funcStartIter, cachePathVar, ".CachePath" ) )
    {
        return false;
    }
    if ( cachePathVar )
    {
        s_CachePath = cachePathVar->GetString();

        // override environment default only if not empty
        if ( s_CachePath.IsEmpty() == false )
        {
            FBuild::Get().SetCachePath( s_CachePath );
        }
    }

    // "Workers"
    Array< AString > workerList;
    if ( !GetStrings( funcStartIter, workerList, ".Workers" ) )
    {
        return false;
    }
    if ( !workerList.IsEmpty() )
    {
        FBuild::Get().SetWorkerList( workerList );
    }

    // "Environment"
    Array< AString > environment;
    if ( !GetStrings( funcStartIter, environment, ".Environment" ) )
    {
        return false;
    }
    if ( !environment.IsEmpty() )
    {
        ProcessEnvironment( environment );
    }

    return true;
}
Пример #24
0
// Build
//------------------------------------------------------------------------------
/*static*/ void FLog::Build( const char * formatString, ... )
{
    AStackString< 8192 > buffer;

    va_list args;
    va_start(args, formatString);
    buffer.VFormat( formatString, args );
    va_end( args );

    Tracing::Output( buffer.Get() );
}
Пример #25
0
// Info
//------------------------------------------------------------------------------
/*static*/ void FLog::Info( const char * formatString, ... )
{
    AStackString< 8192 > buffer;

    va_list args;
    va_start(args, formatString);
    buffer.VFormat( formatString, args );
    va_end( args );

    Output( "Info:", buffer.Get() );
}
Пример #26
0
// UpdateUI
//------------------------------------------------------------------------------
void Worker::UpdateUI()
{
	// throttle UI updates
	if ( m_UIUpdateTimer.GetElapsed() < 0.25f )
	{
		return;
	}

	// title bar
	size_t numConnections = m_ConnectionPool->GetNumConnections();
	AStackString<> status;
	status.Format( "%u Connections", (uint32_t)numConnections );
	if ( m_RestartNeeded )
	{
		status += " (Restart Pending)";
	}
	#if defined( __WINDOWS__ )
		if ( m_LastDiskSpaceResult == 0 )
		{
			status += " (Low Disk Space)";
		}
	#endif
	m_MainWindow->SetStatus( status.Get() );

	// thread output
	JobQueueRemote & jqr = JobQueueRemote::Get();
	const size_t numWorkers = jqr.GetNumWorkers();
	for ( size_t i=0; i<numWorkers; ++i )
	{
		// get status of worker
		AStackString<> workerStatus;
		AStackString<> hostName;
		bool isIdle;
		jqr.GetWorkerStatus( i, hostName, workerStatus, isIdle );

		// are we syncing tools?
		if ( isIdle )
		{
			AStackString<> statusStr;
			if ( m_ConnectionPool->IsSynchingTool( statusStr ) )
			{
				// show status of synchronization
				workerStatus = statusStr;
			}
		}

		// reflect in UI
		m_MainWindow->SetWorkerState( i, hostName, workerStatus );
	}

	m_UIUpdateTimer.Start();
}
Пример #27
0
// Monitor
//------------------------------------------------------------------------------
/*static*/ void FLog::Monitor( const char * formatString, ... )
{
    // Is monitoring enabled?
    if ( g_MonitorFileStream == nullptr )
    {
        return; // No - nothing to do
    }

    PROFILE_SECTION( "FLog::Monitor" )

    AStackString< 1024 > buffer;
    va_list args;
    va_start( args, formatString );
    buffer.VFormat( formatString, args );
    va_end( args );

    AStackString< 1024 > finalBuffer;
    finalBuffer.Format( "%llu %s", Time::GetCurrentFileTime(), buffer.Get() );

    MutexHolder lock( g_MonitorMutex );
    g_MonitorFileStream->WriteBuffer( finalBuffer.Get(), finalBuffer.GetLength() );
}
Пример #28
0
// Publish
//------------------------------------------------------------------------------
/*virtual*/ bool Cache::Publish( const AString & cacheId, const void * data, size_t dataSize )
{
    AStackString<> cacheFileName;
    GetCacheFileName( cacheId, cacheFileName );

    // make sure the cache output path exists
    char * lastSlash = cacheFileName.FindLast( NATIVE_SLASH );
    *lastSlash = 0;
    if ( !FileIO::EnsurePathExists( cacheFileName ) )
    {
        return false;
    }
    *lastSlash = NATIVE_SLASH;

    // open output cache (tmp) file
    AStackString<> cacheFileTmpName( cacheFileName );
    cacheFileTmpName += ".tmp";
    FileStream cacheTmpFile;
    if( !cacheTmpFile.Open( cacheFileTmpName.Get(), FileStream::WRITE_ONLY ) )
    {
        return false;
    }

    // write data
    bool cacheTmpWriteOk = ( cacheTmpFile.Write( data, dataSize ) == dataSize );
    cacheTmpFile.Close();

    if ( !cacheTmpWriteOk )
    {
        // failed to write to cache tmp file
        FileIO::FileDelete( cacheFileTmpName.Get() ); // try to cleanup failure
        return false;
    }

    // rename tmp file to real file
    if ( FileIO::FileMove( cacheFileTmpName, cacheFileName ) == false )
    {
        // try to delete (possibly) existing file
        FileIO::FileDelete( cacheFileName.Get() );

        // try rename again
        if ( FileIO::FileMove( cacheFileTmpName, cacheFileName ) == false )
        {
            // problem renaming file
            FileIO::FileDelete( cacheFileTmpName.Get() ); // try to cleanup tmp file
            return false;
        }
    }

    return true;
}
Пример #29
0
// FileTime
//------------------------------------------------------------------------------
void TestFileIO::FileTime() const
{
	// generate a process unique file path
	AStackString<> path;
	GenerateTempFileName( path );

	// create it
	FileStream f;
	TEST_ASSERT( f.Open( path.Get(), FileStream::WRITE_ONLY ) == true );
	f.Close();

	// get last write time
	const uint64_t oldTime = FileIO::GetFileLastWriteTime( path );
	TEST_ASSERT( oldTime != 0 );

	// wait for some time that is bigger than filesystem time granularity
    #if defined( __OSX__ )
        // HFS+ has surprisingly poor time resolution (1 second)
        Thread::Sleep( 1100 );
    #else
        Thread::Sleep( 500 );
    #endif
    
	// modify file
	FileStream f2;
	TEST_ASSERT( f.Open( path.Get(), FileStream::WRITE_ONLY ) == true );
	f.Write( (uint32_t)0 );
	f.Close();

	// get new last write time
	const uint64_t newTime = FileIO::GetFileLastWriteTime( path );
	TEST_ASSERT( newTime > oldTime );

	// manually set time back
	TEST_ASSERT( FileIO::SetFileLastWriteTime( path, oldTime ) == true );
	uint64_t timeNow = FileIO::GetFileLastWriteTime( path );
    TEST_ASSERT( timeNow == oldTime );
}
Пример #30
0
// AStackStringOverflow
//------------------------------------------------------------------------------
void TestAString::AStackStringOverflow() const
{
    {
        // constructor with string longer than buffer
        AStackString< 8 > string( "01234567890123456789" );
        TEST_ASSERT( string.GetLength() == 20 );
        TEST_ASSERT( string.GetLength() == AString::StrLen( string.Get() ) );
    }
    {
        // assigned of string longer than buffer
        AStackString< 8 > string;
        string = "01234567890123456789";
        TEST_ASSERT( string.GetLength() == 20 );
        TEST_ASSERT( string.GetLength() == AString::StrLen( string.Get() ) );
    }
    {
        // concetentation of string longer than buffer
        AStackString< 8 > string;
        string += "01234567890123456789";
        TEST_ASSERT( string.GetLength() == 20 );
        TEST_ASSERT( string.GetLength() == AString::StrLen( string.Get() ) );
    }
}