lowlevellibsandfws/apputils/src/Baksrv.cpp
changeset 0 e4d67989cc36
child 44 97b0fb8a2cc2
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <baksrv.h>
       
    17 #include "Baksrvs.h"
       
    18 #include <babackup.h>
       
    19 #include <bafl/backup_std.h>
       
    20 #include <basched.h>
       
    21 #include <bsul/clientmessage.h>
       
    22 #include "patchdata.h"
       
    23 
       
    24 extern const BSUL::TClientMessageServerData KServerData;
       
    25 
       
    26 const TInt KBakServMaxOperationTimerLoops = 3; // Number of iterations for base operation timer
       
    27 
       
    28 _LIT(KPanic,"BackupServer");
       
    29 //
       
    30 // RMessage::Panic() also completes the message. This is:
       
    31 // (a) important for efficient cleanup within the kernel
       
    32 // (b) a problem if the message is completed a second time
       
    33 //
       
    34 void PanicClient(const RMessagePtr2& aMessage, TInt aPanic)
       
    35 	{
       
    36 	aMessage.Panic(KPanic,aPanic);
       
    37 	}
       
    38 
       
    39 
       
    40 //
       
    41 // class CShutdownServer
       
    42 //
       
    43 
       
    44 NONSHARABLE_CLASS(CShutdownServer) : public CTimer
       
    45 	{
       
    46 	enum {KMyShutdownDelay=0x2000000};	// approx 2s
       
    47 public:
       
    48 	inline CShutdownServer();
       
    49 	inline void ConstructL();
       
    50 	inline void Start();
       
    51 private:
       
    52 	void RunL();
       
    53 	};
       
    54 
       
    55 inline CShutdownServer::CShutdownServer()
       
    56 	:CTimer(-1)
       
    57 	{
       
    58 	CActiveScheduler::Add(this);
       
    59 	}
       
    60 
       
    61 inline void CShutdownServer::ConstructL()
       
    62 	{
       
    63 	CTimer::ConstructL();
       
    64 	}
       
    65 inline void CShutdownServer::Start()
       
    66 	{
       
    67 	After(KMyShutdownDelay);
       
    68 	}
       
    69 
       
    70 //
       
    71 // Initiate server exit when the timer expires
       
    72 //
       
    73 void CShutdownServer::RunL()
       
    74 	{
       
    75 	CActiveScheduler::Stop();
       
    76 	}
       
    77 
       
    78 
       
    79 //
       
    80 // class CBaServBackupScheduler
       
    81 //
       
    82 
       
    83 EXPORT_C CBaServBackupScheduler::CBaServBackupScheduler()
       
    84 {
       
    85 }
       
    86 
       
    87 EXPORT_C CBaServBackupScheduler::~CBaServBackupScheduler()
       
    88 {
       
    89 }
       
    90 
       
    91 /**
       
    92  *
       
    93  * Set the error handler to aErrorHandler to the current scheduler.
       
    94  *
       
    95  * @param     "CBaServBackupSession* aErrorHandler"
       
    96  *            The handler session.
       
    97  */
       
    98 EXPORT_C void CBaServBackupScheduler::SetErrorHandler(CBaServBackupSession* aErrorHandler)
       
    99 	{
       
   100 	iErrorHandler=aErrorHandler;
       
   101 	}
       
   102 
       
   103 /**
       
   104  *
       
   105  * Handles the error aError.
       
   106  *
       
   107  * @param     "TInt aError"
       
   108  *            The error.
       
   109  */
       
   110 EXPORT_C void CBaServBackupScheduler::Error(TInt aError) const
       
   111 	{
       
   112 	if (iErrorHandler)
       
   113 		{
       
   114 		iErrorHandler->HandleError(aError);
       
   115 		}
       
   116 	else if (aError!=KLeaveWithoutAlert)
       
   117 		{
       
   118 		// Handling the in this way implies that ServiceL should not leave.
       
   119 		CActiveScheduler::Error(aError);
       
   120 		}
       
   121 	}
       
   122 
       
   123 /**
       
   124 Class CBaServBackupSession::CReRegistrationTimer
       
   125 */
       
   126 NONSHARABLE_CLASS(CBaServBackupSession::CReRegistrationTimer) : public CPeriodic
       
   127 {
       
   128 	public:
       
   129 		static CReRegistrationTimer* NewL(TInt aPriority);
       
   130 		static TInt ReRegistrationTimerCallBack(TAny* aPtr);
       
   131 		
       
   132 	protected:
       
   133 		TInt RunError(TInt aError);
       
   134 		
       
   135 	private:
       
   136 		CReRegistrationTimer(TInt aPriority);
       
   137 		void HandleReRegistrationTimerCallBack();
       
   138 
       
   139     public:
       
   140 		CBaBackupServer* iBackupServer;
       
   141 };
       
   142 
       
   143 /**
       
   144 Class CBaBackupServer::CBaServCloseAllOperationTimer
       
   145 */
       
   146 
       
   147 NONSHARABLE_CLASS(CBaBackupServer::CBaServCloseAllOperationTimer): public CPeriodic
       
   148 {
       
   149 	public:
       
   150 	    static CBaServCloseAllOperationTimer* NewL(CBaBackupServer* aBackupServer);
       
   151 	   void ConstructL(CBaBackupServer* aBackupServer);
       
   152 	   ~CBaServCloseAllOperationTimer();
       
   153 	   void SetMessage(const RMessagePtr2& aPtr);
       
   154 	   RMessagePtr2 Message();
       
   155 	   TInt GetOperationCount();
       
   156 	   void SetOperationCount(TInt aCount);
       
   157 	   static TInt OperationTimerCallBack(TAny* aPtr);
       
   158 	protected:
       
   159 	   TInt RunError(TInt aError);
       
   160 	private:
       
   161 	   void HandleOperationTimerCallBack();
       
   162 	   CBaServCloseAllOperationTimer();
       
   163 	private:
       
   164 	   RMessagePtr2 iCloseAllFilesMessage;
       
   165 	   TInt16 iOperationCount;
       
   166 	   CBaBackupServer* iBackupServer;
       
   167 };
       
   168 
       
   169 //
       
   170 // class CBaBackupServer
       
   171 //
       
   172 
       
   173 /**
       
   174  *
       
   175  * Returns a pointer to <code>CBaBackupServer</code> object.
       
   176  *
       
   177  * @return   "CBaBackupServer"
       
   178  *            A newly-constructed backup server object.
       
   179  */
       
   180 EXPORT_C CBaBackupServer* CBaBackupServer::NewL()
       
   181 	{ // static
       
   182 	CBaBackupServer* self=new(ELeave) CBaBackupServer(CActive::EPriorityStandard);
       
   183 	return self;
       
   184 	}
       
   185 
       
   186 /**
       
   187  *
       
   188  * Constructor.
       
   189  *
       
   190  * @param     "TInt aPriority"
       
   191  *            The active object priority.
       
   192  */
       
   193 EXPORT_C CBaBackupServer::CBaBackupServer(TInt aPriority)
       
   194 	: CServer2(aPriority)
       
   195 	{}
       
   196 /**
       
   197  *
       
   198  * Destructor.
       
   199  *
       
   200  */
       
   201 EXPORT_C CBaBackupServer::~CBaBackupServer()
       
   202 	{
       
   203 	TDblQueIter<CSession2> iter(iSessionIter);
       
   204 	iter.SetToFirst();
       
   205 
       
   206 	for (CSession2* session=iter++; session!=NULL; session=iter++)
       
   207 		{
       
   208 		delete session;
       
   209 		}
       
   210 	delete iShutdown;
       
   211 	delete iExtension;
       
   212 	delete iCloseAllFilesOperationTimer;
       
   213 	}
       
   214 
       
   215 /**
       
   216  *
       
   217  * Completes the server construction by adding the server to the active scheduler and creating
       
   218  * a <code>CShutdownServer</code> object.
       
   219  *
       
   220  */
       
   221 EXPORT_C void CBaBackupServer::ConstructL()
       
   222 	{
       
   223 	StartL(__BACKUP_SERVER_NAME_V2);
       
   224 	iExtension = new(ELeave) CBaBackupServerExt();
       
   225 	iShutdown = new (ELeave) CShutdownServer;
       
   226 	iShutdown->ConstructL();
       
   227 	// ensure that the server still exits even if the 1st client fails to connect
       
   228 	iShutdown->Start();
       
   229 	iRegisteredFilesCount = 0;
       
   230 	iCloseAllFilesOperationTimer = CBaBackupServer::CBaServCloseAllOperationTimer::NewL(this);
       
   231 	iCloseAllOperationRunning = EFalse;
       
   232 	
       
   233 	//initialise the client message framework
       
   234 	BSUL::CClientMessage::InitialiseFrameworkL(KServerData);
       
   235 	}
       
   236 
       
   237 /**
       
   238  *
       
   239  * Sets the server to be busy with the aUniqueClientId client.
       
   240  *
       
   241  * @param     "TUint32 aUniqueClientId"
       
   242  *            A unique client identifier.
       
   243  */
       
   244 EXPORT_C void CBaBackupServer::SetBusy(TUint32 aUniqueClientId)
       
   245 	{
       
   246 	iExtension->iUniqueBusyClientId=aUniqueClientId;
       
   247 	}
       
   248 
       
   249 /**
       
   250  *
       
   251  * Returns <code>ETrue</code> if the client using the server is not the one identified by aUniqueClientId
       
   252  * oterwise <code>EFalse</code>
       
   253  *
       
   254  * @param     "TUint32 aUniqueClientId"
       
   255  *            A unique client identifier.
       
   256  */
       
   257 EXPORT_C TBool CBaBackupServer::IsOtherClientBusy(TUint32 aUniqueClientId) const
       
   258 	{
       
   259 	return (iExtension->iUniqueBusyClientId!=0 && iExtension->iUniqueBusyClientId!=aUniqueClientId);
       
   260 	}
       
   261 
       
   262 /**
       
   263  *
       
   264  * Returns <code>ETrue</code> if the client using the server corresponds has aUniqueClientId as unique id
       
   265  * oterwise <code>EFalse</code>
       
   266  *
       
   267  * @param     "TUint32 aUniqueClientId"
       
   268  *            A unique client identifier id.
       
   269  */
       
   270 EXPORT_C TBool CBaBackupServer::IsClientBusy(TUint32 aUniqueClientId) const
       
   271 	{
       
   272 	return ((iExtension->iUniqueBusyClientId==aUniqueClientId) || 
       
   273 			((iExtension->iCachedBusyClientId != 0) && (iExtension->iCachedBusyClientId == aUniqueClientId))); 
       
   274 	}
       
   275 
       
   276 /**
       
   277  *
       
   278  * Handles the closing of all files by signaling the new file lock flag, aFlag, to all client.
       
   279  *
       
   280  * @param     "MBackupObserver::TFileLockFlags aFlag"
       
   281  *            A file lock flag.
       
   282  */
       
   283 EXPORT_C void CBaBackupServer::CloseAllFilesL(MBackupObserver::TFileLockFlags aFlag)
       
   284 	{
       
   285 	// Set the close all operation flag and the reregistration counter to zero
       
   286 	iCloseAllOperationRunning = ETrue;
       
   287 	iSessionLockReRegistrationCount = 0;
       
   288 	
       
   289 	// cleanup that calls RestartAll if required
       
   290 	TDblQueIter<CSession2> iter(iSessionIter);
       
   291 	iter.SetToFirst();
       
   292 
       
   293 	for (CSession2* session=iter++; session!=NULL; session=iter++)
       
   294 		{
       
   295 		static_cast<CBaServBackupSession*>(session)->SignalReleaseAllFileLocksL(aFlag);
       
   296 		}
       
   297 	}
       
   298 
       
   299 /**
       
   300  *
       
   301  * Signals to all clients of getting the lock of their respective files.
       
   302  *
       
   303  */
       
   304 EXPORT_C void CBaBackupServer::RestartAll()
       
   305 	{
       
   306 	TDblQueIter<CSession2> iter(iSessionIter);
       
   307 	iter.SetToFirst();
       
   308 
       
   309 	for (CSession2* session=iter++; session!=NULL; session=iter++)
       
   310 		{
       
   311 		static_cast<CBaServBackupSession*>(session)->SignalRetakeAllFileLocks();
       
   312 		}
       
   313 	}
       
   314 
       
   315 /**
       
   316  *
       
   317  * Allows any subclass of <code>CBaBackupServer</code> of completing the closing of files.
       
   318  * The server will lose the ownership of aClosedFiles object, which implies it is up to this virtual
       
   319  * function to deal with it in order to avoid a memory leak.
       
   320  *
       
   321  * @param     "CArrayFix<CBaServBackupSession::TClosedFile>* aClosedFiles"
       
   322  *            An array of closed files.
       
   323  */
       
   324 EXPORT_C void CBaBackupServer::CompleteClosingFiles(CArrayFix<CBaServBackupSession::TClosedFile>* aClosedFiles)
       
   325 	{
       
   326 	delete aClosedFiles;
       
   327 	}
       
   328 
       
   329 /**
       
   330  *
       
   331  * Allows application framework backup code to check if all registerd files have beem updated
       
   332  *
       
   333  */
       
   334 EXPORT_C TBool CBaBackupServer::HaveAllCloseAllFilesClientsReRegistered()
       
   335 	{
       
   336 	return((iRegisteredFilesCount == iSessionLockReRegistrationCount) ? ETrue : EFalse);
       
   337 	}
       
   338 
       
   339 void CBaBackupServer::CloseFileL(MBackupObserver::TFileLockFlags aFlag,const TDesC& aFileName)
       
   340 	{
       
   341 	TDblQueIter<CSession2> iter(iSessionIter);
       
   342 	iter.SetToFirst();
       
   343 
       
   344 	for (CSession2* session=iter++; session!=NULL; session=iter++)
       
   345 		{
       
   346 		static_cast<CBaServBackupSession*>(session)->SignalReleaseFileLockL(aFlag,aFileName);
       
   347 		}
       
   348 	}
       
   349 
       
   350 void CBaBackupServer::RestartFile(const TDesC& aFileName)
       
   351 	{
       
   352 	TDblQueIter<CSession2> iter(iSessionIter);
       
   353 	iter.SetToFirst();
       
   354 
       
   355 	for (CSession2* session=iter++; session!=NULL; session=iter++)
       
   356 		{
       
   357 		static_cast<CBaServBackupSession*>(session)->SignalRetakeFileLocks(aFileName);
       
   358 		}
       
   359 	}
       
   360 
       
   361 /**
       
   362  *
       
   363  * Creates a server-side client <code>CBaServBackupSession</code> session object by checking first if
       
   364  * the version of the server is compatible with the client.
       
   365  *
       
   366  * @param     "const TVersion &aVersion"
       
   367  *            Version information supplied by the client.
       
   368  */
       
   369 EXPORT_C CSession2* CBaBackupServer::NewSessionL(const TVersion &aVersion, const RMessage2& /*aMessage*/) const
       
   370 	{
       
   371 	TVersion ver(KBakServMajorVN,KBakServMinorVN,KBakServBuildVN);
       
   372 	if (!User::QueryVersionSupported(ver,aVersion))
       
   373 		User::Leave(KErrNotSupported);
       
   374 //
       
   375 	return CBaServBackupSession::NewL();
       
   376 	}
       
   377 
       
   378 /**
       
   379  *
       
   380  * Signals to all clients the aBackupOperationAttributes.
       
   381  *
       
   382  * @param     "const TBackupOperationAttributes& aBackupOperationAttributes"
       
   383  *            Backup operation attributes.
       
   384  */
       
   385 EXPORT_C void CBaBackupServer::SignalBackupOperation(const TBackupOperationAttributes& aBackupOperationAttributes)
       
   386 	{
       
   387 	TDblQueIter<CSession2> iter(iSessionIter);
       
   388 	iter.SetToFirst();
       
   389 
       
   390 	for (CSession2* session=iter++; session!=NULL; session=iter++)
       
   391 		{
       
   392 		static_cast<CBaServBackupSession*>(session)->SignalBackupOperation(aBackupOperationAttributes);
       
   393 		}
       
   394 	// Cache session id if starting backup
       
   395 	if (aBackupOperationAttributes.iOperation == MBackupOperationObserver::EStart)
       
   396 			iExtension->iCachedBusyClientId = iExtension->iUniqueBusyClientId;
       
   397 	}
       
   398 
       
   399 void CBaBackupServer::AddSession()
       
   400 	{
       
   401 	iShutdown->Cancel();
       
   402 	++iSessionCount;
       
   403 	}
       
   404 
       
   405 void CBaBackupServer::DropSession()
       
   406 	{
       
   407 	if (--iSessionCount==0)
       
   408 		{
       
   409 		iShutdown->Start();
       
   410 		}
       
   411 	}
       
   412 
       
   413 /*
       
   414  * Check to see if a CloseAll opertation is in progress
       
   415  * 
       
   416  */
       
   417 TBool CBaBackupServer::IsCloseAllOperationRunning()
       
   418 	{
       
   419 	return iCloseAllOperationRunning;
       
   420 	}
       
   421 
       
   422 /*
       
   423  * Set value of IsCloseAllOperationRunning
       
   424  * 
       
   425  */
       
   426 EXPORT_C void CBaBackupServer::SetCloseAllOperationRunningState(TBool aRunning)
       
   427 	{
       
   428 	iCloseAllOperationRunning = aRunning;
       
   429 	}
       
   430 
       
   431 /**
       
   432  *
       
   433  * This timer will only be created in cases of no derived backup server
       
   434  *
       
   435  */
       
   436 void CBaBackupServer::StartCloseAllFilesOperationTimer(const RMessagePtr2& aPtr)
       
   437 	{
       
   438 	// Store the CloseAll message in case we need to Complete on a timeout
       
   439 	iCloseAllFilesOperationTimer->SetMessage(aPtr);
       
   440 	
       
   441 	// If hardware use patchable constant if not default to 3 seconds
       
   442 	iCloseAllFilesOperationTimer->Start(KBaBackupCloseallFilesTimeout, KBaBackupCloseallFilesTimeout, TCallBack(CBaBackupServer::CBaServCloseAllOperationTimer::OperationTimerCallBack, iCloseAllFilesOperationTimer));
       
   443 	}
       
   444 
       
   445 /**
       
   446  * Handle an error from CBaServBackupSession::ServiceL()
       
   447  * A bad descriptor error implies a badly programmed client, so panic it;
       
   448  * otherwise report the error to the client
       
   449  *
       
   450  * @param     "TInt aError"
       
   451  *            The error.
       
   452  */
       
   453 EXPORT_C TInt CBaBackupServer::RunError(TInt aError)
       
   454 	{
       
   455 	if (aError==KErrBadDescriptor)
       
   456 		{
       
   457 		PanicClient(Message(), EBufferOverflow);
       
   458 		}
       
   459 	else
       
   460 		{
       
   461 		Message().Complete(aError);
       
   462 		}
       
   463 	//
       
   464 	// The leave will result in an early return from CServer::RunL(), skipping
       
   465 	// the call to request another message. So do that now in order to keep the
       
   466 	// server running.
       
   467 	ReStart();
       
   468 	return KErrNone;	// handled the error fully
       
   469 	}
       
   470 
       
   471 //
       
   472 // class CBaBackupServer::CBaServCloseAllOperationTimer
       
   473 //
       
   474 
       
   475 /**
       
   476 @internalComponent
       
   477 */
       
   478 CBaBackupServer::CBaServCloseAllOperationTimer* CBaBackupServer::CBaServCloseAllOperationTimer::NewL(CBaBackupServer* aBackupServer)
       
   479 	{ // static
       
   480 	CBaBackupServer::CBaServCloseAllOperationTimer* self=new(ELeave) CBaBackupServer::CBaServCloseAllOperationTimer();
       
   481 	CleanupStack::PushL(self);
       
   482 	self->ConstructL(aBackupServer);
       
   483 	CleanupStack::Pop(); // self
       
   484 	CActiveScheduler::Add(self);
       
   485 	return self;
       
   486 	}
       
   487 
       
   488 /**
       
   489 @internalComponent
       
   490 */
       
   491 
       
   492 void CBaBackupServer::CBaServCloseAllOperationTimer::ConstructL(CBaBackupServer* aBackupServer)
       
   493 	{
       
   494 	CTimer::ConstructL();
       
   495 	iBackupServer = aBackupServer;
       
   496 	iOperationCount = 0;
       
   497 	}
       
   498 /**
       
   499 @internalComponent
       
   500 */
       
   501 
       
   502 TInt CBaBackupServer::CBaServCloseAllOperationTimer::GetOperationCount()
       
   503 {
       
   504 	return iOperationCount;	
       
   505 }
       
   506 
       
   507 /**
       
   508 @internalComponent
       
   509 */
       
   510 
       
   511 void CBaBackupServer::CBaServCloseAllOperationTimer::SetOperationCount(TInt aCount)
       
   512 {
       
   513 	iOperationCount = aCount;
       
   514 }
       
   515 
       
   516 /**
       
   517 @internalComponent
       
   518 */
       
   519 
       
   520 TInt CBaBackupServer::CBaServCloseAllOperationTimer::RunError(TInt aError)
       
   521 	{
       
   522 	if (aError==KLeaveWithoutAlert)
       
   523 		{
       
   524 		return KErrNone;
       
   525 		}
       
   526 	return aError;
       
   527 	}
       
   528 	
       
   529 /**
       
   530 @internalComponent
       
   531 */
       
   532 CBaBackupServer::CBaServCloseAllOperationTimer::CBaServCloseAllOperationTimer()
       
   533 	: CPeriodic(CActive::EPriorityStandard)
       
   534 	{ ;	}
       
   535 	
       
   536 /**
       
   537 @internalComponent
       
   538 */
       
   539 CBaBackupServer::CBaServCloseAllOperationTimer::~CBaServCloseAllOperationTimer()
       
   540 	{
       
   541 	if (IsActive())
       
   542 		Cancel();	
       
   543 	}
       
   544 
       
   545 /**
       
   546 @internalComponent
       
   547 */
       
   548 void CBaBackupServer::CBaServCloseAllOperationTimer::SetMessage(const RMessagePtr2& aPtr)
       
   549 	{
       
   550 	iCloseAllFilesMessage = aPtr;
       
   551 	}
       
   552 
       
   553 /**
       
   554 @internalComponent
       
   555 */
       
   556 RMessagePtr2 CBaBackupServer::CBaServCloseAllOperationTimer::Message()
       
   557 	{
       
   558 	return iCloseAllFilesMessage;
       
   559 	}
       
   560 	
       
   561 /**
       
   562 @internalComponent
       
   563 */
       
   564 TInt CBaBackupServer::CBaServCloseAllOperationTimer::OperationTimerCallBack(TAny* aPtr)
       
   565 	{ // static
       
   566 	TRAP_IGNORE(REINTERPRET_CAST(CBaBackupServer::CBaServCloseAllOperationTimer*,aPtr)->HandleOperationTimerCallBack());
       
   567 	return 0;
       
   568 	}
       
   569 
       
   570 /**
       
   571 @internalComponent
       
   572 */
       
   573 void CBaBackupServer::CBaServCloseAllOperationTimer::HandleOperationTimerCallBack()
       
   574 	{
       
   575 	TBool finished = iBackupServer->HaveAllCloseAllFilesClientsReRegistered();
       
   576 	TInt retCode;
       
   577 	if (finished || (iOperationCount == KBakServMaxOperationTimerLoops))
       
   578 		{
       
   579 		if (finished)
       
   580 			{
       
   581 			retCode = KErrNone;
       
   582 			}
       
   583 		else
       
   584 			{
       
   585 			retCode = KErrLocked;
       
   586 			}
       
   587 		
       
   588 		// One way or another CloseAll is finished at this point
       
   589 		iBackupServer->SetCloseAllOperationRunningState(EFalse);
       
   590 		
       
   591 		iCloseAllFilesMessage.Complete(retCode);
       
   592 		Cancel();
       
   593 		}
       
   594 	else
       
   595 		{
       
   596 		iOperationCount++;
       
   597 		if (IsActive())
       
   598 			{
       
   599 			Cancel();
       
   600 
       
   601 			// If hardware use patchable constant if not default to 3 seconds
       
   602 			Start(KBaBackupCloseallFilesTimeout, KBaBackupCloseallFilesTimeout, TCallBack(CBaBackupServer::CBaServCloseAllOperationTimer::OperationTimerCallBack,this));
       
   603 			}
       
   604 		}
       
   605 	}
       
   606 
       
   607 //
       
   608 // class CBaServBackupMessageQueue
       
   609 //
       
   610 
       
   611 inline CBaServBackupMessageQueue::TQueueItem::TQueueItem(HBufC* aFileName,TInt aOperation)
       
   612 	: iFileName(aFileName), iOperation(aOperation)
       
   613 	{}
       
   614 
       
   615 CBaServBackupMessageQueue* CBaServBackupMessageQueue::NewL()
       
   616 	{ // static
       
   617 	CBaServBackupMessageQueue* self=new(ELeave) CBaServBackupMessageQueue();
       
   618 	return self;
       
   619 	}
       
   620 
       
   621 CBaServBackupMessageQueue::~CBaServBackupMessageQueue()
       
   622 	{
       
   623 	const TInt count=iQueue.Count();
       
   624 	for (TInt ii=0;ii<count;ii++)
       
   625 		{
       
   626 		delete iQueue[ii].iFileName;
       
   627 		}
       
   628 	iQueue.Reset();
       
   629 	iQueue.Close();
       
   630 	}
       
   631 
       
   632 void CBaServBackupMessageQueue::AddItemL(const TDesC& aFileName,MBackupObserver::TFileLockFlags aFlag)
       
   633 	{
       
   634 	const TInt count=iQueue.Count();
       
   635 	for (TInt ii=0;ii<count;ii++)
       
   636 		{
       
   637 		TQueueItem& item=iQueue[ii];
       
   638 		if(aFileName.MatchF(*item.iFileName) == KErrNone)
       
   639 			{
       
   640 			if (item.iOperation==MBackupObserver::EReleaseLockReadOnly && aFlag==MBackupObserver::EReleaseLockNoAccess)
       
   641 				{
       
   642 				item.iOperation=MBackupObserver::EReleaseLockNoAccess;
       
   643 				}
       
   644 			else if (item.iOperation!=MBackupObserver::EReleaseLockNoAccess)
       
   645 				{
       
   646 				HBufC* file=aFileName.AllocLC();
       
   647 				TQueueItem item(file,aFlag);
       
   648 				User::LeaveIfError(iQueue.Insert(item,ii));
       
   649 				CleanupStack::Pop(); // file
       
   650 				}
       
   651 			return;
       
   652 			}
       
   653 		}
       
   654 	HBufC* file=aFileName.AllocLC();
       
   655 	HBufC* copy=aFileName.AllocLC();
       
   656 	TQueueItem item(file,aFlag);
       
   657 	User::LeaveIfError(iQueue.Append(item));
       
   658 	item=TQueueItem(copy,-1);
       
   659 	const TInt err=iQueue.Append(item);
       
   660 	if (err!=KErrNone)
       
   661 		{
       
   662 		iQueue.Remove(iQueue.Count()-1);
       
   663 		User::Leave(err);
       
   664 		}
       
   665 	CleanupStack::Pop(2); // copy, file
       
   666 	}
       
   667 
       
   668 void CBaServBackupMessageQueue::AddItem(const TDesC& aFileName)
       
   669 	{
       
   670 	const TInt count=iQueue.Count();
       
   671 	for (TInt ii=0;ii<count;ii++)
       
   672 		{
       
   673 		TQueueItem& item=iQueue[ii];
       
   674 		if (aFileName.MatchF(*item.iFileName) == KErrNone && item.iOperation==-1)
       
   675 			{
       
   676 			item.iOperation=0;
       
   677 			break;
       
   678 			}
       
   679 		}
       
   680 	}
       
   681 
       
   682 TBool CBaServBackupMessageQueue::IsEmpty() const
       
   683 	{
       
   684 	return HeadIndex()==KErrNotFound;
       
   685 	}
       
   686 
       
   687 void CBaServBackupMessageQueue::RemoveHead()
       
   688 	{
       
   689 	const TInt index=HeadIndex();
       
   690 	if (index!=KErrNotFound)
       
   691 		{
       
   692 		delete iQueue[index].iFileName;
       
   693 		iQueue.Remove(index);
       
   694 		iQueue.Compress();
       
   695 		}
       
   696 	}
       
   697 
       
   698 void CBaServBackupMessageQueue::RemoveItem(const TDesC& aFileName)
       
   699 	{
       
   700 	const TInt count=iQueue.Count();
       
   701 	for (TInt ii=count-1;ii>=0;ii--)
       
   702 		{
       
   703 		const TQueueItem& item=iQueue[ii];
       
   704 		if (aFileName.MatchF(*item.iFileName) == KErrNone)
       
   705 			{
       
   706 			delete item.iFileName;
       
   707 			iQueue.Remove(ii);
       
   708 			iQueue.Compress();
       
   709 			}
       
   710 		}
       
   711 	}
       
   712 
       
   713 void CBaServBackupMessageQueue::GetHead(TDes& aFileName,MBackupObserver::TFileLockFlags& aFlag) const
       
   714 	{
       
   715 	aFileName.Zero();
       
   716 	const TInt index=HeadIndex();
       
   717 	if (index!=KErrNotFound)
       
   718 		{
       
   719 		const TQueueItem& item=iQueue[index];
       
   720 		aFileName=item.iFileName->Des();
       
   721 		aFlag=(MBackupObserver::TFileLockFlags)item.iOperation;
       
   722 		}
       
   723 	}
       
   724 
       
   725 TInt CBaServBackupMessageQueue::HeadIndex() const
       
   726 	{
       
   727 	TInt index=KErrNotFound;
       
   728 	const TInt count=iQueue.Count();
       
   729 	for (TInt ii=0;ii<count;ii++)
       
   730 		{
       
   731 		const TQueueItem& item=iQueue[ii];
       
   732 		if (item.iOperation!=ENoOp)
       
   733 			{
       
   734 			index=ii;
       
   735 			break;
       
   736 			}
       
   737 		}
       
   738 	return index;
       
   739 	}
       
   740 
       
   741 //
       
   742 // class CBaServBackupSession
       
   743 //
       
   744 
       
   745 CBaServBackupSession* CBaServBackupSession::NewL()
       
   746 	{ // static
       
   747 	CBaServBackupSession* self=new(ELeave) CBaServBackupSession();
       
   748 	CleanupStack::PushL(self);
       
   749 	self->ConstructL();
       
   750 	CleanupStack::Pop(); // self
       
   751 	return self;
       
   752 	}
       
   753 
       
   754 /**
       
   755  *
       
   756  * Constructor.
       
   757  *
       
   758  * @param     "RThread aClient"
       
   759  *            The client thread for which this server-side client session is being constructed.
       
   760  */
       
   761 EXPORT_C CBaServBackupSession::CBaServBackupSession()
       
   762 	: CSession2()
       
   763 	{
       
   764 	iUniqueClientId = (TUint32)this;
       
   765 	}
       
   766 
       
   767 /**
       
   768  *
       
   769  * Destructor.
       
   770  *
       
   771  */
       
   772 EXPORT_C CBaServBackupSession::~CBaServBackupSession()
       
   773 	{
       
   774 	CBaBackupServer* server=BackupServer();
       
   775 	if (server->IsClientBusy(iUniqueClientId))
       
   776 		{
       
   777 		RestartAll();
       
   778 		if (server->IsBackupOperationRunning())
       
   779 			{
       
   780 			TBackupOperationAttributes backupOpAtt(MBackupObserver::ETakeLock, MBackupOperationObserver::EAbort);
       
   781 			server->SignalBackupOperation(backupOpAtt);
       
   782 			server->SetBackupOperationRunning(EFalse);
       
   783 			}
       
   784 		server->SetBusy(0);
       
   785 		}
       
   786 
       
   787 	if (iFileLockObservers)
       
   788 		{
       
   789 		server->DecrementRegisteredFilesCount(iFileLockObservers->Count());	
       
   790 		}
       
   791 
       
   792 	delete iClosedFiles;
       
   793 	delete iFileLockObservers;
       
   794 	delete iReleasedFiles;
       
   795 	delete iMessageQueue;
       
   796 	delete iReRegistrationTimer;
       
   797 	iReRegistrationTimer = 0;
       
   798 	server->DropSession();
       
   799 	}
       
   800 
       
   801 /**
       
   802  *
       
   803  * Completes the session construction by creating a <code>CBaServBackupMessageQueue</code> object.
       
   804  *
       
   805  */
       
   806 EXPORT_C void CBaServBackupSession::ConstructL()
       
   807 	{
       
   808 	iMessageQueue=CBaServBackupMessageQueue::NewL();
       
   809 
       
   810 	// Cannot set iBackupServer in CReRegistrationTimer at this point but must be done before call to Start
       
   811 	iReRegistrationTimer=CBaServBackupSession::CReRegistrationTimer::NewL(CActive::EPriorityStandard);
       
   812 	}
       
   813 
       
   814 /**
       
   815  *
       
   816  * Completes the construction of this <code>CBaServBackupSession</code> session by just doing a base call class.
       
   817  * It also notify the server that a new session has been created.
       
   818  *
       
   819  * @param		"const CServer& aServer"
       
   820  *				The server active object which is responsible for this session
       
   821  */
       
   822 EXPORT_C void CBaServBackupSession::CreateL()
       
   823 	{
       
   824 	BackupServer()->AddSession();
       
   825 	}
       
   826 
       
   827 void CBaServBackupSession::SignalReleaseAllFileLocksL(MBackupObserver::TFileLockFlags aFlag)
       
   828 	{
       
   829 	CBaBackupServer* server=BackupServer();
       
   830 	if (iFileLockObservers)
       
   831 		{
       
   832 		const TInt count=iFileLockObservers->Count();
       
   833 		for (TInt ii=0;ii<count;ii++)
       
   834 			{
       
   835 			TFileName name=(*iFileLockObservers)[ii];
       
   836 			server->CloseFileL(aFlag,name);
       
   837 			}
       
   838 		}
       
   839 	}
       
   840 
       
   841 void CBaServBackupSession::SignalRetakeAllFileLocks()
       
   842 	{
       
   843 //	CBaBackupServer* server=BackupServer();
       
   844 	if (iReleasedFiles)
       
   845 		{
       
   846 		const TInt count=iReleasedFiles->Count();
       
   847 		for (TInt ii=count-1;ii>=0;ii--)
       
   848 			{
       
   849 			TFileName name=(*iReleasedFiles)[ii];
       
   850 //			server->RestartFile(name);
       
   851 			SignalRetakeFileLocks(name);
       
   852 			}
       
   853 		}
       
   854 	}
       
   855 
       
   856 LOCAL_C void CleanupCloseFail(TAny* aPtr)
       
   857 	{
       
   858 	CDesCArray* array=REINTERPRET_CAST(CDesCArray*,aPtr);
       
   859 	array->Delete(array->Count()-1);
       
   860 	}
       
   861 
       
   862 void CBaServBackupSession::SignalReleaseFileLockL(MBackupObserver::TFileLockFlags aFlag,const TDesC& aFileName)
       
   863 	{
       
   864 	TInt pos;
       
   865 	if (iFileLockObservers && iFileLockObservers->Find(aFileName,pos)==KErrNone)
       
   866 		{
       
   867 		if (iReleasedFiles==NULL)
       
   868 			{
       
   869 			iReleasedFiles=new(ELeave) CDesCArraySeg(1);
       
   870 			}
       
   871 		const TBool addedReleasedFile=iReleasedFiles->Find(aFileName,pos)!=KErrNone;
       
   872 		if (addedReleasedFile)
       
   873 			{
       
   874 			iReleasedFiles->AppendL(aFileName);
       
   875 			CleanupStack::PushL(TCleanupItem(CleanupCloseFail,iReleasedFiles));
       
   876 			}
       
   877 		iMessageQueue->AddItemL(aFileName,aFlag);
       
   878 		if (!iNotificationPullMsg.IsNull())
       
   879   			{
       
   880   			iNotificationPullMsg.Complete(KErrNone);
       
   881 
       
   882   			// Okay - if this is part of a CloseAll operation we need to kick off a ReRegistration timer
       
   883   			if (BackupServer()->IsCloseAllOperationRunning())
       
   884   				{
       
   885   				// Set backup server for the timer
       
   886   				iReRegistrationTimer->iBackupServer = BackupServer();
       
   887 
       
   888   				// If hardware use patchable constant if not default to 3 seconds
       
   889   				iReRegistrationTimer->Start(KBaBackupFileLockReRegistrationTimeout, KBaBackupFileLockReRegistrationTimeout, TCallBack(CBaServBackupSession::CReRegistrationTimer::ReRegistrationTimerCallBack, iReRegistrationTimer));  				
       
   890   				}
       
   891 
       
   892   			}
       
   893 		if (addedReleasedFile)
       
   894 			{
       
   895 			CleanupStack::Pop(); // CleanupCloseFail
       
   896 			}
       
   897 		}
       
   898 	}
       
   899 
       
   900 void CBaServBackupSession::SignalRetakeFileLocks(const TDesC& aFileName)
       
   901 	{
       
   902 	if (iReleasedFiles)
       
   903 		{
       
   904 		const TInt count=iReleasedFiles->Count();
       
   905 		for (TInt ii=count-1;ii>=0;ii--)
       
   906 			{
       
   907 			TFileName name=(*iReleasedFiles)[ii];
       
   908 			if (name.MatchF(aFileName)==0)
       
   909 				{
       
   910 				iMessageQueue->AddItem(aFileName);
       
   911 				if (!iNotificationPullMsg.IsNull())
       
   912   					{
       
   913   					iNotificationPullMsg.Complete(KErrNone);
       
   914   					}
       
   915 				iReleasedFiles->Delete(ii);
       
   916 				}
       
   917 			}
       
   918 		if (iReleasedFiles->Count()==0)
       
   919 			{
       
   920 			delete iReleasedFiles;
       
   921 			iReleasedFiles=NULL;
       
   922 			if (iClosedFiles==NULL && BackupServer()->IsClientBusy(iUniqueClientId))
       
   923 				{
       
   924 				BackupServer()->SetBusy(0);
       
   925 				}
       
   926 			}
       
   927 		}
       
   928 	}
       
   929 
       
   930 /**
       
   931  *
       
   932  * Allows the session to handle the error.
       
   933  *
       
   934  * @param		"TInt aError"
       
   935  *				The error.
       
   936  */
       
   937 EXPORT_C void CBaServBackupSession::HandleError(TInt aError)
       
   938 	{
       
   939 	if (aError==KLeaveWithoutAlert)
       
   940 		{
       
   941 		CBaServBackupScheduler::Current()->SetErrorHandler(NULL);
       
   942 		}
       
   943 	}
       
   944 
       
   945 void CBaServBackupSession::DoServiceL(TCompletionType& aCompleteType)
       
   946 	{
       
   947 	switch (iClientMessage->Function())
       
   948 		{
       
   949 	case EBakOpCodeEventReady:
       
   950 		{
       
   951 		HandleEventReadyL();
       
   952 		aCompleteType = ECompleteAsync;
       
   953 		}
       
   954 		break;
       
   955 	case EBakOpCodeStopNotifications:
       
   956 		{
       
   957 		StopNotifications();
       
   958 		}
       
   959 		break;
       
   960 	case EBakOpCodeGetEvent:
       
   961 		GetEventL();
       
   962 		break;
       
   963 	case EBakOpCodeCloseAllFiles:
       
   964 		{
       
   965 		aCompleteType = CloseAllFilesL(iClientMessage->Message());
       
   966 		}
       
   967 		break;
       
   968 	case EBakOpCodeRestartAll:
       
   969 		RestartAll();
       
   970 		break;
       
   971 	case EBakOpCodeCloseFile:
       
   972 		CloseFileL();
       
   973 		break;
       
   974 	case EBakOpCodeRestartFile:
       
   975 		RestartFileL();
       
   976 		break;
       
   977 	case EBakOpCodeNotifyLockChange:
       
   978 		NotifyLockChangeL();
       
   979 		break;
       
   980 	case EBakOpCodeNotifyLockChangeCancel:
       
   981 		NotifyLockChangeCancelL();
       
   982 		break;
       
   983 	case EBakOpCodeNotifyBackupOperation:
       
   984 		NotifyBackupOperationL();
       
   985 		break;
       
   986 	case EBakOpCodeCancelOutstandingBackupOperationEvent:
       
   987 		{
       
   988 		iBackupOperationObserverPresent = EFalse;
       
   989 		if (!iBackupOperationMessagePtr.IsNull())
       
   990 			{
       
   991 			GetBackupOperationEventL(iBackupOperationMessagePtr);
       
   992 			iBackupOperationMessagePtr.Complete(KErrCancel);
       
   993 			}
       
   994 		}
       
   995 		break;
       
   996 	case EBakOpCodeGetBackupOperationState:
       
   997 		GetBackupOperationStateL();
       
   998 		break;
       
   999 	case EBakOpCodeBackupOperationEventReady:
       
  1000 		BackupOperationEventReadyL();
       
  1001 		aCompleteType = ECompleteAsync;
       
  1002 		break;
       
  1003 	case EBakOpCodeGetBackupOperationEvent:
       
  1004 		GetBackupOperationEventL(iClientMessage->Message());
       
  1005 		break;
       
  1006 	case EBakOpCodeSetBackupOperationObserverIsPresent:
       
  1007 		{
       
  1008 		iBackupOperationObserverPresent = iClientMessage->GetIntL(0);
       
  1009 		}
       
  1010 		break;
       
  1011 	default:
       
  1012 		User::Leave(KErrNotSupported);
       
  1013 		break;
       
  1014 		}
       
  1015 	}
       
  1016 
       
  1017 
       
  1018 /**
       
  1019  *
       
  1020  * Handles the servicing of client requests passed to the backup server.
       
  1021  *
       
  1022  * @param		"const RMessage& aMessage"
       
  1023  *				The message containing the client request.
       
  1024  */
       
  1025 EXPORT_C void CBaServBackupSession::ServiceL(const RMessage2& aMessage)
       
  1026 	{
       
  1027 	
       
  1028 	TCompletionType completionType = ECompleteSync;
       
  1029 	
       
  1030 	iClientMessage = BSUL::CClientMessage::NewL(aMessage);
       
  1031 	
       
  1032 	//Push iClientMessage onto the cleanupstack. Although an instance variable, 
       
  1033 	//the lifetime of the object is contained to this function so it needs to
       
  1034 	//be pushed and popped here as it is not deleted in the destructor
       
  1035 	CleanupStack::PushL(iClientMessage);
       
  1036 	
       
  1037 	//Validate the message
       
  1038 	TRAPD(error, iClientMessage->ValidateL());
       
  1039 		
       
  1040 	if(error == KErrNone)	
       
  1041 		{
       
  1042 		TRAP(error, DoServiceL(completionType));
       
  1043 		}
       
  1044 	
       
  1045 	if(completionType == ECompleteSync)
       
  1046 		{
       
  1047 		if (error==KLeaveWithoutAlert)
       
  1048 			{
       
  1049 			CBaServBackupScheduler::Current()->SetErrorHandler(NULL);
       
  1050 			}
       
  1051 		else
       
  1052 			{
       
  1053 			iClientMessage->CompleteRequestL(error);
       
  1054 			}
       
  1055 		}
       
  1056 	
       
  1057 	//Pop and destroy message
       
  1058 	CleanupStack::PopAndDestroy(iClientMessage);
       
  1059 	iClientMessage = NULL;
       
  1060 	}
       
  1061 
       
  1062 void CBaServBackupSession::HandleEventReadyL()
       
  1063 	{
       
  1064 	if (iReRegistrationTimer->IsActive())
       
  1065 		{ // If timer is still active (ie not timed out) we need to increment the counter and cancel the timer
       
  1066 		BackupServer()->IncrementFilesReRegistrationCount();	
       
  1067 		iReRegistrationTimer->Cancel();
       
  1068 		}
       
  1069 		// else timer is already inactive because it's expired
       
  1070 	
       
  1071 	if (iMessageQueue->IsEmpty())
       
  1072 		{
       
  1073 		iNotificationPullMsg = iClientMessage->Message();
       
  1074 		}	
       
  1075 	else
       
  1076 		{
       
  1077 		iClientMessage->CompleteRequestL(KErrNone);
       
  1078 		}
       
  1079 	}
       
  1080 
       
  1081 const TInt KEventFileNameOffset=1;
       
  1082 
       
  1083 void CBaServBackupSession::GetEventL()
       
  1084 	{
       
  1085 	TFileName fileName;
       
  1086 	MBackupObserver::TFileLockFlags fileFlag;
       
  1087 	if(!iMessageQueue->IsEmpty())
       
  1088 		{
       
  1089 		iMessageQueue->GetHead(fileName,fileFlag);
       
  1090 		TBuf<KEventFileNameOffset> num;
       
  1091 		num.Num((TInt)fileFlag);
       
  1092 		
       
  1093 		iClientMessage->WriteL(0,num,0);
       
  1094 		
       
  1095 		iClientMessage->WriteL(0,fileName,KEventFileNameOffset);
       
  1096 	
       
  1097 		iMessageQueue->RemoveHead();	
       
  1098 		}
       
  1099 	else
       
  1100 		{
       
  1101 		iClientMessage->PanicClient(KPanic,ENoEventToFetch);
       
  1102 		User::Leave(KLeaveWithoutAlert);
       
  1103 		}
       
  1104 	}
       
  1105 
       
  1106 void CBaServBackupSession::CleanupCloseAllFiles(TAny* aPtr)
       
  1107 	{ // static
       
  1108 	CBaServBackupSession* self=REINTERPRET_CAST(CBaServBackupSession*,aPtr);
       
  1109 	delete self->iClosedFiles;
       
  1110 	self->iClosedFiles=NULL;
       
  1111 	self->BackupServer()->RestartAll();
       
  1112 	}
       
  1113 
       
  1114 /**
       
  1115  Asks the server to close all files. This function may leave in case the server is busy.
       
  1116  If the requesting client is the current busy client and it has already requested CloseAll,
       
  1117  this request will be ignored.
       
  1118  
       
  1119  @param	aMessage The reference to the message containing the client request: file lock.
       
  1120  @leave KErrServerBusy if the requesting client is not the busy client. Plus other system-wide 
       
  1121  errors.
       
  1122  */
       
  1123 EXPORT_C TCompletionType CBaServBackupSession::CloseAllFilesL(const RMessage2& aMessage)
       
  1124 	{
       
  1125 	// Raise file lock notifications
       
  1126 	TRAPD(err,DoCloseAllFilesL(aMessage));
       
  1127 	
       
  1128 	if (err == KErrNone)
       
  1129 		{
       
  1130 		// Start timer to check all file locks re-registered before completing message
       
  1131 		BackupServer()->StartCloseAllFilesOperationTimer(aMessage);
       
  1132 		}
       
  1133 	else
       
  1134 		{
       
  1135 		// If the error is that the same client has already requested CloseAll, ignore this request
       
  1136 		// If not this error, recover the CloseAllOperationRunningState flag and leave with the error.
       
  1137 		if (err != KErrAlreadyExists) 
       
  1138 			{
       
  1139 			BackupServer()->SetCloseAllOperationRunningState(EFalse);
       
  1140 			User::Leave(err);
       
  1141 			}
       
  1142 		}
       
  1143 
       
  1144 	return ECompleteAsync;
       
  1145 	}
       
  1146 
       
  1147 void CBaBackupServer::IncrementRegisteredFilesCount()
       
  1148 	{
       
  1149 	iRegisteredFilesCount++;
       
  1150 	}
       
  1151 
       
  1152 void CBaBackupServer::DecrementRegisteredFilesCount(TInt aNumberFiles)
       
  1153 	{
       
  1154 	iRegisteredFilesCount = iRegisteredFilesCount - aNumberFiles;
       
  1155 	}
       
  1156 
       
  1157 void CBaBackupServer::IncrementFilesReRegistrationCount()
       
  1158 	{
       
  1159 	iSessionLockReRegistrationCount++;
       
  1160 	}
       
  1161 
       
  1162 /**
       
  1163  Function called by both base and derived backup sessions in order to start asynchronous 
       
  1164  file lock notifications.
       
  1165  The requesting client is set to the current busy client.
       
  1166  
       
  1167  @leave KErrServerBusy if the requesting client is not the current busy client or the server
       
  1168  is under CloseAll operation. KErrAlreadyExists if the same client has sent CloseAll request.
       
  1169  Plus other system-wide errors.
       
  1170  */
       
  1171  
       
  1172 EXPORT_C TCompletionType CBaServBackupSession::DoCloseAllFilesL(const RMessage2& /*aMessage*/)
       
  1173 	{
       
  1174 	CBaBackupServer* server=BackupServer();
       
  1175 	if (server->IsOtherClientBusy(iUniqueClientId))
       
  1176 		{
       
  1177 		User::Leave(KErrServerBusy);
       
  1178 		}
       
  1179 		
       
  1180 	if (BackupServer()->IsCloseAllOperationRunning())
       
  1181 		{
       
  1182 		User::Leave(KErrAlreadyExists);
       
  1183 		}		
       
  1184 		
       
  1185 	CleanupStack::PushL(TCleanupItem(CleanupCloseAllFiles,this));
       
  1186 	if (iClosedFiles)
       
  1187 		{
       
  1188 		delete iClosedFiles;
       
  1189 		iClosedFiles=NULL;
       
  1190 		}
       
  1191 	server->SetBusy(iUniqueClientId);
       
  1192 	
       
  1193 	MBackupObserver::TFileLockFlags fileFlag=
       
  1194 		(MBackupObserver::TFileLockFlags)iClientMessage->GetIntL(0);
       
  1195 	server->CloseAllFilesL(fileFlag);
       
  1196 	
       
  1197 	iClosedFiles=new(ELeave) CArrayFixSeg<CBaServBackupSession::TClosedFile>(1);
       
  1198 	CBaServBackupScheduler::Current()->SetErrorHandler(this);
       
  1199 	CleanupStack::Pop(); // CleanupCloseAllFiles
       
  1200 	return ECompleteAsync;
       
  1201 	}
       
  1202 
       
  1203 /**
       
  1204  *
       
  1205  * Asks the server to signal all clients of getting the lock of their respective files.
       
  1206  *
       
  1207  */
       
  1208 EXPORT_C void CBaServBackupSession::RestartAll()
       
  1209 	{
       
  1210 	CBaBackupServer* server=BackupServer();	
       
  1211 	if (server->IsClientBusy(iUniqueClientId))
       
  1212 		{
       
  1213 		DoRestartAll();
       
  1214 		}
       
  1215 	}
       
  1216 
       
  1217 void CBaServBackupSession::DoRestartAll()
       
  1218 	{
       
  1219 	CBaBackupServer* server=BackupServer();	
       
  1220 	server->RestartAll();
       
  1221 	delete iReleasedFiles;
       
  1222 	iReleasedFiles=NULL;
       
  1223 	if (iClosedFiles)
       
  1224 		{
       
  1225 		CArrayFix<CBaServBackupSession::TClosedFile>* closedFiles=iClosedFiles;
       
  1226 		iClosedFiles=NULL;
       
  1227 		server->CompleteClosingFiles(closedFiles); // takes ownership of closedFiles immediately
       
  1228 		}
       
  1229 	}
       
  1230 
       
  1231 /**
       
  1232 Handle the client's request to close a file.
       
  1233 The request will be ignored if the requesting client the current busy client and the server is
       
  1234 under CloseAll operation.
       
  1235 
       
  1236 @leave KErrServerBusy if the server is busy with the other client, plus other system-wide errors.
       
  1237 */
       
  1238 void CBaServBackupSession::CloseFileL()
       
  1239 	{
       
  1240 	CBaBackupServer* server=BackupServer();
       
  1241 	if (server->IsOtherClientBusy(iUniqueClientId))
       
  1242 		{
       
  1243 		User::Leave(KErrServerBusy);
       
  1244 		}
       
  1245 
       
  1246 	if (! server->IsCloseAllOperationRunning())
       
  1247 		{
       
  1248 		MBackupObserver::TFileLockFlags flag=
       
  1249 			static_cast<MBackupObserver::TFileLockFlags>(iClientMessage->GetIntL(2));
       
  1250 		TFileName fileName;
       
  1251 		GetFileNameL(fileName);
       
  1252 		server->SetBusy(iUniqueClientId);
       
  1253 		server->CloseFileL(flag,fileName);
       
  1254 		}
       
  1255 	}
       
  1256 
       
  1257 void CBaServBackupSession::RestartFileL()
       
  1258 	{
       
  1259 	TFileName fileName;
       
  1260 	GetFileNameL(fileName);
       
  1261 	BackupServer()->RestartFile(fileName);
       
  1262 	}
       
  1263 
       
  1264 /**
       
  1265 Handles the client's request of notification of a file lock change.
       
  1266   
       
  1267 @leave KErrServerBusy if the server is under CloseAll operation, KLeaveWithoutAlert if the requested 
       
  1268  file has been registered. Plus other system-wide errors.
       
  1269 */
       
  1270 void CBaServBackupSession::NotifyLockChangeL()
       
  1271 	{
       
  1272 	if(BackupServer()->IsCloseAllOperationRunning())
       
  1273 		{
       
  1274 		User::Leave(KErrServerBusy);
       
  1275 		}
       
  1276 		
       
  1277 	TFileName fileName;
       
  1278 	GetFileNameL(fileName);
       
  1279 	if (iFileLockObservers==NULL)
       
  1280 		{
       
  1281 		iFileLockObservers=new(ELeave) CDesCArraySeg(1);
       
  1282 		}
       
  1283 	else
       
  1284 		{
       
  1285 		TInt pos;
       
  1286 		if(iFileLockObservers->Find(fileName,pos)== KErrNone)
       
  1287 			{
       
  1288 			iClientMessage->PanicClient(KPanic,EReqAlreadyOutstanding);
       
  1289 			User::Leave(KLeaveWithoutAlert);
       
  1290 			}		
       
  1291 		}
       
  1292 	iFileLockObservers->AppendL(fileName);
       
  1293 	BackupServer()->IncrementRegisteredFilesCount();
       
  1294 	}
       
  1295 
       
  1296 LOCAL_C void RemoveFileName(CDesCArray& aArray,const TDesC& aFileName)
       
  1297 	{
       
  1298 	TInt pos;
       
  1299 	if (aArray.Find(aFileName,pos)==KErrNone)
       
  1300 		{
       
  1301 		aArray.Delete(pos);
       
  1302 		}
       
  1303 	}
       
  1304 
       
  1305 void CBaServBackupSession::NotifyLockChangeCancelL()
       
  1306 	{
       
  1307 	TFileName fileName;
       
  1308 	GetFileNameL(fileName);
       
  1309 	if (iFileLockObservers)
       
  1310 		{
       
  1311 		RemoveFileName(*iFileLockObservers,fileName);
       
  1312 		BackupServer()->DecrementRegisteredFilesCount();
       
  1313 		}
       
  1314 	if (iReleasedFiles)
       
  1315 		{
       
  1316 		RemoveFileName(*iReleasedFiles,fileName);
       
  1317 		}
       
  1318 	iMessageQueue->RemoveItem(fileName);
       
  1319   	}
       
  1320 
       
  1321 void CBaServBackupSession::GetFileNameL(TDes& aFileName)
       
  1322 	{
       
  1323 	//The verification of this parameter has already been handled
       
  1324 	//by the CClientMessage class so we can safely read the value
       
  1325 	iClientMessage->ReadL(1,aFileName);
       
  1326 	}
       
  1327 
       
  1328 
       
  1329 void CBaServBackupSession::GetBackupOperationEventL(const RMessagePtr2& aPtr)
       
  1330 	{
       
  1331 	TPckg<TBackupOperationAttributes> backupOpAttPkg(iBackupOperationAttributes);
       
  1332 	
       
  1333 	aPtr.WriteL(0, backupOpAttPkg);
       
  1334 	}
       
  1335 
       
  1336 void CBaServBackupSession::BackupOperationEventReadyL()
       
  1337 	{
       
  1338 	if (iBackupOperationObserverPresent)
       
  1339 		{
       
  1340 		iBackupOperationMessagePtr = iClientMessage->Message();
       
  1341 		}
       
  1342 	else
       
  1343 		{
       
  1344 		iClientMessage->CompleteRequestL(KErrNone);
       
  1345 		}
       
  1346 	}
       
  1347 
       
  1348 void CBaServBackupSession::NotifyBackupOperationL()
       
  1349 	{
       
  1350 	CBaBackupServer* server=BackupServer();
       
  1351 	if (server->CBaBackupServer::IsOtherClientBusy(iUniqueClientId))
       
  1352 		{
       
  1353 		User::Leave(KErrServerBusy);
       
  1354 		}
       
  1355 	TPckg<TBackupOperationAttributes> backupOpAttPkg(iBackupOperationAttributes);
       
  1356 	
       
  1357 	iClientMessage->ReadL(0,backupOpAttPkg);
       
  1358 
       
  1359 	const TBool backupOperationRunning = ((iBackupOperationAttributes.iOperation==MBackupOperationObserver::EStart) ? ETrue : EFalse);
       
  1360 	server->SetBackupOperationRunning(backupOperationRunning);
       
  1361 	server->SetBusy(backupOperationRunning ? iUniqueClientId : 0);
       
  1362 	server->SignalBackupOperation(iBackupOperationAttributes);
       
  1363 	if (!iBackupOperationMessagePtr.IsNull())
       
  1364 		{
       
  1365 		GetBackupOperationEventL(iBackupOperationMessagePtr);
       
  1366 		iBackupOperationMessagePtr.Complete(KErrCancel);
       
  1367 		}
       
  1368 	}
       
  1369 
       
  1370 void CBaServBackupSession::GetBackupOperationStateL()
       
  1371 	{
       
  1372 	const TBool isRunning = BackupServer()->IsBackupOperationRunning();
       
  1373 	TPckgC<TBool> pkgObs(isRunning);
       
  1374 
       
  1375 	iClientMessage->WriteL(0, pkgObs);
       
  1376 	}
       
  1377 
       
  1378 void CBaServBackupSession::SignalBackupOperation(const TBackupOperationAttributes& aBackupOperationAttributes)
       
  1379 	{
       
  1380 	iBackupOperationAttributes = aBackupOperationAttributes;
       
  1381 	if (!iBackupOperationMessagePtr.IsNull())
       
  1382 		{
       
  1383 		TRAPD(err,GetBackupOperationEventL(iBackupOperationMessagePtr));
       
  1384 		iBackupOperationMessagePtr.Complete(err);
       
  1385 		}
       
  1386 	}
       
  1387 
       
  1388 void CBaServBackupSession::StopNotifications()
       
  1389 	{
       
  1390 		if(!iNotificationPullMsg.IsNull())
       
  1391 		{// complete the registration message
       
  1392 		iNotificationPullMsg.Complete(KErrNone);
       
  1393 		}
       
  1394 	}
       
  1395 
       
  1396 /**
       
  1397 @internalComponent
       
  1398 */
       
  1399 CBaServBackupSession::CReRegistrationTimer* CBaServBackupSession::CReRegistrationTimer::NewL(TInt aPriority)
       
  1400 	{ // static
       
  1401 	CBaServBackupSession::CReRegistrationTimer* self=new(ELeave) CBaServBackupSession::CReRegistrationTimer(aPriority);
       
  1402 	CleanupStack::PushL(self);
       
  1403 	self->ConstructL();
       
  1404 	CleanupStack::Pop(); // self
       
  1405 	CActiveScheduler::Add(self);
       
  1406 	return self;
       
  1407 	}
       
  1408 
       
  1409 /**
       
  1410 @internalComponent
       
  1411 */
       
  1412 TInt CBaServBackupSession::CReRegistrationTimer::RunError(TInt aError)
       
  1413 	{
       
  1414 	if (aError==KLeaveWithoutAlert)
       
  1415 		{
       
  1416 		return KErrNone;
       
  1417 		}
       
  1418 	return aError;
       
  1419 	}
       
  1420 	
       
  1421 /**
       
  1422 @internalComponent
       
  1423 */
       
  1424 CBaServBackupSession::CReRegistrationTimer::CReRegistrationTimer(TInt aPriority)
       
  1425 	: CPeriodic(aPriority)
       
  1426 	{ }
       
  1427 	
       
  1428 /**
       
  1429 @internalComponent
       
  1430 */
       
  1431 TInt CBaServBackupSession::CReRegistrationTimer::ReRegistrationTimerCallBack(TAny* aPtr)
       
  1432 	{ // static
       
  1433 	TRAP_IGNORE(REINTERPRET_CAST(CBaServBackupSession::CReRegistrationTimer*,aPtr)->HandleReRegistrationTimerCallBack());
       
  1434 	return 0;
       
  1435 	}
       
  1436 
       
  1437 /**
       
  1438 @internalComponent
       
  1439 */
       
  1440 void CBaServBackupSession::CReRegistrationTimer::HandleReRegistrationTimerCallBack()
       
  1441 	{
       
  1442 	iBackupServer->IncrementFilesReRegistrationCount();
       
  1443 	
       
  1444 	if (IsActive())
       
  1445 		{
       
  1446 		Cancel();
       
  1447 		}
       
  1448 	}
       
  1449