testexecmdw/tef/tef/logger/src/server.cpp
branchRCL_3
changeset 3 9397a16b6eb8
parent 1 6edeef394eb7
equal deleted inserted replaced
1:6edeef394eb7 3:9397a16b6eb8
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * Main log server engine.
       
    16 * Process log requests from multiple clients simultaneously.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 /**
       
    23  @file server.cpp
       
    24 */
       
    25 #include "server.h"
       
    26 
       
    27 const TInt KLowMemBufLength = 128;
       
    28 
       
    29 CLogServer* CLogServer::NewL()
       
    30 /**
       
    31  * @return - Instance of the log server
       
    32  */
       
    33 	{
       
    34 	CLogServer * server = new (ELeave) CLogServer();
       
    35 	CleanupStack::PushL(server);
       
    36 	server->ConstructL();
       
    37 	// CServer base class call
       
    38 	server->StartL(KTestExecuteLogServerName);
       
    39 	CleanupStack::Pop(server);
       
    40 	return server;
       
    41 	}
       
    42 
       
    43 void CLogServer::ConstructL()
       
    44 /**
       
    45  * Second phase construction
       
    46  */
       
    47 	{
       
    48 	User::LeaveIfError(Fs().Connect());
       
    49 	}
       
    50 
       
    51 
       
    52 CLogServer::CLogServer() : CServer2(EPriorityStandard,ESharableSessions)
       
    53 /**
       
    54  * Constructor
       
    55  */
       
    56 	{
       
    57 	}
       
    58 
       
    59 CLogServer::~CLogServer()
       
    60 /**
       
    61  * Destructor
       
    62  */
       
    63 	{
       
    64 	// Close the array of control structures
       
    65 	LogControl().Close();
       
    66 	Fs().Close();
       
    67 	}
       
    68 
       
    69 
       
    70 CSession2* CLogServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const
       
    71 /**
       
    72  * @param RMessage - RMessage for the session open
       
    73  */
       
    74 	{
       
    75 	// Just create the session
       
    76 	CLogSession* session = new (ELeave) CLogSession();
       
    77 	return session;
       
    78 	}
       
    79 
       
    80 void CLogServer::ControlComplete(CLogFileControl& aControl)
       
    81 /**
       
    82  * @param aControl - Logfile control class reference
       
    83  *
       
    84  * Checks to see if this control session can be removed 
       
    85  */
       
    86 	{
       
    87 	// Check session count and the data buffers on the queue 
       
    88 	if(aControl.SessionCount() || !aControl.QueueEmpty())
       
    89 		return;
       
    90 
       
    91 	// There are no subsessions mapped to the logfile control class and
       
    92 	// no data buffers on its write queue
       
    93 	// Loop through the server's control array and remove it then delete it
       
    94 	TInt i;
       
    95 	for(i=0;i<LogControl().Count();i++)
       
    96 		{
       
    97 		if(&aControl == LogControl()[i])
       
    98 			{
       
    99 			// Done
       
   100 			LogControl().Remove(i);
       
   101 			delete &aControl;
       
   102 			break;
       
   103 			}
       
   104 		}
       
   105 	// If it's the last one then exit the server
       
   106 	if(!LogControl().Count())
       
   107 		CActiveScheduler::Stop();
       
   108 	}
       
   109 
       
   110 
       
   111 ///////
       
   112 
       
   113 CLogSession::CLogSession()
       
   114 /**
       
   115  * Constructor
       
   116  */
       
   117 	{
       
   118 	}
       
   119 
       
   120 CLogSession::~CLogSession()
       
   121 /**
       
   122  * Destructor
       
   123  */
       
   124 	{
       
   125 	// Check for null
       
   126 	// Session close without a createlog call leaves iControl null
       
   127 	if(!iControl)
       
   128 		return;
       
   129 	// A logfile control structure can have multiple server sessions
       
   130 	// decrement its server session count
       
   131 	iControl->RemoveSession();
       
   132 	CLogServer* p=(CLogServer*) Server();
       
   133 	// Shuts Down the server if this is the last open session
       
   134 	p->ControlComplete(*iControl);
       
   135 	}
       
   136 
       
   137 void CLogSession::ServiceL(const RMessage2& aMessage)
       
   138 /**
       
   139  * @param aMessage - Function and data for the session
       
   140  */
       
   141 	{
       
   142 	switch(aMessage.Function())
       
   143 		{
       
   144 		// API CreateLog() call
       
   145 		case RTestExecuteLogServ::ECreateLog :
       
   146 			{
       
   147 			// Sanity check to make sure it's not been called multiple times
       
   148 			if(iControl)
       
   149 				{
       
   150 				aMessage.Complete(KErrInUse);
       
   151 				break;
       
   152 				}
       
   153 			// Get the filepath
       
   154 			// size policed on the client side
       
   155 			TBuf<KMaxTestExecuteLogFilePath> logFilePath;
       
   156 			// Read it
       
   157 			aMessage.ReadL(0,logFilePath);
       
   158 			// Get the log mode in the second argument
       
   159 			RTestExecuteLogServ::TLogMode logMode;
       
   160 			logMode = (RTestExecuteLogServ::TLogMode)aMessage.Int1();
       
   161 			// Get a pointer to the parent server
       
   162 			CLogServer* server=(CLogServer*) Server();
       
   163 			// For compare's convert the whole path to lower case
       
   164 			logFilePath.LowerCase();
       
   165 			// Get rid of leading and trailing spaces.
       
   166 			logFilePath.Trim();
       
   167 			// Loop the through the server's logfile control class list
       
   168 			// to see if there's a match.
       
   169 			TInt i;
       
   170 			for(i=0;i<server->LogControl().Count();i++)
       
   171 				{
       
   172 				if(server->LogControl()[i]->LogFile() == logFilePath)
       
   173 					// This file's already in open so we don't have to open it
       
   174 					break;
       
   175 				}
       
   176 			TInt err = KErrNone;
       
   177 			// Check the count
       
   178 			if(i < server->LogControl().Count())
       
   179 				// Map this session to an existing logfile control class in the list
       
   180 				iControl = server->LogControl()[i];
       
   181 			else
       
   182 				{
       
   183 				// Create a new logfile control class
       
   184 				// creates/opens the logfile
       
   185 				TRAP(err,iControl = CLogFileControl::NewL(*server,logFilePath,logMode));
       
   186 				if(!err)
       
   187 					// Append it to the logfile control class list
       
   188 					server->LogControl().Append(iControl);
       
   189 				}
       
   190 			if(!err)
       
   191 				// Increment its session count
       
   192 				iControl->AddSession();
       
   193 			aMessage.Complete(err);
       
   194 			}
       
   195 			break;
       
   196 		// One of the API write calls
       
   197 		case RTestExecuteLogServ::EWriteLog :
       
   198 			{
       
   199 			// Sanity check
       
   200 			if(!iControl)
       
   201 				{
       
   202 				aMessage.Complete(KErrNotFound);
       
   203 				break;
       
   204 				}
       
   205 			// Data can be any size
       
   206 			// Get the length from second argument
       
   207 			TInt bufferLength = aMessage.Int1();
       
   208 			// Get a heap buffer of the right size
       
   209 			HBufC8* buffer = NULL;
       
   210 			TRAPD(err, buffer = HBufC8::NewL(bufferLength));
       
   211 			if (KErrNoMemory == err)
       
   212 				{
       
   213 				// If the buffer length is bigger than 128 and allocation failed, try to allocate
       
   214 				// 128 bytes and set it the low memory information.
       
   215 				if (bufferLength > KLowMemBufLength)  
       
   216 					{
       
   217 					HBufC8* buf = HBufC8::NewL(KLowMemBufLength);
       
   218 					CleanupStack::PushL(buf);
       
   219 					TPtr8 ptr = buf->Des();
       
   220 					ptr.Copy(KLoggerNotEnoughMemory8);
       
   221 					CLogBuffer* logBuffer = new (ELeave) CLogBuffer(*buf);
       
   222 					CleanupStack::Pop(buf);
       
   223 					iControl->AddLogBuffer(*logBuffer);
       
   224 					}
       
   225 				}
       
   226 			else
       
   227 				{
       
   228 				CleanupStack::PushL(buffer);
       
   229 				TPtr8 ptr(buffer->Des());
       
   230 				// read the data
       
   231 				aMessage.ReadL(0,ptr);			
       
   232 				// Get a buffer control class contructed with the heap data
       
   233 				// takes ownership
       
   234 				CLogBuffer* logBuffer = new (ELeave) CLogBuffer(*buffer);
       
   235 				CleanupStack::Pop(buffer);
       
   236 				// Add it to the logfile control class buffer queue
       
   237 				iControl->AddLogBuffer(*logBuffer);
       
   238 				}
       
   239 			if(!iControl->IsActive())
       
   240 				// AO is idle, kick into life
       
   241 				iControl->Kick();
       
   242 			aMessage.Complete(KErrNone);
       
   243 			}
       
   244 			break;
       
   245 
       
   246 		default:
       
   247 			break;
       
   248 		}
       
   249 	}
       
   250 
       
   251 ///////
       
   252 
       
   253 CLogFileControl* CLogFileControl::NewL(CLogServer& aParent, const TDesC& aLogFilePath,RTestExecuteLogServ::TLogMode aMode)
       
   254 /**
       
   255  * @param aParent - Server reference for callback
       
   256  * @param aLogFilePath - Full path and filename of the logfile
       
   257  * @param aMode - Overwrite or Append
       
   258  *
       
   259  * First phase construction for logfile control class
       
   260  */
       
   261 	{
       
   262 	CLogFileControl* self = new (ELeave) CLogFileControl(aParent,aLogFilePath);
       
   263 	self->ConstructL(aMode);
       
   264 	return self;
       
   265 	}
       
   266 
       
   267 CLogFileControl::CLogFileControl(CLogServer& aParent,const TDesC& aLogFilePath) :
       
   268 	iParent(aParent),
       
   269 	iLogFileName(aLogFilePath),
       
   270 	iTransmitted(EFalse)
       
   271 /**
       
   272  * @param aParent - Server reference for callback
       
   273  * @param aLogFilePath - Full path and filename of the logfile
       
   274  *
       
   275  * Constructor - Safe initialisation
       
   276  */
       
   277 	{
       
   278 	iQueue.SetOffset(CLogBuffer::LinkOffset());
       
   279 	}
       
   280 
       
   281 void CLogFileControl::ConstructL(RTestExecuteLogServ::TLogMode aMode)
       
   282 /**
       
   283  * @param aMode - Overwrite or Append
       
   284  *
       
   285  * Second phase construction - Create or open the logfile
       
   286  */
       
   287 	{
       
   288 	if(aMode == RTestExecuteLogServ::ELogModeOverWrite)
       
   289 		// In overwrite mode replace
       
   290 		User::LeaveIfError(iLogFile.Replace(iParent.Fs(),iLogFileName,EFileWrite|EFileShareAny));
       
   291 	else
       
   292 		{
       
   293 		// For append try open then replace
       
   294 		TInt err = iLogFile.Open(iParent.Fs(),iLogFileName,EFileWrite|EFileShareAny);
       
   295 		if(err != KErrNone)
       
   296 			// Bomb out if replace fails
       
   297 			User::LeaveIfError(iLogFile.Replace(iParent.Fs(),iLogFileName,EFileWrite|EFileShareAny));
       
   298 		else
       
   299 			{
       
   300 			// Open worked. Position at EOF
       
   301 			TInt pos;
       
   302 			User::LeaveIfError(iLogFile.Seek(ESeekEnd,pos));
       
   303 			}
       
   304 		}
       
   305 	}
       
   306 
       
   307 CLogFileControl::~CLogFileControl()
       
   308 /**
       
   309  * Destructor
       
   310  * The server maintains a list of these classes and will not destruct one if there
       
   311  * is data on its queue
       
   312  * Destructor just closes the file handle.
       
   313  */
       
   314 	{
       
   315 	iLogFile.Close();
       
   316 	}
       
   317 
       
   318 void CLogFileControl::RunL()
       
   319 /**
       
   320  * Main File writing pump
       
   321  * Called on write completion or Kick() by the session that accepts the data
       
   322  */
       
   323 	{
       
   324 #if (defined _DEBUG)
       
   325 	_LIT(KPanic,"LogEng RunL()");
       
   326 #endif
       
   327 	__ASSERT_DEBUG(iStatus.Int() == KErrNone,User::Panic(KPanic,iStatus.Int()));
       
   328 	// Check to see if this is the result of write completion
       
   329 	if(iTransmitted)
       
   330 		{
       
   331 		// Write completed
       
   332 		// Remove the buffer at the head of the queue and free it
       
   333 		CLogBuffer* buffer = iQueue.First();
       
   334 		iQueue.Remove(*buffer);
       
   335 		delete buffer;
       
   336 		}
       
   337 	// Check to see if there's more on the queue
       
   338 	if(!iQueue.IsEmpty())
       
   339 		{
       
   340 		// There is so write the head of the queue
       
   341 		CLogBuffer* buffer = iQueue.First();	
       
   342 		SetActive();
       
   343 		// Set the flag to say we've transmitted
       
   344 		iTransmitted = ETrue;
       
   345 		iLogFile.Write(buffer->Buf(),iStatus);
       
   346 		iLogFile.Flush();
       
   347 		}
       
   348 	else
       
   349 		{
       
   350 		// Nothing on the queue
       
   351 		iTransmitted = EFalse;
       
   352 		// Call into the server to check if this resource can be freed
       
   353 		iParent.ControlComplete(*this);
       
   354 		}
       
   355 	}
       
   356 
       
   357 ///////
       
   358 CLogBuffer::CLogBuffer(HBufC8& aLogBuffer) : iLogBuffer(aLogBuffer)
       
   359 /**
       
   360  * @param aLogBuffer - Heap descriptor. This class takes ownership
       
   361  * Constructor
       
   362  */
       
   363 	{
       
   364 	}
       
   365 
       
   366 CLogBuffer::~CLogBuffer()
       
   367 /**
       
   368  * Destructor
       
   369  * This class owns a heap buffer so just free it
       
   370  */
       
   371 	{
       
   372 	delete &iLogBuffer;
       
   373 	}