os/persistentdata/loggingservices/rfilelogger/Logger/Src/Server.Cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/loggingservices/rfilelogger/Logger/Src/Server.Cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,553 @@
     1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// Main log server engine.
    1.18 +// Process log requests from multiple clients simultaneously.
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +/**
    1.23 + @file server.cpp
    1.24 +*/
    1.25 +#include "server.h"
    1.26 +
    1.27 +CLogServer* CLogServer::NewL()
    1.28 +/**
    1.29 + * @return - Instance of the log server
    1.30 + */
    1.31 +	{
    1.32 +	CLogServer * server = new (ELeave) CLogServer();
    1.33 +	CleanupStack::PushL(server);
    1.34 +	server->ConstructL();
    1.35 +	// CServer base class call
    1.36 +	server->StartL(KFileLogrerServerName);
    1.37 +	CleanupStack::Pop(server);
    1.38 +	return server;
    1.39 +	}
    1.40 +
    1.41 +void CLogServer::ConstructL()
    1.42 +/**
    1.43 + * Second phase construction
    1.44 + */
    1.45 +	{
    1.46 +	User::LeaveIfError(Fs().Connect());
    1.47 +	}
    1.48 +
    1.49 +
    1.50 +CLogServer::CLogServer() : CServer2(EPriorityStandard,ESharableSessions)
    1.51 +/**
    1.52 + * Constructor
    1.53 + */
    1.54 +	{
    1.55 +	}
    1.56 +
    1.57 +CLogServer::~CLogServer()
    1.58 +/**
    1.59 + * Destructor
    1.60 + */
    1.61 +	{
    1.62 +	// Close the array of control structures
    1.63 +	LogControl().Close();
    1.64 +	Fs().Close();
    1.65 +	}
    1.66 +
    1.67 +
    1.68 +CSession2* CLogServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const
    1.69 +/**
    1.70 + * @param RMessage - RMessage for the session open
    1.71 + */
    1.72 +	{
    1.73 +	// Just create the session
    1.74 +	CLogSession* session = new (ELeave) CLogSession();
    1.75 +	return session;
    1.76 +	}
    1.77 +
    1.78 +void CLogServer::ControlComplete(CLogFileControl& aControl)
    1.79 +/**
    1.80 + * @param aControl - Logfile control class reference
    1.81 + *
    1.82 + * Checks to see if this control session can be removed 
    1.83 + */
    1.84 +	{
    1.85 +	// Check session count and the data buffers on the queue 
    1.86 +	if(aControl.SessionCount() || !aControl.QueueEmpty())
    1.87 +		return;
    1.88 +
    1.89 +	// There are no subsessions mapped to the logfile control class and
    1.90 +	// no data buffers on its write queue
    1.91 +	// Loop through the server's control array and remove it then delete it
    1.92 +	TInt i;
    1.93 +	for(i=0;i<LogControl().Count();i++)
    1.94 +		{
    1.95 +		if(&aControl == LogControl()[i])
    1.96 +			{
    1.97 +			// Done
    1.98 +			LogControl().Remove(i);
    1.99 +			delete &aControl;
   1.100 +			break;
   1.101 +			}
   1.102 +		}
   1.103 +	// If it's the last one then exit the server
   1.104 +	if(!LogControl().Count())
   1.105 +		CActiveScheduler::Stop();
   1.106 +	}
   1.107 +
   1.108 +
   1.109 +///////
   1.110 +
   1.111 +CLogSession::CLogSession()
   1.112 +/**
   1.113 + * Constructor
   1.114 + */
   1.115 +	{
   1.116 +	}
   1.117 +
   1.118 +CLogSession::~CLogSession()
   1.119 +/**
   1.120 + * Destructor
   1.121 + */
   1.122 +	{
   1.123 +	// Check for null
   1.124 +	// Session close without a createlog call leaves iControl null
   1.125 +	if(!iControl)
   1.126 +		return;
   1.127 +	// A logfile control structure can have multiple server sessions
   1.128 +	// decrement its server session count
   1.129 +	iControl->RemoveSession();
   1.130 +	CLogServer* p=(CLogServer*) Server();
   1.131 +	// Shuts Down the server if this is the last open session
   1.132 +	p->ControlComplete(*iControl);
   1.133 +	}
   1.134 +
   1.135 +void CLogSession::ServiceL(const RMessage2& aMessage)
   1.136 +/**
   1.137 + * @param aMessage - Function and data for the session
   1.138 + */
   1.139 +	{
   1.140 +	switch(aMessage.Function())
   1.141 +		{
   1.142 +		// API CreateLog() call
   1.143 +		case RFileFlogger::ECreateLog :
   1.144 +			{
   1.145 +			// Sanity check to make sure it's not been called multiple times
   1.146 +			if(iControl)
   1.147 +				{
   1.148 +				aMessage.Complete(KErrInUse);
   1.149 +				break;
   1.150 +				}
   1.151 +			// Get the filepath
   1.152 +			// size policed on the client side
   1.153 +			TBuf<KMaxLoggerFilePath> logFilePath;
   1.154 +			// Read it
   1.155 +			aMessage.ReadL(0,logFilePath);
   1.156 +			// Get the log mode in the second argument
   1.157 +			RFileFlogger::TLogMode logMode;
   1.158 +			logMode = (RFileFlogger::TLogMode)aMessage.Int1();
   1.159 +			// Get a pointer to the parent server
   1.160 +			CLogServer* server=(CLogServer*) Server();
   1.161 +			// For compare's convert the whole path to lower case
   1.162 +			logFilePath.LowerCase();
   1.163 +			// Get rid of leading and trailing spaces.
   1.164 +			logFilePath.Trim();
   1.165 +						
   1.166 +			// Loop the through the server's logfile control class list
   1.167 +			// to see if there's a match.
   1.168 +			TInt i;
   1.169 +			for(i=0;i<server->LogControl().Count();i++)
   1.170 +				{
   1.171 +				if(server->LogControl()[i]->LogFile() == logFilePath)
   1.172 +					// This file's already in open so we don't have to open it
   1.173 +					break;
   1.174 +				}
   1.175 +			TInt err = KErrNone;
   1.176 +			// Check the count
   1.177 +			if(i < server->LogControl().Count())
   1.178 +				// Map this session to an existing logfile control class in the list
   1.179 +				iControl = server->LogControl()[i];
   1.180 +			else
   1.181 +				{
   1.182 +				// Create a new logfile control class
   1.183 +				// creates/opens the logfile
   1.184 +				TRAP(err,iControl = CLogFileControl::NewL(*server,logFilePath,logMode));
   1.185 +				if(!err)
   1.186 +					{  // nancy
   1.187 +					// find out the type of output format and assign to this new created control
   1.188 +					TInt error = logFilePath.Find(_L(".xml"));
   1.189 +					if(error==KErrNotFound) iControl->SetLogType(CLogFileControl::ETxt);
   1.190 +					else iControl->SetLogType(CLogFileControl::EXml);					
   1.191 +					// end nancy
   1.192 +					// Append it to the logfile control class list
   1.193 +					server->LogControl().Append(iControl);					
   1.194 +					}
   1.195 +				}
   1.196 +			if(!err)
   1.197 +				// Increment its session count
   1.198 +				iControl->AddSession();
   1.199 +			aMessage.Complete(err);
   1.200 +			}
   1.201 +			break;
   1.202 +		// One of the API write calls
   1.203 +		case RFileFlogger::EWriteLog :
   1.204 +			{
   1.205 +			// Sanity check
   1.206 +			if(!iControl)
   1.207 +				{
   1.208 +				aMessage.Complete(KErrNotFound);
   1.209 +				break;
   1.210 +				}
   1.211 +			// Data can be any size
   1.212 +			// Get the length from second argument
   1.213 +			TInt bufferLength = aMessage.Int1();
   1.214 +			// Get a heap buffer of the right size
   1.215 +			HBufC8* buffer = HBufC8::NewLC(bufferLength);
   1.216 +			TPtr8 ptr(buffer->Des());
   1.217 +			// read the data
   1.218 +			aMessage.ReadL(0,ptr);			
   1.219 +			// Get a buffer control class contructed with the heap data
   1.220 +			// takes ownership
   1.221 +			CLogBuffer* logBuffer = new (ELeave) CLogBuffer(*buffer);
   1.222 +			CleanupStack::Pop(buffer);
   1.223 +			// Add it to the logfile control class buffer queue
   1.224 +			iControl->AddLogBuffer(*logBuffer);
   1.225 +			if(!iControl->IsActive())
   1.226 +				// AO is idle, kick into life
   1.227 +				iControl->Kick();
   1.228 +			aMessage.Complete(KErrNone);
   1.229 +			}
   1.230 +			break;
   1.231 +
   1.232 +		default:
   1.233 +			break;
   1.234 +		}
   1.235 +	}
   1.236 +
   1.237 +///////
   1.238 +
   1.239 +CLogFileControl* CLogFileControl::NewL(CLogServer& aParent, const TDesC& aLogFilePath,RFileFlogger::TLogMode aMode)
   1.240 +/**
   1.241 + * @param aParent - Server reference for callback
   1.242 + * @param aLogFilePath - Full path and filename of the logfile
   1.243 + * @param aMode - Overwrite or Append
   1.244 + *
   1.245 + * First phase construction for logfile control class
   1.246 + */
   1.247 +	{
   1.248 +	CLogFileControl* self = new (ELeave) CLogFileControl(aParent,aLogFilePath);
   1.249 +	CleanupStack::PushL(self);
   1.250 +	self->ConstructL(aMode);
   1.251 +	CleanupStack::Pop();
   1.252 +	return self;
   1.253 +	}
   1.254 +
   1.255 +CLogFileControl::CLogFileControl(CLogServer& aParent,const TDesC& aLogFilePath) :
   1.256 +	iParent(aParent),
   1.257 +	iLogFileName(aLogFilePath),
   1.258 +	iTransmitted(EFalse)
   1.259 +/**
   1.260 + * @param aParent - Server reference for callback
   1.261 + * @param aLogFilePath - Full path and filename of the logfile
   1.262 + *
   1.263 + * Constructor - Safe initialisation
   1.264 + */
   1.265 +	{
   1.266 +	iQueue.SetOffset(CLogBuffer::LinkOffset());
   1.267 +	}
   1.268 +
   1.269 +void CLogFileControl::ConstructL(RFileFlogger::TLogMode aMode)
   1.270 +/**
   1.271 + * @param aMode - Overwrite or Append
   1.272 + *
   1.273 + * Second phase construction - Create or open the logfile
   1.274 + */
   1.275 +	{
   1.276 +	if(aMode == RFileFlogger::ELogModeOverWrite)
   1.277 +		// In overwrite mode replace
   1.278 +		User::LeaveIfError(iLogFile.Replace(iParent.Fs(),iLogFileName,EFileWrite));
   1.279 +	else
   1.280 +		{
   1.281 +		// For append try open then replace
   1.282 +		TInt err = iLogFile.Open(iParent.Fs(),iLogFileName,EFileWrite);
   1.283 +		if(err != KErrNone)
   1.284 +			// Bomb out if replace fails
   1.285 +			User::LeaveIfError(iLogFile.Replace(iParent.Fs(),iLogFileName,EFileWrite));
   1.286 +		else
   1.287 +			{
   1.288 +			// Open worked. Position at EOF
   1.289 +			TInt pos;
   1.290 +			iLogFile.Size(pos);
   1.291 +			User::LeaveIfError(iLogFile.Seek(ESeekEnd,pos));
   1.292 +			}
   1.293 +		}
   1.294 +	}
   1.295 +
   1.296 +CLogFileControl::~CLogFileControl()
   1.297 +/**
   1.298 + * Destructor
   1.299 + * The server maintains a list of these classes and will not destruct one if there
   1.300 + * is data on its queue
   1.301 + * Destructor just closes the file handle.
   1.302 + */
   1.303 +	{
   1.304 +	iLogFile.Close();
   1.305 +	}
   1.306 +
   1.307 +void CLogFileControl::RunL()
   1.308 +/**
   1.309 + * Main File writing pump
   1.310 + * Called on write completion or Kick() by the session that accepts the data
   1.311 + */
   1.312 +	{
   1.313 +#if (defined _DEBUG)
   1.314 +	_LIT(KPanic,"LogEng RunL()");
   1.315 +#endif
   1.316 +	__ASSERT_DEBUG(iStatus.Int() == KErrNone,User::Panic(KPanic,iStatus.Int()));
   1.317 +	// Check to see if this is the result of write completion
   1.318 +	if(iTransmitted)
   1.319 +		{
   1.320 +		// Write completed
   1.321 +		// Remove the buffer at the head of the queue and free it
   1.322 +		CLogBuffer* buffer = iQueue.First();
   1.323 +		iQueue.Remove(*buffer);
   1.324 +		delete buffer;
   1.325 +		}
   1.326 +	// Check to see if there's more on the queue
   1.327 +	if(!iQueue.IsEmpty())
   1.328 +		{
   1.329 +		// There is so write the head of the queue
   1.330 +		CLogBuffer* buffer = iQueue.First();	
   1.331 +		SetActive();
   1.332 +		// Set the flag to say we've transmitted
   1.333 +		iTransmitted = ETrue;
   1.334 +
   1.335 +//  ------------------------------------
   1.336 +		if(iLogFormat==ETxt)  WriteTxt(buffer->Buf());
   1.337 +		else WriteXml(buffer->Buf());
   1.338 +		} 
   1.339 +	else
   1.340 +		{
   1.341 +		// Nothing on the queue
   1.342 +		iTransmitted = EFalse;
   1.343 +		// Call into the server to check if this resource can be freed
   1.344 +		iParent.ControlComplete(*this);
   1.345 +		}
   1.346 +	}
   1.347 +
   1.348 +void CLogFileControl::WriteXml(const TDesC8 &aDes)
   1.349 +/**
   1.350 + * @param aDes - send a aDes string in xml format to a log file
   1.351 + */
   1.352 +	{
   1.353 +/*--------- Maintaince Warning:  -----------------------------------
   1.354 +******* the fomat of below is sensible from client original format.  
   1.355 +******* Any change should match actual string formated from client. 
   1.356 +******* Double check the code on client side 
   1.357 +
   1.358 +* The current assumtion of format:
   1.359 +* First string values are seperated by sign " - " and extra pair of fields are
   1.360 +* seperated from main log message  by long unusual string "LogFieldsRequiredBeingAddedToAboveLogMessage"
   1.361 +* The \t used to seperate field name and field value and \r\n used to seperate
   1.362 +* each other from those pairs of field
   1.363 +* \t\t\t\t\t\t is used to end of whole string
   1.364 +--------------------------------------------------------------------------------*/
   1.365 +		_LIT8(KxmlHeader,"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n<LOGFILE>");
   1.366 +		//The order of variables:
   1.367 +		// time 		- aTime
   1.368 +		// Severity 	- aSeverity
   1.369 +		// Thread 		- aThread
   1.370 +		// Filename 	- aFilename
   1.371 +		// Linenumber 	- aLinenumber
   1.372 +		// Text 		- aText
   1.373 +		
   1.374 +		// Start of string retrive/deformating 
   1.375 +		HBufC8* pBuf1 = HBufC8::New(KMaxLoggerLineLength*2); //(aDes.Length()+200);
   1.376 +		if(!pBuf1)
   1.377 +			{
   1.378 +			return; // no memory 
   1.379 +			}
   1.380 +		TPtr8 aPtr(pBuf1->Des());  // used for searching
   1.381 +		TPtr8 alogbuf(pBuf1->Des());  //used for final log
   1.382 +		aPtr.Append(aDes);
   1.383 +		TPtrC8 SearchBuf;
   1.384 +		TInt aCount[8]; 
   1.385 +		aCount[0]=0;
   1.386 +		TInt posI(0);
   1.387 +
   1.388 +        // retrive log message:
   1.389 +		// Retrive common part of log message:
   1.390 +		TInt i=0;
   1.391 +		for(i=1; i<6; i++)
   1.392 +			{
   1.393 +			SearchBuf.Set(aPtr.Mid(posI));
   1.394 +			aCount[i]=SearchBuf.Find(KSeperation8)+posI;
   1.395 +			posI=aCount[i]+3;
   1.396 +			if(aCount[i]<aCount[i-1])	
   1.397 +                {
   1.398 +                delete pBuf1;
   1.399 +                return; // wrong format string from client
   1.400 +                }
   1.401 +			}
   1.402 +		// seperating common log message and extra log fields will be easy for future maintaince.
   1.403 +		TLogField8* alogField = new TLogField8[6];  // the common part of log message for both 
   1.404 +								  					// with and without extra log fields
   1.405 +		if(!alogField) 
   1.406 +            {
   1.407 +            delete pBuf1;
   1.408 +            return; // no memory
   1.409 +            }
   1.410 +
   1.411 +		TLogField8* extralogField=NULL; // only applied to extra log fields
   1.412 +
   1.413 +		TInt alength=0;  // a length of array of extra log fields
   1.414 +
   1.415 +		alogField[0].iLogTag8.Copy(_L8("TIME"));
   1.416 +		alogField[1].iLogTag8.Copy(_L8("SEVERITY"));
   1.417 +		alogField[2].iLogTag8.Copy(_L8("THREAD"));
   1.418 +		alogField[3].iLogTag8.Copy(_L8("FILENAME"));
   1.419 +		alogField[4].iLogTag8.Copy(_L8("LINENUMBER"));
   1.420 +		alogField[5].iLogTag8.Copy(_L8("TEXT"));
   1.421 +			
   1.422 +		alogField[0].iLogValue8.Copy(aPtr.Mid(aCount[0],aCount[1]-aCount[0]));
   1.423 +		for(i=1; i<5; i++)
   1.424 +			{
   1.425 +			alogField[i].iLogValue8.Copy(aPtr.Mid(aCount[i]+3,aCount[i+1]-aCount[i]-3));				
   1.426 +			}
   1.427 +
   1.428 +		SearchBuf.Set(aPtr.Mid(posI));
   1.429 +		aCount[6]=SearchBuf.Find(_L8("LogFieldsRequiredBeingAddedToAboveLogMessage"))+posI; 
   1.430 +		if(aCount[6]<posI)  // no addtional fields. Find return value is KErrNotFound or >0
   1.431 +			{
   1.432 +			alogField[5].iLogValue8.Copy(aPtr.Mid(aCount[5]+3,aDes.Length()-aCount[5]-5));
   1.433 +			}
   1.434 +		else
   1.435 +            {
   1.436 +			alogField[5].iLogValue8.Copy(aPtr.Mid(aCount[5]+3,aCount[6]-aCount[5]-5));
   1.437 +			posI=aCount[6]+45;  //45 is from the length of long string and a tab
   1.438 +			SearchBuf.Set(aPtr.Mid(posI));
   1.439 +			aCount[7]=SearchBuf.Find(_L8("\r\n"))+posI;
   1.440 +			TLex8 lex(aPtr.Mid(posI,aCount[7]-posI));  // get the length
   1.441 +			TInt err=lex.Val(alength); 
   1.442 +			if (err)
   1.443 +                alength=0; // ignor the extra log fields. Let the log go
   1.444 +
   1.445 +			// Retrive the extra log fields
   1.446 +			extralogField = new TLogField8[alength];
   1.447 +			if(!extralogField)
   1.448 +                {
   1.449 +                delete pBuf1; 
   1.450 +                return; // no memory
   1.451 +                }
   1.452 +			for(TInt i=0; i<alength; i++)
   1.453 +				{
   1.454 +				aCount[6]=aCount[7]+2;
   1.455 +				SearchBuf.Set(aPtr.Mid(aCount[6]));
   1.456 +				aCount[7]=SearchBuf.Find(_L8("\t"))+aCount[6];
   1.457 +				extralogField[i].iLogTag8.Copy(aPtr.Mid(aCount[6],aCount[7]-aCount[6]));
   1.458 +				aCount[6]=aCount[7]+1;
   1.459 +				SearchBuf.Set(aPtr.Mid(aCount[6]));
   1.460 +				aCount[7]=SearchBuf.Find(_L8("\r\n"))+aCount[6];
   1.461 +				extralogField[i].iLogValue8.Copy(aPtr.Mid(aCount[6],aCount[7]-aCount[6]));
   1.462 +				}
   1.463 +            }
   1.464 +		// Start to organize an XML format:
   1.465 +		TInt afileSize;
   1.466 +		_LIT(KLogMutex, "LoggingServerMutex");
   1.467 +		RMutex mutex;
   1.468 +		TInt r = mutex.CreateGlobal(KLogMutex);
   1.469 +		if(r==KErrAlreadyExists)
   1.470 +			r = mutex.OpenGlobal(KLogMutex);  
   1.471 +		
   1.472 +		if(!r)
   1.473 +            mutex.Wait(); // If still failed, let logging go without bother the mutex.
   1.474 +		iLogFile.Size(afileSize);
   1.475 +		if(afileSize<12) // 12 is from charters of "\r\n</LOGFILE>" 
   1.476 +					//It shoud happened once at the beginning of the file
   1.477 +					// such as overwrite mode
   1.478 +            {
   1.479 +			afileSize=12; // used for lock position
   1.480 +			alogbuf.Copy(KxmlHeader);
   1.481 +			}
   1.482 +		alogbuf.Append(_L8("\r\n<MESSAGE>\r\n"));
   1.483 +		for(TInt i=0; i<6; i++)
   1.484 +			{
   1.485 +			alogbuf.Append(_L8("  <"));
   1.486 +			alogbuf.Append(alogField[i].iLogTag8);
   1.487 +			alogbuf.Append(_L8(">"));
   1.488 +			alogbuf.Append(alogField[i].iLogValue8);
   1.489 +			alogbuf.Append(_L8("</"));
   1.490 +			alogbuf.Append(alogField[i].iLogTag8);
   1.491 +			alogbuf.Append(_L8(">\r\n"));				
   1.492 +			}
   1.493 +		for(TInt i=0; i<alength; i++)  
   1.494 +			{
   1.495 +			alogbuf.Append(_L8("  <"));
   1.496 +			alogbuf.Append(extralogField[i].iLogTag8);
   1.497 +			alogbuf.Append(_L8(">"));
   1.498 +			alogbuf.Append(extralogField[i].iLogValue8);
   1.499 +			alogbuf.Append(_L8("</"));
   1.500 +			alogbuf.Append(extralogField[i].iLogTag8);
   1.501 +			alogbuf.Append(_L8(">\r\n"));				
   1.502 +			}
   1.503 +		
   1.504 +		alogbuf.Append(_L8("</MESSAGE>"));
   1.505 +		alogbuf.Append(_L8("\r\n</LOGFILE>"));
   1.506 +		
   1.507 +		iLogFile.Write(afileSize-12, alogbuf,iStatus);
   1.508 +													
   1.509 +		if(!r)	
   1.510 +			{
   1.511 +			mutex.Signal();
   1.512 +			mutex.Close();				
   1.513 +			} 
   1.514 +
   1.515 +		if(extralogField)
   1.516 +            delete[] extralogField;
   1.517 +
   1.518 +		delete[] alogField;	
   1.519 +		delete pBuf1;
   1.520 +	}
   1.521 +
   1.522 +void CLogFileControl::WriteTxt(const TDesC8 &aDes)
   1.523 +/**
   1.524 + * @param aDes - send a aDes string in xml format to a log file
   1.525 + */
   1.526 +	{
   1.527 +/*--------- Maintaince Warning for aLogBuffer -----------------------------------
   1.528 +******* the fomat of below is sensible from client original format.  
   1.529 +******* Any change should match actual string formated from client. 
   1.530 +******* Double check the code on client side 
   1.531 +
   1.532 +* The current assumtion of format:
   1.533 +* First string values are seperated by sign " - " and extra pair of fields are
   1.534 +* seperated from main log message  by long unusual string "LogFieldsRequiredBeingAddedToAboveLogMessage"
   1.535 +* The \t used to seperate field name and field value and \r\n used to seperate
   1.536 +* each other from those pairs of field
   1.537 +--------------------------------------------------------------------------------*/
   1.538 +	iLogFile.Write(aDes,iStatus);
   1.539 +	}
   1.540 +///////
   1.541 +CLogBuffer::CLogBuffer(HBufC8& aLogBuffer) : iLogBuffer(aLogBuffer)
   1.542 +/**
   1.543 + * @param aLogBuffer - Heap descriptor. This class takes ownership
   1.544 + * Constructor
   1.545 + */
   1.546 +	{
   1.547 +	}
   1.548 +
   1.549 +CLogBuffer::~CLogBuffer()
   1.550 +/**
   1.551 + * Destructor
   1.552 + * This class owns a heap buffer so just free it
   1.553 + */
   1.554 +	{
   1.555 +	delete &iLogBuffer;
   1.556 +	}