/*=============================================================================
	CALatencyLog.cpp

	$Log: CALatencyLog.cpp,v $
	Revision 1.4  2004/12/12 22:32:18  jcm10
	update to Tiger latency code
	
	Revision 1.3  2003/10/23 00:03:25  bills
	some tweaks
	
	Revision 1.2  2002/07/13 01:42:31  jcm10
	make the latency logs available via properties
	
	Revision 1.1  2002/07/11 23:36:21  jcm10
	first checked in
	
	Revision 0.0  Thu Jul 11 2002 15:51:46 US/Pacific  moorf
	Created
		
	$NoKeywords: $
=============================================================================*/

//=============================================================================
//	Includes
//=============================================================================

#include "CALatencyLog.h"
#include "CADebugMacros.h"
#include "CAException.h"
#include "CAHostTimeBase.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

//	routines from latency.c
#if Panther_LatencyLog
extern "C" void initialize();
extern "C" void sample_sc(uint64_t start, uint64_t stop, char *binPointer);
#else
extern "C" void		InitializeLatencyTracing(const char* inLogFile);
extern "C" void		TeardownLatencyTracing();
extern "C" FILE*	GetLatencyLogFile();
extern "C" void		SetLatencyLogFile(FILE* inLogFile);
extern "C" void		sample_sc(uint64_t start, uint64_t stop);
#endif

//=============================================================================
//	CALatencyLog
//=============================================================================

CALatencyLog::CALatencyLog(const char* inLogFileName, const char* inLogFileExtension)
{
	mIsRoot = CanUse();
	Assert(mIsRoot, "CALatencyLog::CALatencyLog: have to be root to use");
	
#if Panther_LatencyLog
	memset(mBuffer, 0, kLatencyBufferSize);
	strcpy(mLogFileName, inLogFileName);
	strcpy(mLogFileExtension, inLogFileExtension);
	
	if(mIsRoot)
	{
		initialize();
	}
#else
	BuildFileName(inLogFileName, inLogFileExtension, mLogFileName);
	
	if(mIsRoot)
	{
		InitializeLatencyTracing(mLogFileName);
	}
#endif
}

CALatencyLog::~CALatencyLog()
{
#if !Panther_LatencyLog
	if(mIsRoot)
	{
		TeardownLatencyTracing();
	}
#endif
}

void	CALatencyLog::Capture(UInt64 inStartTime, UInt64 inEndTime, bool inWriteToFile, const char* header)
{
	if(mIsRoot)
	{
#if Panther_LatencyLog
		sample_sc(inStartTime, inEndTime, mBuffer);
		
		if(inWriteToFile)
		{
			char	theLogFileName[PATH_MAX];
			BuildFileName(mLogFileName, mLogFileExtension, theLogFileName);
			
			DebugMessageN3("Capturing latency log from %fmics to %fmics into \"%s\"\n", CAHostTimeBase::ConvertToNanos(inStartTime) / 1000.0, CAHostTimeBase::ConvertToNanos(inEndTime) / 1000.0, theLogFileName);
			
			UInt32 theLogSize = strlen(mBuffer);
			
			//	open the file
			FILE* theFile = fopen(theLogFileName, "a+");
			if(theFile != NULL)
			{
				if (header)
					fwrite (header, 1, strlen (header), theFile);
					
				//	write the data at the end
				fwrite(mBuffer, 1, theLogSize, theFile);
								
				//	close the file
				fclose(theFile);
			}
		}
#else
		FILE* theLogFile = NULL;
		FILE* theSavedLogFile = NULL;
		
		if(inWriteToFile)
		{
			theLogFile = GetLatencyLogFile();
		}
		else
		{
			theLogFile = stdout;
			theSavedLogFile = GetLatencyLogFile();
			SetLatencyLogFile(stdout);
		}
		
		if(header != NULL)
		{
			fprintf(theLogFile, "%s", header);
		}
		
		sample_sc(inStartTime, inEndTime);
		
		if(theSavedLogFile != NULL)
		{
			SetLatencyLogFile(theSavedLogFile);
		}
#endif
	}
	else
	{
		DebugMessage("CALatencyLog::Capture: must be root to use.");
	}
}

#if Panther_LatencyLog
void	CALatencyLog::GetLog(char* outLog, UInt32& ioLogSize) const
{
	if(mIsRoot)
	{
		UInt32 theLogSize = strlen(mBuffer) + 1;
		
		if(theLogSize < ioLogSize)
		{
			ioLogSize = theLogSize;
		}
		
		strncpy(outLog, mBuffer, ioLogSize);
	}
	else
	{
		DebugMessage("CALatencyLog::Capture: must be root to use.");
	}
}
	
UInt32	CALatencyLog::GetLogSize() const
{
	UInt32 theAnswer = 0;
	
	if(mIsRoot)
	{
		theAnswer = strlen(mBuffer) + 1;
	}
	else
	{
		DebugMessage("CALatencyLog::Capture: must be root to use.");
	}
	
	return theAnswer;
}
#endif

void	CALatencyLog::BuildFileName(const char* inRoot, const char* inExtension, char* outFileName)
{
	sprintf(outFileName, "%s%s", inRoot, inExtension);
	
	struct stat	statbuf;
	if(stat(outFileName, &statbuf) == 0)
	{
		UInt32 theFileNumber = 1;
		while(stat(outFileName, &statbuf) == 0)
		{
			sprintf(outFileName, "%s-%ld%s", inRoot, theFileNumber, inExtension);
			++theFileNumber;
		}
	}
	
}
