commands/leak/leak.cpp
changeset 0 7f656887cf89
child 31 d0e1c40de386
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // leak.cpp
       
     2 // 
       
     3 // Copyright (c) 2007 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "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 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include "leak.h"
       
    14 #include <fshell/common.mmh>
       
    15 
       
    16 const TInt KMinChunkSize = 4 * 1024;
       
    17 const TInt KMaxChunkSize = 512 * 1024 * 1024;
       
    18 
       
    19 CCommandBase* CCmdLeak::NewLC()
       
    20 	{
       
    21 	CCmdLeak* self = new(ELeave) CCmdLeak();
       
    22 	CleanupStack::PushL(self);
       
    23 	self->BaseConstructL();
       
    24 	return self;
       
    25 	}
       
    26 
       
    27 CCmdLeak::~CCmdLeak()
       
    28 	{
       
    29 	iChunk.Close();
       
    30 	if (iChunkHeap)
       
    31 		{
       
    32 		iChunkHeap->Reset();
       
    33 		iChunkHeap->Close();
       
    34 		}
       
    35 	}
       
    36 
       
    37 CCmdLeak::CCmdLeak()
       
    38 	{
       
    39 	}
       
    40 
       
    41 const TDesC& CCmdLeak::Name() const
       
    42 	{
       
    43 	_LIT(KName, "leak");
       
    44 	return KName;
       
    45 	}
       
    46 
       
    47 void CCmdLeak::DoRunL()
       
    48 	{
       
    49 	if ((iAmount < 0) || (iIncrementAmount < 0))
       
    50 		{
       
    51 		User::Leave(KErrArgument);
       
    52 		}
       
    53 
       
    54 	if (iArguments.IsPresent(0))
       
    55 		{
       
    56 		if (iIncrementAmount == 0)
       
    57 			{
       
    58 			iIncrementAmount = iAmount;
       
    59 			}
       
    60 		}
       
    61 	else
       
    62 		{
       
    63 		iAmount = KMaxTInt;
       
    64 		if (iIncrementAmount == 0)
       
    65 			{
       
    66 			iIncrementAmount = KMinChunkSize;
       
    67 			}
       
    68 		}
       
    69 
       
    70 	if (iUseHeap)
       
    71 		{
       
    72 		iChunkHeap = UserHeap::ChunkHeap(NULL, KMinChunkSize, 256*1024*1024);
       
    73 		if (!iChunkHeap) LeaveIfErr(KErrNoMemory, _L("Couldn't create chunk heap"));
       
    74 		}
       
    75 	else
       
    76 		{
       
    77 		if (iIncrementAmount & 4095) LeaveIfErr(KErrArgument, _L("increment-amount must be a multiple of 4096"));
       
    78 		TInt err = iChunk.CreateLocal(KMinChunkSize, KMaxChunkSize);
       
    79 		LeaveIfErr(err, _L("Failed to create local chunk"));
       
    80 		}
       
    81 
       
    82 	RIoConsoleWriteHandle stdout = Stdout();
       
    83 	stdout.SetCursorHeight(0);
       
    84 	TInt err = KErrNone;
       
    85 	do
       
    86 		{
       
    87 		err = LeakStep(Min(iIncrementAmount, iAmount - iCurrentLeak));
       
    88 		if (iVerbose)
       
    89 			{
       
    90 			Write(_L("\r"));
       
    91 			stdout.ClearToEndOfLine();
       
    92 			Printf(_L("Allocated %d: %d"), iCurrentLeak, err);
       
    93 			}
       
    94 		if (err && iRetry && iIncrementAmount > 4)
       
    95 			{
       
    96 			// Keep going with a smaller increment
       
    97 			err = KErrNone;
       
    98 			iIncrementAmount /= 2;
       
    99 			continue;
       
   100 			}
       
   101 
       
   102 		if (iRate > 0)
       
   103 			{
       
   104 			User::After(iRate * 1000);
       
   105 			}
       
   106 		}
       
   107 		while ((err == KErrNone) && (iCurrentLeak < iAmount));
       
   108 
       
   109 	if (err == KErrNoMemory)
       
   110 		{
       
   111 		Printf(_L("Out of memory. "));
       
   112 		}
       
   113 	else if (err)
       
   114 		{
       
   115 		Printf(_L("Error: %d. "), err);
       
   116 		}
       
   117 
       
   118 	Printf(_L("\r\nLeaked %d bytes. Press any key to exit (and free the memory).\r\n"), iCurrentLeak);
       
   119 
       
   120 	RIoConsoleReadHandle stdin = Stdin();
       
   121 	stdin.ReadKey();
       
   122 	}
       
   123 
       
   124 void CCmdLeak::OptionsL(RCommandOptionList& aOptions)
       
   125 	{
       
   126 	_LIT(KOptVerbose, "verbose");
       
   127 	aOptions.AppendBoolL(iVerbose, KOptVerbose);
       
   128 
       
   129 	_LIT(KOptIncrementAmount, "increment-amount");
       
   130 	aOptions.AppendIntL(iIncrementAmount, KOptIncrementAmount);
       
   131 
       
   132 	_LIT(KOptRate, "rate");
       
   133 	aOptions.AppendUintL(iRate, KOptRate);
       
   134 
       
   135 	_LIT(KOptUseHeap, "heap");
       
   136 	aOptions.AppendBoolL(iUseHeap, KOptUseHeap);
       
   137 
       
   138 	_LIT(KOptRetry, "retry");
       
   139 	aOptions.AppendBoolL(iRetry, KOptRetry);
       
   140 	}
       
   141 
       
   142 void CCmdLeak::ArgumentsL(RCommandArgumentList& aArguments)
       
   143 	{
       
   144 	_LIT(KArgAmount, "amount");
       
   145 	aArguments.AppendIntL(iAmount, KArgAmount);
       
   146 	}
       
   147 
       
   148 
       
   149 #ifdef EXE_BUILD
       
   150 EXE_BOILER_PLATE(CCmdLeak)
       
   151 #endif
       
   152 
       
   153 TInt CCmdLeak::LeakStep(TInt aAmount)
       
   154 	{
       
   155 	TInt err = KErrNone;
       
   156 	if (iChunkHeap)
       
   157 		{
       
   158 		TAny* cell = iChunkHeap->Alloc(aAmount);
       
   159 		if (!cell) err = KErrNoMemory;
       
   160 		}
       
   161 	else
       
   162 		{
       
   163 		if (aAmount < 4096) err = KErrNoMemory; // implies we're retrying - unlike the others that keep retrying down to 4 bytes, we have to stop at page granularity
       
   164 		else err = iChunk.Adjust(iCurrentLeak + aAmount);
       
   165 		}
       
   166 
       
   167 	if (!err) iCurrentLeak += aAmount;
       
   168 	return err;
       
   169 	}