sysresmonitoring/oommonitor/src/oomclientrequestqueue.cpp
branchRCL_3
changeset 1 0fdb7f6b0309
child 2 7645e9ce10dc
equal deleted inserted replaced
0:2e3d3ce01487 1:0fdb7f6b0309
       
     1 /*
       
     2 * Copyright (c) 2006 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:  COomClientRequestQueue.cpp.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "oomclientrequestqueue.h"
       
    21 #include "oomtraces.h"
       
    22 #include "oomsubscribehelper.h"
       
    23 #include "oompanic.h"
       
    24 #include "oommemorymonitor.h"
       
    25 #include <UikonInternalPSKeys.h>
       
    26 
       
    27 const TInt KOomWatchDogStatusIdle = -1;
       
    28 const TInt KClientTimeToFreeMemory = 500000; //microseconds
       
    29 
       
    30 COomClientRequestQueue::COomClientRequestQueue(CMemoryMonitor& aMonitor)
       
    31     :iQueue(_FOFF(TClientRequest,iLink)),
       
    32     iMonitor(aMonitor)
       
    33     {
       
    34     FUNC_LOG;
       
    35     }
       
    36 
       
    37 COomClientRequestQueue::~COomClientRequestQueue()
       
    38     {
       
    39     FUNC_LOG;
       
    40     
       
    41     if (iWatchdogStatusSubscriber)
       
    42         {
       
    43         iWatchdogStatusSubscriber->StopSubscribe();
       
    44         }
       
    45     iWatchdogStatusProperty.Close();
       
    46     delete iWatchdogStatusSubscriber;
       
    47 
       
    48     if (iClientRequestTimer)
       
    49         {
       
    50         iClientRequestTimer->Cancel();
       
    51         }
       
    52     delete iClientRequestTimer;
       
    53     
       
    54     TClientRequest* request;
       
    55     TSglQueIter<TClientRequest> iter(iQueue);
       
    56     iter.SetToFirst(); 
       
    57     while (iter)
       
    58         {
       
    59         request = iter++;
       
    60         iQueue.Remove(*request);
       
    61         delete request;
       
    62         };
       
    63     }
       
    64 
       
    65 COomClientRequestQueue* COomClientRequestQueue::NewL(CMemoryMonitor& aMonitor)
       
    66     {
       
    67     FUNC_LOG;
       
    68     
       
    69     COomClientRequestQueue* self = new (ELeave) COomClientRequestQueue(aMonitor);
       
    70     CleanupStack::PushL(self);
       
    71     self->ConstructL();
       
    72     CleanupStack::Pop(self); 
       
    73     return self;
       
    74     }
       
    75 
       
    76 void COomClientRequestQueue::ConstructL()
       
    77     {
       
    78     FUNC_LOG;
       
    79     
       
    80     TInt err = iWatchdogStatusProperty.Attach(KPSUidUikon, KUikOOMWatchdogStatus);
       
    81 
       
    82     TRACES1("COomClientRequestQueue::ConstructL: KUikOOMWatchdogStatus err = %d", err);
       
    83     
       
    84     err = iWatchdogStatusProperty.Set(KOomWatchDogStatusIdle);
       
    85     
       
    86     iWatchdogStatusSubscriber = new (ELeave) CSubscribeHelper(TCallBack(WatchdogStatusStatusChanged, this), iWatchdogStatusProperty);
       
    87     iWatchdogStatusSubscriber->Subscribe();
       
    88 
       
    89     
       
    90     iClientRequestTimer = COomClientRequestTimer::NewL(*this);    
       
    91     }
       
    92 
       
    93 void COomClientRequestQueue::RequestFreeMemoryL(const RMessage2& aMessage)
       
    94     {
       
    95     FUNC_LOG;
       
    96     
       
    97     TClientRequest* request = new (ELeave) TClientRequest(EClientServerRequestFreeMemory, aMessage);
       
    98     CleanupStack::PushL(request);
       
    99     AddClientRequestL(*request);
       
   100     CleanupStack::Pop(request);
       
   101     }
       
   102 
       
   103 void COomClientRequestQueue::RequestOptionalRamL(const RMessage2& aMessage)
       
   104     {
       
   105     FUNC_LOG;
       
   106     
       
   107     TClientRequest* request = new (ELeave) TClientRequest(EClientServerRequestOptionalRam, aMessage);
       
   108     CleanupStack::PushL(request);
       
   109     AddClientRequestL(*request);
       
   110     CleanupStack::Pop(request);
       
   111     }
       
   112 
       
   113 TInt COomClientRequestQueue::WatchdogStatusStatusChanged(TAny* aPtr)
       
   114     {
       
   115     FUNC_LOG;
       
   116 
       
   117     COomClientRequestQueue* self = static_cast<COomClientRequestQueue*>(aPtr);
       
   118     if (self)
       
   119         {
       
   120         self->HandleWatchdogStatusCallBack();
       
   121         }
       
   122     return KErrNone;
       
   123     }
       
   124 
       
   125 void COomClientRequestQueue::HandleWatchdogStatusCallBack()
       
   126     {
       
   127     FUNC_LOG;
       
   128 
       
   129     // Someone has set the key to request some free memory.
       
   130     TInt memoryRequested = 0;
       
   131     iWatchdogStatusProperty.Get(memoryRequested);
       
   132 
       
   133     // Try to free the RAM.
       
   134     if (memoryRequested >= 1)
       
   135         {
       
   136         TClientRequest request = TClientRequest(EPublishAndSubscribe, memoryRequested);
       
   137         TRAP_IGNORE(AddClientRequestL(request));
       
   138         }
       
   139     // Set the key back to KOomWatchDogStatusIdle to indicate we're done.
       
   140     iWatchdogStatusProperty.Set(KOomWatchDogStatusIdle);
       
   141     }
       
   142 
       
   143 // The new request is added to the queue, then we have the following conditions: 
       
   144 // 1. A client request is currently being processed
       
   145 // 2. The last client request completed less than KClientTimeToFreeMemory microseconds ago -> start the timer
       
   146 // 3. The timer has already been started
       
   147 // 4. none of the above -> process this request
       
   148 void COomClientRequestQueue::AddClientRequestL(TClientRequest& request)
       
   149     {
       
   150     FUNC_LOG;
       
   151     
       
   152     iQueue.AddLast(request);
       
   153  
       
   154     if ( !iClientRequestActive && !iClientRequestTimer->IsActive() )
       
   155         {
       
   156         TTime now;
       
   157         now.UniversalTime();
       
   158         TInt64 interval64 = (now.MicroSecondsFrom(iLastClientCompletedTime)).Int64();
       
   159         TRACES3("COomClientRequestQueue::AddClientRequestL: now = %Ld, iLastClientCompletedTime = %Ld, interval64 = %Ld",
       
   160                 now.Int64(), iLastClientCompletedTime.Int64(), interval64);
       
   161                
       
   162         if ( interval64 < 0)        
       
   163             {
       
   164             //If the system time is moved backwards we lose the information about when the last request was 
       
   165             //made, so we wait for KClientTimeToFreeMemory microseconds
       
   166             iClientRequestTimer->After(TTimeIntervalMicroSeconds32(KClientTimeToFreeMemory));            
       
   167             }
       
   168         else if ( interval64 < KClientTimeToFreeMemory)
       
   169             {            
       
   170             //The last completed client is given KClientTimeToFreeMemory microseconds to allocate the memory 
       
   171             //it requested
       
   172             iClientRequestTimer->After(TTimeIntervalMicroSeconds32(interval64));
       
   173             }
       
   174         else 
       
   175             {
       
   176             StartClientRequestL();
       
   177             }        
       
   178         }
       
   179     }
       
   180 
       
   181 void COomClientRequestQueue::StartClientRequestL()
       
   182     {    
       
   183     FUNC_LOG;
       
   184     
       
   185     iClientRequestActive = ETrue;
       
   186 
       
   187     TClientRequest* request = iQueue.First();
       
   188 
       
   189     switch (request->iClientRequestType)
       
   190         {
       
   191         case EClientServerRequestOptionalRam:
       
   192             {
       
   193             TInt pluginId = request->iRequestFreeRamMessage.Int2();
       
   194             iMonitor.FreeOptionalRamL(request->iBytesRequested, pluginId);
       
   195             break;
       
   196             }
       
   197         case EClientServerRequestFreeMemory:
       
   198             iMonitor.RequestFreeMemoryL(request->iBytesRequested);
       
   199             break;
       
   200         case EPublishAndSubscribe:
       
   201             iMonitor.RequestFreeMemoryPandSL(request->iBytesRequested);
       
   202             break;
       
   203         default:
       
   204             OomMonitorPanic(KInvalidClientRequestType);
       
   205             break;
       
   206         }
       
   207     }
       
   208 
       
   209 CMemoryMonitor& COomClientRequestQueue::Monitor()
       
   210     {
       
   211     FUNC_LOG;
       
   212     
       
   213     return iMonitor;
       
   214     }
       
   215 
       
   216 TClientRequest::TClientRequest(TActionTriggerType aClientRequestType, TInt aBytesRequested)    
       
   217     : iClientRequestType(aClientRequestType), iBytesRequested(aBytesRequested)   
       
   218     {
       
   219     FUNC_LOG;
       
   220     }
       
   221 
       
   222 TClientRequest::TClientRequest(TActionTriggerType aClientRequestType, const RMessage2& aRequestFreeRam)    
       
   223     : iClientRequestType(aClientRequestType), iRequestFreeRamMessage(aRequestFreeRam)
       
   224     {
       
   225     FUNC_LOG;
       
   226     
       
   227     iBytesRequested = aRequestFreeRam.Int0();
       
   228     }
       
   229 
       
   230 void COomClientRequestQueue::ActionsCompleted(TInt aBytesFree, TBool aMemoryGood)
       
   231     {
       
   232     FUNC_LOG;
       
   233     
       
   234     if (iClientRequestActive)
       
   235         {
       
   236 #ifdef _DEBUG
       
   237         TSglQueIter<TClientRequest> iter(iQueue);
       
   238         iter.SetToFirst();
       
   239         TClientRequest* req;
       
   240         while (iter)
       
   241             {
       
   242             req = iter++;
       
   243             TActionTriggerType crt = req->iClientRequestType;
       
   244             TInt bytes = req->iBytesRequested;
       
   245             TRACES2("COomClientRequestQueue::ActionsCompleted Printing Queue: Type = %d, Bytes Requested = %d", crt, bytes);
       
   246             };
       
   247 #endif 
       
   248 
       
   249         __ASSERT_DEBUG(!iQueue.IsEmpty(), OomMonitorPanic(KClientQueueNotEmpty));        
       
   250         __ASSERT_DEBUG(!iClientRequestTimer->IsActive(), OomMonitorPanic(KClientRequestTimerActive));        
       
   251 
       
   252         TClientRequest* request = iQueue.First();
       
   253         RMessage2 message;
       
   254         
       
   255         switch (request->iClientRequestType)
       
   256             {
       
   257             case EClientServerRequestOptionalRam:
       
   258                 message = request->iRequestFreeRamMessage;
       
   259                 if (!message.IsNull())
       
   260                     {
       
   261                     TInt memoryAvailable = aBytesFree - iMonitor.GoodThreshold();
       
   262                     TInt minimumNeeded = message.Int1();
       
   263                     if (memoryAvailable >= minimumNeeded)
       
   264                         {
       
   265                         message.Complete(memoryAvailable);
       
   266                         }
       
   267                     else
       
   268                         {
       
   269                         message.Complete(KErrNoMemory);
       
   270                         }
       
   271                     }
       
   272                 break;
       
   273             case EClientServerRequestFreeMemory:
       
   274                 message = request->iRequestFreeRamMessage;
       
   275                 if (!message.IsNull())
       
   276                     {
       
   277                     // If memory available is greater than the requested RAM then complete with the amount of free memory, otherwise complete with KErrNoMemory
       
   278                     message.Complete(aMemoryGood ? KErrNone : KErrNoMemory);        
       
   279                     }
       
   280                 break;
       
   281             case EPublishAndSubscribe:
       
   282                 // No action required for P&S key
       
   283                 break; 
       
   284             default:
       
   285                 OomMonitorPanic(KInvalidClientRequestType);
       
   286                 break;
       
   287             }
       
   288             
       
   289         iClientRequestActive = EFalse;
       
   290         iQueue.Remove(*request);
       
   291         delete request;
       
   292 
       
   293         iLastClientCompletedTime.UniversalTime();
       
   294         
       
   295         if (!iQueue.IsEmpty())
       
   296             {
       
   297             //We give the client KClientTimeToFreeMemory microseconds to free the memory it requested before 
       
   298             //processing the next request
       
   299             iClientRequestTimer->After(TTimeIntervalMicroSeconds32(KClientTimeToFreeMemory));
       
   300             }
       
   301         }    
       
   302     }
       
   303 
       
   304 void COomClientRequestQueue::RequestTimerCallbackL()
       
   305     {
       
   306     FUNC_LOG;
       
   307     
       
   308     __ASSERT_DEBUG(!iQueue.IsEmpty(), OomMonitorPanic(KClientQueueNotEmpty));        
       
   309     
       
   310     StartClientRequestL();
       
   311     }
       
   312 
       
   313 COomClientRequestTimer* COomClientRequestTimer::NewL(COomClientRequestQueue& aQueue)
       
   314     {
       
   315     FUNC_LOG;
       
   316 
       
   317     COomClientRequestTimer* self = new (ELeave) COomClientRequestTimer(aQueue);
       
   318     CleanupStack::PushL(self);
       
   319     self->ConstructL();
       
   320     CleanupStack::Pop(self);
       
   321     return self;
       
   322     }
       
   323 
       
   324 COomClientRequestTimer::COomClientRequestTimer(COomClientRequestQueue& aQueue)
       
   325 : CTimer(CActive::EPriorityStandard), iClientRequestQueue(aQueue)
       
   326     {
       
   327     FUNC_LOG;
       
   328     
       
   329     CActiveScheduler::Add(this);
       
   330     }
       
   331 
       
   332 
       
   333 void COomClientRequestTimer::RunL()
       
   334     {
       
   335     FUNC_LOG;
       
   336     
       
   337     iClientRequestQueue.RequestTimerCallbackL();
       
   338     }
       
   339 
       
   340 
       
   341 
       
   342 
       
   343     
       
   344