Example #1
0
void CAI_ScriptConditions::Enable( void )
{
	m_hTarget = gEntList.FindEntityByName( NULL, m_target );

	CBaseEntity *pActor = gEntList.FindEntityByName( NULL, m_Actor );
	if ( m_ElementList.Count() == 0 )
	{
		if ( m_Actor != NULL_STRING && pActor == NULL )
		{
			DevMsg( "Warning: Spawning AI script conditions (%s) associated with an non-existant NPC\n", GetDebugName() );
			m_NoValidActors.FireOutput( this, this, 0 );
			Disable();
			return;
		}

		if ( pActor && pActor->MyNPCPointer() == NULL )
		{
			Warning( "Script condition warning: warning actor is not an NPC\n" );
			Disable();
			return;
		}
	}

	while( pActor != NULL )
	{
		if( !ActorInList(pActor) )
		{
			AddNewElement( pActor );
		}

		pActor = gEntList.FindEntityByName( pActor, m_Actor );
	}

	//If we are hitting this it means we are using a Target->Player condition
	if ( m_Actor == NULL_STRING )
	{
		if( !ActorInList(pActor) )
		{
			AddNewElement( NULL );
		}
	}

	m_fDisabled = false;

	SetThink( &CAI_ScriptConditions::EvaluationThink );
	SetThinkTime();
}
Example #2
0
void CAI_ScriptConditions::EvaluationThink()
{
	if ( m_fDisabled == true )
		return;

	int iActorsDone = 0;

#ifdef HL2_DLL
	if( AI_GetSinglePlayer()->GetFlags() & FL_NOTARGET )
	{
		ScrCondDbgMsg( ("%s WARNING: Player is NOTARGET. This will affect all LOS conditiosn involving the player!\n", GetDebugName()) );
	}
#endif


	for ( int i = 0; i < m_ElementList.Count(); )
	{
		CAI_ScriptConditionsElement *pConditionElement = &m_ElementList[i];

		if ( pConditionElement == NULL )
		{
			i++;
			continue;
		}

		CBaseEntity *pActor = pConditionElement->GetActor();
		CBaseEntity *pActivator = this;

#ifdef HL2_EPISODIC
		if ( pActor && HasSpawnFlags( SF_ACTOR_AS_ACTIVATOR ) )
		{
			pActivator = pActor;
		}
#endif

		AssertMsg( !m_fDisabled, ("Violated invariant between CAI_ScriptConditions disabled state and think func setting") );

		if ( m_Actor != NULL_STRING && !pActor )
		{
			if ( m_ElementList.Count() == 1 )
			{
				DevMsg( "Warning: Active AI script conditions associated with an non-existant or destroyed NPC\n" );
				m_NoValidActors.FireOutput( this, this, 0 );
			}

			iActorsDone++;
			m_ElementList.Remove( i );
			continue;
		}

		i++;

		if( m_flMinTimeout > 0 && pConditionElement->GetTimeOut()->Expired() )
		{
			ScrCondDbgMsg( ( "%s firing output OnConditionsTimeout (%f seconds)\n", STRING( GetEntityName() ), pConditionElement->GetTimeOut()->GetInterval() ) );

			iActorsDone++;
			m_OnConditionsTimeout.FireOutput( pActivator, this );
			continue;
		}

		bool      result = true;
		const int nEvaluators = sizeof( gm_Evaluators ) / sizeof( gm_Evaluators[0] );

		EvalArgs_t args =
		{
			pActor,
			GetPlayer(),
			m_hTarget.Get()
		};

		for ( int i = 0; i < nEvaluators; ++i )
		{
			if ( !(this->*gm_Evaluators[i].pfnEvaluator)( args ) )
			{
				pConditionElement->GetTimer()->Reset();
				result = false;

				ScrCondDbgMsg( ( "%s failed on: %s\n", GetDebugName(), gm_Evaluators[ i ].pszName ) );

				break;
			}
		}

		if ( result )
		{
			ScrCondDbgMsg( ( "%s waiting... %f\n", GetDebugName(), pConditionElement->GetTimer()->GetRemaining() ) );
		}

		if ( result && pConditionElement->GetTimer()->Expired() )
		{
			ScrCondDbgMsg( ( "%s firing output OnConditionsSatisfied\n", GetDebugName() ) );

			// Default behavior for now, provide worldcraft option later.
			iActorsDone++;
			m_OnConditionsSatisfied.FireOutput( pActivator, this );
		}
	}

	//All done!
	if ( iActorsDone == m_ElementList.Count() )
	{
		Disable();
		m_ElementList.Purge();
	}

	SetThinkTime();
}
Example #3
0
bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[], Profile *pProfile, struct Synchronization *synch)
{
    /* Process any command-line options */
    int nParamCnt = argc - 1;
    const char** args = argv + 1;

    // create targets
    vector<Target> vTargets;
    int iFirstFile = -1;
    for (int i = 1; i < argc; i++)
    {
        if (argv[i][0] != '-' && argv[i][0] != '/')
        {
            iFirstFile = i;
            Target target;
            target.SetPath(argv[i]);
            vTargets.push_back(target);
        }
    }

    // find block size (other parameters may be stated in terms of blocks)
    for (int x = 1; x < argc; ++x)
    {
        if ((nullptr != argv[x]) && (('-' == argv[x][0]) || ('/' == argv[x][0])) && ('b' == argv[x][1]) && ('\0' != argv[x][2]))
        {
            _dwBlockSize = 0;
            UINT64 ullBlockSize;
            if (_GetSizeInBytes(&argv[x][2], ullBlockSize))
            {
                for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                {
                    // TODO: UINT64->DWORD
                    i->SetBlockSizeInBytes((DWORD)ullBlockSize);
                }
            }
            else
            {
                fprintf(stderr, "Invalid block size passed to -b\n");
                exit(1);
            }
            _dwBlockSize = (DWORD)ullBlockSize;
            break;
        }
    }

    TimeSpan timeSpan;
    bool bExit = false;
    while (nParamCnt)
    {
        const char* arg = *args;
        bool fError = false;

        // check if it is a parameter or already path
        if ('-' != *arg && '/' != *arg)
        {
            break;
        }

        // skip '-' or '/'
        ++arg;

        if ('\0' == *arg)
        {
            fprintf(stderr, "Invalid option\n");
            exit(1);
        }

        switch (*arg)
        {
        case '?':
            _DisplayUsageInfo(argv[0]);
            exit(0);

        case 'a':    //affinity
            //-a1,2,3,4 (assign threads to cpus 1,2,3,4 (round robin))
            if (!_ParseAffinity(arg, &timeSpan))
            {
                fError = true;
            }
            break;

        case 'b':    //block size
            // nop - block size has been taken care of before the loop
            break;

        case 'B':    //base file offset (offset from the beggining of the file), cannot be used with 'random'
            if (*(arg + 1) != '\0')
            {
                UINT64 cb;
                if (_GetSizeInBytes(arg + 1, cb))
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetBaseFileOffsetInBytes(cb);
                    }
                }
                else
                {
                    fprintf(stderr, "Invalid base file offset passed to -B\n");
                    fError = true;
                }
            }
            else
            {
                fError = true;
            }
            break;

        case 'c':    //create file of the given size
            if (*(arg + 1) != '\0')
            {
                UINT64 cb;
                if (_GetSizeInBytes(arg + 1, cb))
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetFileSize(cb);
                        i->SetCreateFile(true);
                    }
                }
                else
                {
                    fprintf(stderr, "Invalid file size passed to -c\n");
                    fError = true;
                }
            }
            else
            {
                fError = true;
            }
            break;

        case 'C':    //cool down time
            {
                int c = atoi(arg + 1);
                if (c >= 0)
                {
                    timeSpan.SetCooldown(c);
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'd':    //duration
            {
                int x = atoi(arg + 1);
                if (x > 0)
                {
                    timeSpan.SetDuration(x);
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'D':    //standard deviation
            {
                timeSpan.SetCalculateIopsStdDev(true);

                int x = atoi(arg + 1);
                if (x > 0)
                {
                    timeSpan.SetIoBucketDurationInMilliseconds(x);
                }
            }
            break;

        case 'e':    //etw
            if (!_ParseETWParameter(arg, pProfile))
            {
                fError = true;
            }
            break;

        case 'f':
            if ('r' == *(arg + 1))
            {
                for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                {
                    i->SetRandomAccessHint(true);
                }
            }
            else if ('s' == *(arg + 1))
            {
                for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                {
                    i->SetSequentialScanHint(true);
                }
            }
            else
            {
                if (*(arg + 1) != '\0')
                {
                    UINT64 cb;
                    if (_GetSizeInBytes(arg + 1, cb))
                    {
                        for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                        {
                            i->SetMaxFileSize(cb);
                        }
                    }
                    else
                    {
                        fprintf(stderr, "Invalid max file size passed to -f\n");
                        fError = true;
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'F':    //total number of threads
            {
                int c = atoi(arg + 1);
                if (c > 0)
                {
                    timeSpan.SetThreadCount(c);
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'g':    //throughput in bytes per millisecond
            {
                int c = atoi(arg + 1);
                if (c > 0)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetThroughput(c);
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'h':    //disable both software and hardware caching
            for (auto i = vTargets.begin(); i != vTargets.end(); i++)
            {
                i->SetDisableAllCache(true);
            }
            break;

        case 'i':    //number of IOs to issue before think time
            {
                int c = atoi(arg + 1);
                if (c > 0)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetBurstSize(c);
                        i->SetUseBurstSize(true);
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'j':    //time to wait between bursts of IOs
            {
                int c = atoi(arg + 1);
                if (c > 0)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetThinkTime(c);
                        i->SetEnableThinkTime(true);
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'I':   //io priority
            {
                int x = atoi(arg + 1);
                if (x > 0 && x < 4)
                {
                    PRIORITY_HINT hint[] = { IoPriorityHintVeryLow, IoPriorityHintLow, IoPriorityHintNormal };
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetIOPriorityHint(hint[x - 1]);
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'l':    //large pages
            for (auto i = vTargets.begin(); i != vTargets.end(); i++)
            {
                i->SetUseLargePages(true);
            }
            break;
        
        case 'L':    //measure latency
            timeSpan.SetMeasureLatency(true);
            break;

        case 'n':    //disable affinity (by default simple affinity is turned on)
            timeSpan.SetDisableAffinity(true);
            break;

        case 'o':    //request count (1==synchronous)
            {
                int c = atoi(arg + 1);
                if (c > 0)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetRequestCount(c);
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'p':    //start async IO operations with the same offset
            //makes sense only for -o2 and greater
            for (auto i = vTargets.begin(); i != vTargets.end(); i++)
            {
                i->SetUseParallelAsyncIO(true);
            }
            break;

        case 'P':    //show progress every x IO operations
            {
                int c = atoi(arg + 1);
                if (c < 1)
                {
                    c = 65536;
                }
                pProfile->SetProgress(c);
            }
            break;

        case 'r':    //random access
            {
                UINT64 cb = _dwBlockSize;
                if (*(arg + 1) != '\0')
                {
                    if (!_GetSizeInBytes(arg + 1, cb) || (cb == 0))
                    {
                        fprintf(stderr, "Invalid alignment passed to -r\n");
                        fError = true;
                    }
                }
                if (!fError)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetUseRandomAccessPattern(true);
                        i->SetBlockAlignmentInBytes(cb);
                    }
                }
            }
            break;

        case 'R':    //custom result parser
            if (0 != *(arg + 1))
            {
                const char* pszArg = arg + 1;
                if (strcmp(pszArg, "xml") == 0)
                {
                    pProfile->SetResultsFormat(ResultsFormat::Xml);
                }
                else if (strcmp(pszArg, "text") != 0)
                {
                    fError = true;
                    fprintf(stderr, "Invalid results format: '%s'.\n", pszArg);
                }
            }
            else
            {
                fError = true;
            }
            break;

        case 's':    //stride size
            {
                int idx = 1;

                if ('i' == *(arg + idx))
                {
                    // do interlocked sequential mode
                    // ISSUE-REVIEW: this does nothing if -r is specified
                    // ISSUE-REVIEW: this does nothing if -p is specified
                    // ISSUE-REVIEW: this does nothing if we are single-threaded 
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetUseInterlockedSequential(true);
                    }

                    idx++;
                }
                
                if (*(arg + idx) != '\0')
                {
                    UINT64 cb;
                    if (_GetSizeInBytes(arg + idx, cb))
                    {
                        for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                        {
                            i->SetBlockAlignmentInBytes(cb);
                        }
                    }
                    else
                    {
                        fprintf(stderr, "Invalid stride size passed to -s\n");
                        fError = true;
                    }
                }
            }
            break;

        case 'S':   //disable OS caching (software buffering)
            //IMPORTANT: File access must begin at byte offsets within the file that are integer multiples of the volume's sector size. 
            // File access must be for numbers of bytes that are integer multiples of the volume's sector size. For example, if the sector
            // size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes. 
            // Buffer addresses for read and write operations should be sector aligned (aligned on addresses in memory that are integer
            // multiples of the volume's sector size). Depending on the disk, this requirement may not be enforced. 
            for (auto i = vTargets.begin(); i != vTargets.end(); i++)
            {
                i->SetDisableOSCache(true);
            }
            break;

        case 't':    //number of threads per file
            {
                int c = atoi(arg + 1);
                if (c > 0)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetThreadsPerFile(c);
                    }
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'T':    //offsets between threads reading the same file
            {
                UINT64 cb;
                if (_GetSizeInBytes(arg + 1, cb) && (cb > 0))
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetThreadStrideInBytes(cb);
                    }
                }
                else
                {
                    fprintf(stderr, "Invalid offset passed to -T\n");
                    fError = true;
                }
            }
            break;

        case 'v':    //verbose mode
            pProfile->SetVerbose(true);
            break;

        case 'w':    //write test [default=read]
            {
                int c = -1;
                if (*(arg + 1) == '\0')
                {
                    c = _ulWriteRatio;
                }
                else
                {
                    c = atoi(arg + 1);
                    if (c < 0 || c > 100)
                    {
                        c = -1;
                        fError = true;
                    }
                }
                if (c != -1)
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetWriteRatio(c);
                    }
                }
            }
            break;

        case 'W':    //warm up time
            {
                int c = atoi(arg + 1);
                if (c >= 0)
                {
                    timeSpan.SetWarmup(c);
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'x':    //completion routines
            timeSpan.SetCompletionRoutines(true);
            break;

        case 'y':    //external synchronization
            switch (*(arg + 1))
            {

            case 's':
                _hEventStarted = CreateEvent(NULL, TRUE, FALSE, arg + 2);
                if (NULL == _hEventStarted)
                {
                    fprintf(stderr, "Error creating/opening start notification event: '%s'\n", arg + 2);
                    exit(1);    // TODO: this class shouldn't terminate the process
                }
                break;

            case 'f':
                _hEventFinished = CreateEvent(NULL, TRUE, FALSE, arg + 2);
                if (NULL == _hEventFinished)
                {
                    fprintf(stderr, "Error creating/opening finish notification event: '%s'\n", arg + 2);
                    exit(1);    // TODO: this class shouldn't terminate the process
                }
                break;

            case 'r':
                synch->hStartEvent = CreateEvent(NULL, TRUE, FALSE, arg + 2);
                if (NULL == synch->hStartEvent)
                {
                    fprintf(stderr, "Error creating/opening wait-for-start event: '%s'\n", arg + 2);
                    exit(1);    // TODO: this class shouldn't terminate the process
                }
                break;

            case 'p':
                synch->hStopEvent = CreateEvent(NULL, TRUE, FALSE, arg + 2);
                if (NULL == synch->hStopEvent)
                {
                    fprintf(stderr, "Error creating/opening force-stop event: '%s'\n", arg + 2);
                    exit(1);    // TODO: this class shouldn't terminate the process
                }
                break;

            case 'e':
                {
                    HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, arg + 2);
                    if (NULL == hEvent)
                    {
                        fprintf(stderr, "Error opening event '%s'\n", arg + 2);
                        exit(1);    // TODO: this class shouldn't terminate the process
                    }
                    if (!SetEvent(hEvent))
                    {
                        fprintf(stderr, "Error setting event '%s'\n", arg + 2);
                        exit(1);    // TODO: this class shouldn't terminate the process
                    }
                    CloseHandle(hEvent);
                    printf("Succesfully set event: '%s'\n", arg + 2);
                    bExit = true;
                    break;
                }

            default:
                fError = true;
            }

        case 'z':    //random seed
            if (*(arg + 1) == '\0')
            {
                timeSpan.SetRandSeed((ULONG)GetTickCount64());
            }
            else
            {
                int c = atoi(arg + 1);
                if (c >= 0)
                {
                    timeSpan.SetRandSeed(c);
                }
                else
                {
                    fError = true;
                }
            }
            break;

        case 'Z':    //zero write buffers
            if (*(arg + 1) == '\0')
            {
                for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                {
                    i->SetZeroWriteBuffers(true);
                }
            }
            else
            {
                UINT64 cb = 0;
                string sPath;
                if (_GetRandomDataWriteBufferData(string(arg + 1), cb, sPath) && (cb > 0))
                {
                    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
                    {
                        i->SetRandomDataWriteBufferSize(cb);
                        i->SetRandomDataWriteBufferSourcePath(sPath);
                    }
                }
                else
                {
                    fprintf(stderr, "Invalid size passed to -Z\n");
                    fError = true;
                }
            }
            break;

        default:
            fprintf(stderr, "Invalid option: '%s'\n", arg);
            exit(1);                    // TODO: this class shouldn't terminate the process
        }

        if (fError)
        {
            fprintf(stderr, "Incorrectly provided option: '%s'\n", arg);
            exit(1);                    // TODO: this class shouldn't terminate the process
        }

        --nParamCnt;
        ++args;
    }

    //
    // exit if a user specified an action which was already satisfied and doesn't require running test
    //
    if (bExit)
    {
        printf("Now exiting...\n");
        exit(1);                        // TODO: this class shouldn't terminate the process
    }

    if (vTargets.size() < 1)
    {
        fprintf(stderr, "You need to provide at least one filename\n");
        return false;
    }

    for (auto i = vTargets.begin(); i != vTargets.end(); i++)
    {
        timeSpan.AddTarget(*i);
    }
    pProfile->AddTimeSpan(timeSpan);

    return true;
}