--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/leak/leak.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,169 @@
+// leak.cpp
+//
+// Copyright (c) 2007 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+#include "leak.h"
+#include <fshell/common.mmh>
+
+const TInt KMinChunkSize = 4 * 1024;
+const TInt KMaxChunkSize = 512 * 1024 * 1024;
+
+CCommandBase* CCmdLeak::NewLC()
+ {
+ CCmdLeak* self = new(ELeave) CCmdLeak();
+ CleanupStack::PushL(self);
+ self->BaseConstructL();
+ return self;
+ }
+
+CCmdLeak::~CCmdLeak()
+ {
+ iChunk.Close();
+ if (iChunkHeap)
+ {
+ iChunkHeap->Reset();
+ iChunkHeap->Close();
+ }
+ }
+
+CCmdLeak::CCmdLeak()
+ {
+ }
+
+const TDesC& CCmdLeak::Name() const
+ {
+ _LIT(KName, "leak");
+ return KName;
+ }
+
+void CCmdLeak::DoRunL()
+ {
+ if ((iAmount < 0) || (iIncrementAmount < 0))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ if (iArguments.IsPresent(0))
+ {
+ if (iIncrementAmount == 0)
+ {
+ iIncrementAmount = iAmount;
+ }
+ }
+ else
+ {
+ iAmount = KMaxTInt;
+ if (iIncrementAmount == 0)
+ {
+ iIncrementAmount = KMinChunkSize;
+ }
+ }
+
+ if (iUseHeap)
+ {
+ iChunkHeap = UserHeap::ChunkHeap(NULL, KMinChunkSize, 256*1024*1024);
+ if (!iChunkHeap) LeaveIfErr(KErrNoMemory, _L("Couldn't create chunk heap"));
+ }
+ else
+ {
+ if (iIncrementAmount & 4095) LeaveIfErr(KErrArgument, _L("increment-amount must be a multiple of 4096"));
+ TInt err = iChunk.CreateLocal(KMinChunkSize, KMaxChunkSize);
+ LeaveIfErr(err, _L("Failed to create local chunk"));
+ }
+
+ RIoConsoleWriteHandle stdout = Stdout();
+ stdout.SetCursorHeight(0);
+ TInt err = KErrNone;
+ do
+ {
+ err = LeakStep(Min(iIncrementAmount, iAmount - iCurrentLeak));
+ if (iVerbose)
+ {
+ Write(_L("\r"));
+ stdout.ClearToEndOfLine();
+ Printf(_L("Allocated %d: %d"), iCurrentLeak, err);
+ }
+ if (err && iRetry && iIncrementAmount > 4)
+ {
+ // Keep going with a smaller increment
+ err = KErrNone;
+ iIncrementAmount /= 2;
+ continue;
+ }
+
+ if (iRate > 0)
+ {
+ User::After(iRate * 1000);
+ }
+ }
+ while ((err == KErrNone) && (iCurrentLeak < iAmount));
+
+ if (err == KErrNoMemory)
+ {
+ Printf(_L("Out of memory. "));
+ }
+ else if (err)
+ {
+ Printf(_L("Error: %d. "), err);
+ }
+
+ Printf(_L("\r\nLeaked %d bytes. Press any key to exit (and free the memory).\r\n"), iCurrentLeak);
+
+ RIoConsoleReadHandle stdin = Stdin();
+ stdin.ReadKey();
+ }
+
+void CCmdLeak::OptionsL(RCommandOptionList& aOptions)
+ {
+ _LIT(KOptVerbose, "verbose");
+ aOptions.AppendBoolL(iVerbose, KOptVerbose);
+
+ _LIT(KOptIncrementAmount, "increment-amount");
+ aOptions.AppendIntL(iIncrementAmount, KOptIncrementAmount);
+
+ _LIT(KOptRate, "rate");
+ aOptions.AppendUintL(iRate, KOptRate);
+
+ _LIT(KOptUseHeap, "heap");
+ aOptions.AppendBoolL(iUseHeap, KOptUseHeap);
+
+ _LIT(KOptRetry, "retry");
+ aOptions.AppendBoolL(iRetry, KOptRetry);
+ }
+
+void CCmdLeak::ArgumentsL(RCommandArgumentList& aArguments)
+ {
+ _LIT(KArgAmount, "amount");
+ aArguments.AppendIntL(iAmount, KArgAmount);
+ }
+
+
+#ifdef EXE_BUILD
+EXE_BOILER_PLATE(CCmdLeak)
+#endif
+
+TInt CCmdLeak::LeakStep(TInt aAmount)
+ {
+ TInt err = KErrNone;
+ if (iChunkHeap)
+ {
+ TAny* cell = iChunkHeap->Alloc(aAmount);
+ if (!cell) err = KErrNoMemory;
+ }
+ else
+ {
+ 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
+ else err = iChunk.Adjust(iCurrentLeak + aAmount);
+ }
+
+ if (!err) iCurrentLeak += aAmount;
+ return err;
+ }