1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/loggingservices/eventlogger/LogServ/src/logservsession.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,471 @@
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 +//
1.18 +
1.19 +#include "logservsession.h"
1.20 +#include "LogNotify.h"
1.21 +#include "LogServServer.h"
1.22 +#include "logservpanic.h"
1.23 +#include "LogServView.h"
1.24 +#include "LogServOperationBase.h"
1.25 +#include "LogServBackupInterface.h"
1.26 +#include "LogServOperationFactory.h"
1.27 +#include "LogServOperationManager.h"
1.28 +#include "LogServDatabaseChangeInterface.h"
1.29 +#include "LogServDatabaseChangeDefinition.h"
1.30 +#include "LogServSqlStrings.h"
1.31 +
1.32 +// Constants
1.33 +const TInt KLogViewListGranuality = 5;
1.34 +const TInt KLogServPendingGlobalChangesArrayGranularity = 3;
1.35 +
1.36 +
1.37 +/////////////////////////////////////////////////////////////////////////////////////////
1.38 +// -----> CLogServSession (source)
1.39 +/////////////////////////////////////////////////////////////////////////////////////////
1.40 +
1.41 +CLogServSession::CLogServSession(TLogServSessionId aSessionId,
1.42 + MLogServSessionLifetimeObserver& aObserver,
1.43 + MLogServBackupInterface& aBackupInterface,
1.44 + MLogServTaskInterface& aTaskInterface,
1.45 + MLogServOperationManager& aOperationManager,
1.46 + MLogServDatabaseChangeInterface& aChangeInterface,
1.47 + MLogServDatabaseTransactionInterface& aDatabase) :
1.48 + iSessionId(aSessionId),
1.49 + iObserver(aObserver),
1.50 + iBackupInterface(aBackupInterface),
1.51 + iTaskInterface(aTaskInterface),
1.52 + iOperationManager(aOperationManager),
1.53 + iChangeInterface(aChangeInterface),
1.54 + iDatabase(aDatabase),
1.55 + iViewList(KLogViewListGranuality),
1.56 + iPendingGlobalChanges(KLogServPendingGlobalChangesArrayGranularity)
1.57 + {
1.58 + iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventCreated);
1.59 + }
1.60 +
1.61 +CLogServSession::~CLogServSession()
1.62 + {
1.63 + LOGTEXT3("CLogServSession::~CLogServSession() - client logging off: %S, %d", &iClientThreadName, iSessionId);
1.64 +
1.65 + // Set second parameter to not complete the message, otherwise if the client has died a KERN-EXEC 44 will be generated.
1.66 + iOperationManager.OMCancel(iSessionId, EFalse);
1.67 +
1.68 + delete iPackage;
1.69 + delete iNotify;
1.70 +
1.71 + iChangeInterface.DCIRequestChangeNotificationsCancel(*this);
1.72 + //
1.73 + iViewList.ResetAndDestroy();
1.74 + iViewList.Close();
1.75 + iPendingGlobalChanges.Close();
1.76 + //
1.77 + iObserver.SLOHandleEvent(Id(), MLogServSessionLifetimeObserver::ELogServSessionEventDestroyed);
1.78 +
1.79 + LOGTEXT2("CLogServSession::~CLogServSession() - client dead %d", iSessionId);
1.80 + LOGTEXT("");
1.81 + }
1.82 +
1.83 +/////////////////////////////////////////////////////////////////////////////////////////
1.84 +/////////////////////////////////////////////////////////////////////////////////////////
1.85 +/////////////////////////////////////////////////////////////////////////////////////////
1.86 +
1.87 +void CLogServSession::DCOHandleGlobalChangeEventL(const TLogServDatabaseChangeDefinition& aChange)
1.88 + {
1.89 + if (iExtendedNotificationRequested)
1.90 + User::LeaveIfError(iPendingGlobalChanges.Append(aChange));
1.91 + ExtendedNotifyCompleteL(KErrNone);
1.92 + }
1.93 +
1.94 +/////////////////////////////////////////////////////////////////////////////////////////
1.95 +/////////////////////////////////////////////////////////////////////////////////////////
1.96 +/////////////////////////////////////////////////////////////////////////////////////////
1.97 +void CLogServSession::CreateL()
1.98 + {
1.99 + iPackage = CLogPackage::NewL();
1.100 +
1.101 + // Request change notifications
1.102 + iChangeInterface.DCIRequestChangeNotificationsL(*this);
1.103 + }
1.104 +
1.105 +//
1.106 +// Handle a client request.
1.107 +//
1.108 +// Leaving is handled by CLogServ::RunError() which reports the error code to the client
1.109 +// Note: operation add themselves to the server active queue in their constructor
1.110 +// The server active object owns them and deletes them when necessary
1.111 +// So the iffy looking code below won't actually leak memory
1.112 +//
1.113 +void CLogServSession::ServiceL(const RMessage2& aMessage)
1.114 + {
1.115 + LOGTEXT3("CLogServSession::ServiceL(%S, %d)", &iClientThreadName, aMessage.Function());
1.116 +
1.117 + switch(aMessage.Function())
1.118 + {
1.119 + /**
1.120 + * Overall operation management
1.121 + */
1.122 + case ELogOperationGetResult:
1.123 + case ELogOperationCancel:
1.124 + case ELogOperationInitiate:
1.125 + ServiceOperationFunctionL(aMessage);
1.126 + break;
1.127 +
1.128 + /**
1.129 + * Notification related
1.130 + */
1.131 + case ELogNotify:
1.132 + {
1.133 + if (!iNotify)
1.134 + {
1.135 + iNotify = CLogNotify::NewL(iBackupInterface, iChangeInterface, Server().Priority());
1.136 +
1.137 + #ifdef LOGGING_ENABLED
1.138 + iNotify->SetClientThreadName(iClientThreadName);
1.139 + #endif
1.140 + }
1.141 +
1.142 + if (!iNotify->IsActive())
1.143 + {
1.144 + const TTimeIntervalMicroSeconds32 delayTime = reinterpret_cast<TInt>(aMessage.Ptr0());
1.145 +
1.146 + //Validate time value
1.147 + if(delayTime.Int() < 0)
1.148 + {
1.149 + User::Leave(KErrArgument);
1.150 + }
1.151 + iNotify->Notify(delayTime, aMessage);
1.152 + }
1.153 + else
1.154 + ::PanicClientL(aMessage, ELogAlreadyActive19);
1.155 + break;
1.156 + }
1.157 + case ELogNotifyCancel:
1.158 + {
1.159 + if (iNotify)
1.160 + iNotify->Cancel();
1.161 + aMessage.Complete(KErrCancel);
1.162 + break;
1.163 + }
1.164 + case ELogNotifyExtended:
1.165 + {
1.166 + if (iExtendedNotificationMessage == RMessage2())
1.167 + {
1.168 + iExtendedNotificationMessage = aMessage;
1.169 + iExtendedNotificationRequested = ETrue;
1.170 + }
1.171 + else
1.172 + ::PanicClientL(aMessage, ELogExtendedMessageAlreadyActive);
1.173 + break;
1.174 + }
1.175 + case ELogNotifyExtendedCancel:
1.176 + {
1.177 + if (iExtendedNotificationMessage != RMessage2())
1.178 + ExtendedNotifyCompleteL(KErrCancel);
1.179 + //
1.180 + iExtendedNotificationRequested = EFalse;
1.181 + iPendingGlobalChanges.Reset();
1.182 + iPendingGlobalChanges.GranularCompress();
1.183 + //
1.184 + aMessage.Complete(KErrCancel);
1.185 + break;
1.186 + }
1.187 +
1.188 + /**
1.189 + * View functionality
1.190 + */
1.191 + case ELogViewCreate:
1.192 + case ELogViewDelete:
1.193 + case ELogViewCount:
1.194 + case ELogViewOperationInitiate:
1.195 + case ELogViewChangeNotificationsRequest:
1.196 + case ELogViewChangeNotificationsCancel:
1.197 + case ELogViewFetchChanges:
1.198 + case ELogViewNotifyLockStatusChange:
1.199 + case ELogViewNotifyLockStatusChangeCancel:
1.200 + ServiceViewFunctionL(aMessage);
1.201 + break;
1.202 +
1.203 + /**
1.204 + * Misc. (debug) functionality
1.205 + */
1.206 +#ifdef _DEBUG
1.207 + case ELogMakeTransient:
1.208 + {
1.209 + Server().MakeTransient((TBool)aMessage.Ptr0());
1.210 + aMessage.Complete(KErrNone);
1.211 + break;
1.212 + }
1.213 + case ELogIsServerReady:
1.214 + {
1.215 + const TBool serverReady = (iBackupInterface.BIErrorValueForCurrentState() == KErrNone);
1.216 + aMessage.Complete(serverReady);
1.217 + break;
1.218 + }
1.219 + case ELogSetHeapFail:
1.220 + {
1.221 + User::__DbgSetAllocFail(RHeap::EUser, RHeap::TAllocFail(aMessage.Int0()),aMessage.Int1());
1.222 + aMessage.Complete(KErrNone);
1.223 + break;
1.224 + }
1.225 +#endif// _DEBUG
1.226 + /**
1.227 + * Unknown operations
1.228 + */
1.229 + default:
1.230 + ::PanicClientL(aMessage, ELogIllegalFunction);
1.231 + break;
1.232 + }
1.233 + }
1.234 +
1.235 +/**
1.236 +If aError is KErrBadDescriptor, then panic the client, else - default error handling.
1.237 +KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad
1.238 +descriptor to the server.
1.239 +*/
1.240 +void CLogServSession::ServiceError(const RMessage2& aMessage,TInt aError)
1.241 + {
1.242 + if(aError == KErrBadDescriptor)
1.243 + {
1.244 + //The __LOGPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call
1.245 + //from a leaving call will terminate the server.
1.246 + aMessage.Panic(KLogServ, ELogBadDescriptor);
1.247 + }
1.248 + CSession2::ServiceError(aMessage, aError);
1.249 + }
1.250 +
1.251 +/////////////////////////////////////////////////////////////////////////////////////////
1.252 +/////////////////////////////////////////////////////////////////////////////////////////
1.253 +/////////////////////////////////////////////////////////////////////////////////////////
1.254 +
1.255 +CLogServServer& CLogServSession::Server() const
1.256 + {
1.257 + return *static_cast<CLogServServer*>(const_cast<CServer2*>(CSession2::Server()));
1.258 + }
1.259 +
1.260 +/////////////////////////////////////////////////////////////////////////////////////////
1.261 +/////////////////////////////////////////////////////////////////////////////////////////
1.262 +/////////////////////////////////////////////////////////////////////////////////////////
1.263 +
1.264 +
1.265 +CLogServViewBase& CLogServSession::ViewByIdL(TUint32 aViewId)
1.266 + {
1.267 + const TInt index = ViewPositionById(aViewId);
1.268 + User::LeaveIfError(index);
1.269 + return *iViewList[index];
1.270 + }
1.271 +
1.272 +TInt CLogServSession::ViewPositionById(TUint32 aViewId) const
1.273 + {
1.274 + const TInt count = iViewList.Count();
1.275 + for(TInt i=0; i<count; i++)
1.276 + {
1.277 + const CLogServViewBase& view = *iViewList[i];
1.278 + if (view.ViewId() == aViewId)
1.279 + return i;
1.280 + }
1.281 + return KErrNotFound;
1.282 + }
1.283 +
1.284 +
1.285 +void CLogServSession::ReadClientServerDataL(TLogClientServerData& aClientServerData,
1.286 + const RMessage2 &aMessage, TInt aMinOperation, TInt aMaxOperation)
1.287 + {
1.288 +
1.289 + TInt length = aMessage.GetDesLengthL(0);
1.290 + if(length != sizeof(TLogClientServerData))
1.291 + {
1.292 + User::Leave(KErrBadDescriptor);
1.293 + }
1.294 +
1.295 + TPckg<TLogClientServerData> pData(aClientServerData);
1.296 + aMessage.ReadL(0, pData);
1.297 +
1.298 + //Validate Operation Type
1.299 + if((aClientServerData.iOperationType < aMinOperation) ||
1.300 + (aClientServerData.iOperationType > aMaxOperation))
1.301 + {
1.302 + User::Leave(KErrArgument);
1.303 + }
1.304 + }
1.305 +
1.306 +void CLogServSession::ServiceViewFunctionL(const RMessage2& aMessage)
1.307 + {
1.308 + switch(aMessage.Function())
1.309 + {
1.310 + case ELogViewCreate:
1.311 + {
1.312 + iViewList.ReserveL(iViewList.Count() + 1);
1.313 + // Type is first parameter, view id is second
1.314 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.315 + const TLogViewType type = static_cast<TLogViewType>(aMessage.Int1());
1.316 +
1.317 + //Validate type value
1.318 + if((type < ELogViewTypeEvent)||(type > ELogViewTypeDuplicate))
1.319 + {
1.320 + User::Leave(KErrArgument);
1.321 + }
1.322 +
1.323 + // Ask the factory to create it
1.324 + CLogServViewBase* view = LogServFactory::NewViewL(type, id, iDatabase, iBackupInterface, *iPackage, aMessage);
1.325 + TInt err = iViewList.Append(view);
1.326 + __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
1.327 + aMessage.Complete(err);
1.328 + break;
1.329 + }
1.330 + case ELogViewDelete:
1.331 + {
1.332 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.333 + TInt indexAndError = ViewPositionById(id);
1.334 + if (indexAndError >= 0)
1.335 + {
1.336 + delete iViewList[indexAndError];
1.337 + iViewList.Remove(indexAndError);
1.338 + indexAndError = KErrNone;
1.339 + }
1.340 + aMessage.Complete(indexAndError);
1.341 + break;
1.342 + }
1.343 + case ELogViewCount:
1.344 + {
1.345 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.346 + CLogServViewBase& view = ViewByIdL(id);
1.347 + const TInt count = view.Count();
1.348 + aMessage.Complete(count);
1.349 + break;
1.350 + }
1.351 + case ELogViewOperationInitiate:
1.352 + {
1.353 + // We don't allow any operations during a backup
1.354 + iBackupInterface.BIValidateStateForDatabaseOperationL();
1.355 + //
1.356 + TLogClientServerData clientServerData;
1.357 + ReadClientServerDataL(clientServerData,aMessage,
1.358 + ELogOperationViewSetup, ELogOperationViewWindowFetch);
1.359 +
1.360 + //
1.361 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int1());
1.362 + CLogServViewBase& view = ViewByIdL(id);
1.363 +
1.364 + // Create operation. Operations are owned by the operation manager (they are added to a queue)
1.365 + // when the objects are created, so this does not leak any memory.
1.366 + CLogServOperationBase* operation = LogServFactory::NewViewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId, view);
1.367 + (void) operation;
1.368 + break;
1.369 + }
1.370 + case ELogViewChangeNotificationsRequest:
1.371 + {
1.372 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.373 + CLogServViewBase& view = ViewByIdL(id);
1.374 + view.RequestChangeNotifications(aMessage);
1.375 + break;
1.376 + }
1.377 + case ELogViewChangeNotificationsCancel:
1.378 + {
1.379 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.380 + CLogServViewBase& view = ViewByIdL(id);
1.381 + view.RequestChangeNotificationsCancel();
1.382 + aMessage.Complete(KErrNone);
1.383 + break;
1.384 + }
1.385 + case ELogViewFetchChanges:
1.386 + {
1.387 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.388 + CLogServViewBase& view = ViewByIdL(id);
1.389 + view.RequestChangesL(aMessage);
1.390 + aMessage.Complete(KErrNone);
1.391 + break;
1.392 + }
1.393 + case ELogViewNotifyLockStatusChange:
1.394 + {
1.395 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.396 + CLogServViewBase& view = ViewByIdL(id);
1.397 + view.RequestLockStatusChanges(aMessage);
1.398 + break;
1.399 + }
1.400 + case ELogViewNotifyLockStatusChangeCancel:
1.401 + {
1.402 + const TLogViewId id = static_cast<TLogViewId>(aMessage.Int0());
1.403 + CLogServViewBase& view = ViewByIdL(id);
1.404 + view.RequestLockStatusChangesCancel();
1.405 + aMessage.Complete(KErrNone);
1.406 + break;
1.407 + }
1.408 + }
1.409 + }
1.410 +
1.411 +void CLogServSession::ServiceOperationFunctionL(const RMessage2& aMessage)
1.412 + {
1.413 + // We don't allow any operations during a backup
1.414 + iBackupInterface.BIValidateStateForDatabaseOperationL();
1.415 + //
1.416 + TLogClientServerData clientServerData;
1.417 + ReadClientServerDataL(clientServerData,aMessage, ELogOperationEventAdd,ELogOperationMaintain);
1.418 + //
1.419 + const TInt function = aMessage.Function();
1.420 + //
1.421 + const TLogOperationId& operationId = clientServerData.iOperationId;
1.422 + #ifdef LOGGING_ENABLED
1.423 + const TLogOperationType& operationType = clientServerData.iOperationType;
1.424 + #endif
1.425 + LOGTEXT4("CLogServSession::ServiceOperationFunctionL() - Operation function for client %S: Id: %d, Type: %d", &iClientThreadName, operationId, operationType);
1.426 + //
1.427 + switch(function)
1.428 + {
1.429 + case ELogOperationGetResult:
1.430 + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - getting result");
1.431 + iOperationManager.OMGetResultL(operationId, iSessionId, aMessage);
1.432 + aMessage.Complete(KErrNone);
1.433 + break;
1.434 + case ELogOperationCancel:
1.435 + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - cancelling");
1.436 + iOperationManager.OMCancel(operationId, iSessionId, ETrue);
1.437 + aMessage.Complete(KErrCancel);
1.438 + break;
1.439 + case ELogOperationInitiate:
1.440 + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - initiating");
1.441 + // Create operation. Operations are owned by the operation manager (they are added to a queue)
1.442 + // when the objects are created, so this does not leak any memory.
1.443 + CLogServOperationBase* operation = LogServFactory::NewOperationL(clientServerData, iTaskInterface, iOperationManager, aMessage, *iPackage, iSessionId);
1.444 + (void) operation;
1.445 + break;
1.446 + }
1.447 + LOGTEXT("CLogServSession::ServiceOperationFunctionL() - end");
1.448 + }
1.449 +
1.450 +void CLogServSession::ExtendedNotifyCompleteL(TInt aCompletionCode)
1.451 + {
1.452 + const TInt count = iPendingGlobalChanges.Count();
1.453 + if (iExtendedNotificationMessage != RMessage2() && (count || aCompletionCode < KErrNone))
1.454 + {
1.455 + if (aCompletionCode >= KErrNone && count)
1.456 + {
1.457 + const TLogServDatabaseChangeDefinition& change = iPendingGlobalChanges[0];
1.458 + //
1.459 + const TPckgBuf<TInt> pContext(change.iChangeType.iUid);
1.460 + const TPckg<TInt> pParam1(change.iChangeParam1);
1.461 + const TPckg<TInt> pParam2(change.iChangeParam2);
1.462 + const TPckg<TInt> pParam3(change.iChangeParam3);
1.463 + //
1.464 + iExtendedNotificationMessage.WriteL(0, pContext);
1.465 + iExtendedNotificationMessage.WriteL(1, pParam1);
1.466 + iExtendedNotificationMessage.WriteL(2, pParam2);
1.467 + iExtendedNotificationMessage.WriteL(3, pParam3);
1.468 + //
1.469 + iPendingGlobalChanges.Remove(0);
1.470 + }
1.471 + //
1.472 + iExtendedNotificationMessage.Complete(aCompletionCode);
1.473 + }
1.474 + }