sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include "logservcli.h"
sl@0: 
sl@0: // System includes
sl@0: #include <e32math.h>
sl@0: #include <s32mem.h>
sl@0: 
sl@0: // User includes
sl@0: #include "LogServShared.h"
sl@0: 
sl@0: static TInt StartServer()
sl@0: //
sl@0: // Start the server process/thread which lives in an EPOCEXE object
sl@0: //
sl@0: 	{
sl@0: 	const TUidType serverUid(KNullUid,KNullUid,KServerUid3);
sl@0: 
sl@0: 	//
sl@0: 	// EPOC is easy, we just create a new server process. Simultaneous launching
sl@0: 	// of two such processes should be detected when the second one attempts to
sl@0: 	// create the server object, failing with KErrAlreadyExists.
sl@0: 	//
sl@0: 	RProcess server;
sl@0: 	TInt r=server.Create(KLogServerName,KNullDesC,serverUid);
sl@0: 	if (r == KErrNone)
sl@0: 		server.SetPriority(EPriorityForeground);
sl@0: 		
sl@0: 	if (r!=KErrNone)
sl@0: 		return r;
sl@0: 	
sl@0: 	TRequestStatus stat;
sl@0: 	server.Rendezvous(stat);
sl@0: 	if (stat!=KRequestPending)
sl@0: 		server.Kill(0);		// abort startup
sl@0: 	else
sl@0: 		server.Resume();	// logon OK - start the server
sl@0: 	User::WaitForRequest(stat);		// wait for start or death
sl@0: 	// we can't use the 'exit reason' if the server panicked as this
sl@0: 	// is the panic 'reason' and may be '0' which cannot be distinguished
sl@0: 	// from KErrNone
sl@0: 	r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
sl@0: 	server.Close();
sl@0: 	return r;
sl@0: 
sl@0: 	}
sl@0: 
sl@0: // Initialise the operation and view ids
sl@0: RLogSession::RLogSession()
sl@0: : iOperationId(KLogNullOperationId + 1), iViewId(KLogNullViewId + 1)
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: TInt RLogSession::Connect()
sl@0: //
sl@0: // Connect to the server, attempting to start it if necessary
sl@0: //
sl@0: 	{
sl@0: 	TInt retry=2;
sl@0: 	for (;;)
sl@0: 		{
sl@0: 		TInt r=CreateSession(KLogServerFullName,TVersion(0,0,0));
sl@0: 		if (r!=KErrNotFound && r!=KErrServerTerminated)
sl@0: 			return r;
sl@0: 		if (--retry==0)
sl@0: 			return r;
sl@0: 		r=StartServer();
sl@0: 		if (r!=KErrNone && r!=KErrAlreadyExists)
sl@0: 			return r;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void RLogSession::Send(TInt aType, const TIpcArgs& aArgs, TRequestStatus& aStatus) const
sl@0: 	{
sl@0: 	SendWithRetryAsync(aType, aArgs, aStatus);
sl@0: 	}
sl@0: 
sl@0: TInt RLogSession::Send(TInt aType, const TIpcArgs& aArgs) const
sl@0: 	{
sl@0: 	return SendWithRetry(aType, aArgs);
sl@0: 	}
sl@0: 
sl@0: TInt RLogSession::SendWithRetry(TInt aType, const TIpcArgs& aParam) const
sl@0: 	{
sl@0: 	TInt ret = SendReceive(aType, aParam);
sl@0: 	if (ret < KErrNone)
sl@0: 		{
sl@0: 		if(ret == KErrServerTerminated || ret == KErrNotFound)
sl@0: 			{
sl@0: 			// Try to reconnect
sl@0: 			const_cast<RLogSession&>(*this).Close();
sl@0: 			ret = const_cast<RLogSession&>(*this).Connect();
sl@0: 			if(ret == KErrNone)
sl@0: 				{
sl@0: 				// Try to resend
sl@0: 				ret = SendReceive(aType, aParam);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	return ret;
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void RLogSession::SendWithRetryAsync(TInt aType, const TIpcArgs& aParam, TRequestStatus& aStatus) const
sl@0: 	{
sl@0: 	SendReceive(aType, aParam, aStatus);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: #ifdef LOGGING_ENABLED
sl@0: 
sl@0: const TInt KLogEngLogBufferSize = 256;
sl@0: 
sl@0: void Log::New()
sl@0: 	{
sl@0: 	_LIT(KNewLogText, "===== NEW LOG =====");
sl@0: 	//
sl@0: 	RFileLogger logger;
sl@0: 	TInt ret=logger.Connect();
sl@0: 	if	(ret==KErrNone)
sl@0: 		{
sl@0: 		logger.CreateLog(KLogFolder, KLogFileName, EFileLoggingModeOverwrite);
sl@0: 		logger.Write(KNewLogText);
sl@0: 		}
sl@0: 	logger.Close();
sl@0: 	}
sl@0: 
sl@0: void Log::Write(const TDesC& aText)
sl@0: 	{
sl@0: 	PruneLogFile();
sl@0: 
sl@0: 	RFileLogger logger;
sl@0: 	TInt ret=logger.Connect();
sl@0: 	if (ret==KErrNone)
sl@0: 		{
sl@0: 		logger.SetDateAndTime(EFalse,EFalse);
sl@0: 		logger.CreateLog(KLogFolder, KLogFileName,EFileLoggingModeAppend);
sl@0: 		TBuf<KLogEngLogBufferSize> buf;
sl@0: 		
sl@0: 		// The debug log uses hometime rather than UTC for its timestamps. This is
sl@0: 		// purely a debugging aid.
sl@0: 		TTime now;
sl@0: 		now.HomeTime();
sl@0: 		
sl@0: 		TDateTime dateTime;
sl@0: 		dateTime = now.DateTime();
sl@0: 		buf.Format(KTimeFormat,dateTime.Hour(),dateTime.Minute(),dateTime.Second(),dateTime.MicroSecond());
sl@0: 		buf.AppendFormat(KTextFormat,&aText);
sl@0: 
sl@0: 		logger.Write(buf);
sl@0: 		}
sl@0: 
sl@0: 	logger.Close();
sl@0: 	}
sl@0: 
sl@0: void Log::WriteFormat(TRefByValue<const TDesC> aFmt,...)
sl@0: 	{
sl@0:     VA_LIST list;
sl@0:     VA_START(list,aFmt);
sl@0: 
sl@0: 	PruneLogFile();
sl@0: 
sl@0: 	TBuf<2*KLogEngLogBufferSize> buf;
sl@0: 	buf.SetMax();
sl@0: 	buf.FillZ();
sl@0: 	
sl@0: 	// The debug log uses hometime rather than UTC for its timestamps. This is
sl@0: 	// purely a debugging aid.
sl@0: 	TTime now;
sl@0: 	now.HomeTime();
sl@0: 	
sl@0: 	TDateTime dateTime;
sl@0: 	dateTime = now.DateTime();
sl@0: 	buf.Format(KTimeFormat,dateTime.Hour(),dateTime.Minute(),dateTime.Second(),dateTime.MicroSecond());
sl@0: 	buf.AppendFormatList(aFmt, list );
sl@0: 
sl@0: 	RFileLogger logger;
sl@0: 	TInt ret=logger.Connect();
sl@0: 	if (ret==KErrNone)
sl@0: 		{
sl@0: 		logger.SetDateAndTime(EFalse,EFalse);
sl@0: 		logger.CreateLog(KLogFolder, KLogFileName,EFileLoggingModeAppend);
sl@0: 		logger.Write(buf);
sl@0: 		}
sl@0: 
sl@0: 	logger.Close();
sl@0: 	}
sl@0: 
sl@0: void Log::PruneLogFile()
sl@0: 	{
sl@0: 	const TInt KMaxLogSize = 1024 * 500;
sl@0: 	//
sl@0: 	_LIT(KBaseFolder, "_:\\Logs\\");
sl@0: 	TFileName fileName(KBaseFolder);
sl@0: 	fileName[0] = 'A' + static_cast<TInt>(RFs::GetSystemDrive());
sl@0: 	fileName.Append(KLogFolder);
sl@0: 	fileName.Append(KPathDelimiter);
sl@0: 	fileName.Append(KLogFileName);
sl@0: 	//
sl@0: 	RFs fsSession;
sl@0: 	if	(fsSession.Connect() == KErrNone)
sl@0: 		{
sl@0: 		TEntry entry;
sl@0: 		if	(fsSession.Entry(fileName, entry) == KErrNone)
sl@0: 			{
sl@0: 			// Check size and delete if its too big
sl@0: 			if (entry.iSize >= KMaxLogSize)
sl@0: 				{
sl@0: 				TInt fileDeleteErr=fsSession.Delete(fileName); 
sl@0: 
sl@0: 				// If a debug build - record error
sl@0: 				#ifdef _DEBUG
sl@0: 					if (fileDeleteErr != KErrNone)
sl@0: 						{
sl@0: 						RDebug::Print(_L("Log::PruneLogFile - Failed to delete file. Error = %d"), fileDeleteErr);
sl@0: 						}
sl@0: 				#else
sl@0: 					(void)fileDeleteErr;
sl@0: 				#endif
sl@0: 				}	
sl@0: 			}
sl@0: 		}
sl@0: 	fsSession.Close();
sl@0: 	}
sl@0: 
sl@0: #endif
sl@0: