commands/cloggerconfig/cloggerconfig.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/cloggerconfig/cloggerconfig.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,433 @@
+// cloggerconfig.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 <fshell/ioutils.h>
+#include <fshell/clogger.h>
+#include <BADESCA.H>
+#include <e32msgqueue.h>
+
+using namespace IoUtils;
+
+class CCmdCloggerConfig : public CCommandBase
+	{
+public:
+	static CCommandBase* NewLC();
+	~CCmdCloggerConfig();
+private:
+	CCmdCloggerConfig();
+	void PrintLogL();
+	void GetBackupFileNameL(TFileName& aName);
+	void SetAllL(TBool aEnabled);
+private: // From CCommandBase.
+	virtual const TDesC& Name() const;
+	virtual void DoRunL();
+	virtual void ArgumentsL(RCommandArgumentList& aArguments);
+	virtual void OptionsL(RCommandOptionList& aOptions);
+private:
+	RClogger iClogger;
+	RCloggerLogConsumer iLogGetter;
+	TUint iGlobalOptions;
+	TBool iPersist;
+	TBool iReset;
+	HBufC* iTagName;
+	TUint iEnabledMask;
+	TUint iRotateOptions;
+	TBool iRotate;
+	TBool iFollow;
+	TBool iWipe;
+	TInt iNumBuffers;
+	TInt iBufferSize;
+	RBuf iTempBuffer;
+	TBool iRdebug;
+	TBool iBackup;
+	TBool iRestore;
+	TBool iDisableAll;
+	TBool iEnableAll;
+	};
+
+
+CCommandBase* CCmdCloggerConfig::NewLC()
+	{
+	CCmdCloggerConfig* self = new(ELeave) CCmdCloggerConfig();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdCloggerConfig::~CCmdCloggerConfig()
+	{
+	iClogger.Close();
+	iLogGetter.Close();
+	delete iTagName;
+	iTempBuffer.Close();
+	}
+
+CCmdCloggerConfig::CCmdCloggerConfig()
+	{
+	}
+
+const TDesC& CCmdCloggerConfig::Name() const
+	{
+	_LIT(KName, "cloggerconfig");	
+	return KName;
+	}
+
+#define WRITEIF(opt, flag) if (opt & (RClogger :: flag)) { Write(_L(#flag)); Write(_L(" ")); }
+
+void CCmdCloggerConfig::DoRunL()
+	{
+	if (iEnableAll && iDisableAll)
+		{
+		LeaveIfErr(KErrArgument, _L("Can't enable and disable all tags"));
+		}
+
+	User::LeaveIfError(iClogger.Connect());
+
+	TBool listSettings = ETrue;
+	if (iReset)
+		{
+		iClogger.ResetSettings();
+		listSettings = EFalse;
+		}
+	
+	if (iOptions.IsPresent(&iGlobalOptions))
+		{
+		iClogger.SetGlobalOptions(iGlobalOptions);
+		listSettings = EFalse;
+		}
+	if (iOptions.IsPresent(&iRotateOptions))
+		{
+		TInt n;
+		iClogger.GetRotateBehaviour(&n);
+		iClogger.SetRotateBehaviour(n, iRotateOptions);
+		listSettings = EFalse;
+		}
+	if (iNumBuffers || iBufferSize)
+		{
+		if (iNumBuffers == 0)
+			{
+			// Need to read it in as we have to set both at once.  Bad API...
+			iClogger.GetRamBufferSize(&iNumBuffers);
+			}
+		if (iBufferSize == 0)
+			{
+			// Same reason as above
+			iBufferSize = iClogger.GetRamBufferSize(NULL);
+			}
+		iClogger.SetRamBufferSize(iBufferSize, iNumBuffers);
+		listSettings = EFalse;
+		}
+	if (iPersist || iBackup || iRestore)
+		{
+		// We don't do anything here, we take action at the end of this function
+		listSettings = EFalse;
+		}
+	if (iRotate)
+		{
+		TFileName name;
+		TInt err = iClogger.Rotate(name);
+		Printf(_L("Log rotated to %S\r\n"), &name);
+		if (err) PrintError(err, _L("Rotate returned error"));
+		listSettings = EFalse;
+		}
+	else if (iWipe)
+		{
+		TInt oldLogs;
+		TUint rotopt = iClogger.GetRotateBehaviour(&oldLogs);
+		iClogger.SetRotateBehaviour(KMaxTInt, RClogger::EDoNothingSpecial); // Change rotate behaviour temporarily
+		
+		TFileName name;
+		TInt err = iClogger.Rotate(name);
+		//Printf(_L("Log rotated to %S\r\n"), &name);
+		if (err) PrintError(err, _L("Rotate returned error"));
+		else
+			{
+			err = FsL().Delete(name);
+
+			iClogger.SetRotateBehaviour(oldLogs, rotopt); // Restore old behaviour
+			LeaveIfErr(err, _L("Couldn't remove wiped log %S"), &name);
+			}
+
+		listSettings = EFalse;
+		}
+
+	if (iDisableAll)
+		{
+		SetAllL(EFalse);
+		listSettings = EFalse;
+		}
+
+	if (iEnableAll)
+		{
+		SetAllL(ETrue);
+		listSettings = EFalse;
+		}
+
+	if (iRdebug)
+		{
+		TUint opts = iClogger.GetGlobalOptions();
+		opts |= RClogger::ERedirectRDebugPrintToClogger;
+		iClogger.SetGlobalOptions(opts);
+		
+		PrintLogL();
+		}
+
+	if (iFollow)
+		{
+		PrintLogL(); // Does not return
+		}
+
+	if (iArguments.IsPresent(1))
+		{
+		// Set
+		TInt err = iClogger.SetEnabled(*iTagName, iEnabledMask);
+		if (err == KErrNotFound)
+			{
+			PrintError(err, _L("Tag does not exist, couldn't set it. (NOTE: This behaviour will be changed in the future so you can set tags that haven't been created yet!)"));
+			User::Leave(KErrNotFound);
+			}
+		LeaveIfErr(err, _L("Couldn't enable tag."));
+		listSettings = EFalse;
+		}
+	else if (iArguments.IsPresent(0))
+		{
+		// Get
+		TUint32 e = iClogger.IsEnabled(*iTagName);
+		Printf(_L("Tag [%S] enabled: 0x%x\r\n"), iTagName, e);
+		listSettings = EFalse;
+		}
+	
+	if (listSettings)
+		{
+		// List global options
+		TUint globalOptions = iClogger.GetGlobalOptions();
+		Printf(_L("Global options: 0x%x ( "), globalOptions);
+		if (!globalOptions)
+			{
+			Write(_L("None "));
+			}
+		else
+			{
+			WRITEIF(globalOptions, EBufferLog);
+			WRITEIF(globalOptions, EMirrorToRDebugPrint);
+			WRITEIF(globalOptions, EMirrorToBluetooth);
+			WRITEIF(globalOptions, EMirrorToMessageQueue);
+			WRITEIF(globalOptions, ERedirectRDebugPrintToClogger);
+			WRITEIF(globalOptions, EDisableFileWriter);
+			}
+		Write(_L(")\r\n"));
+
+		// List rotate options
+		TInt numLogs = 0;
+		TUint rotateBehaviour = iClogger.GetRotateBehaviour(&numLogs);
+		Printf(_L("Number of rotated logs to keep: %i\r\n"), numLogs);
+		Printf(_L("Rotate behaviour: 0x%x ( "), rotateBehaviour);
+		if (!rotateBehaviour)
+			{
+			Write(_L("EDoNothingSpecial "));
+			}
+		else
+			{
+			WRITEIF(rotateBehaviour, ECopyRotatedToExternalMedia);
+			WRITEIF(rotateBehaviour, EAutoRotateAtStartup);
+			WRITEIF(rotateBehaviour, ECompressRotatedLogs);
+			}
+		Write(_L(")\r\n"));
+
+		// List buffer size
+		TInt numBuffers = 0;
+		TInt bufSize = iClogger.GetRamBufferSize(&numBuffers);
+		Printf(_L("Number of RAM buffers: %i\r\n"), numBuffers);
+		Printf(_L("Size of RAM buffers: %i\r\n"), bufSize);
+
+		// List tags
+		CDesC16Array* tags = NULL;
+		RBuf8 enabled;
+		iClogger.GetTagStatesL(tags, enabled);
+		TInt count = enabled.Size() / 4;
+		if (count) Printf(_L("\r\n"));
+		for (TInt i = 0; i < count; i++)
+			{
+			TPtrC tag = tags->operator[](i);
+			TUint32 e = ((TUint32*)enabled.Ptr())[i];
+			Printf(_L("Tag [%S] enabled: 0x%x\r\n"), &tag, e);
+			}
+		delete tags;
+		enabled.Close();
+		}
+
+	if (iPersist)
+		{
+		iClogger.PersistSettings();
+		}
+
+	if (iBackup)
+		{
+		// Args should be: --exec 'cp -ro C:\Private\10202be9\persists\10272efd.cre E:\Private\10202be9\persists\10272efd.cre'
+		TFileName args;
+		GetBackupFileNameL(args);
+
+		TInt len = args.Length();
+		args.Append(args);
+		args.Append('\'');
+		args[0] = 'C';
+		args.Insert(len, _L(" "));
+		args.Insert(0, _L("--exec 'cp -ro "));
+		
+		RChildProcess shell;
+		shell.CreateL(_L("fshell.exe"), args, IoSession(), Stdin(), Stdout(), Stderr());
+		CleanupClosePushL(shell);
+		TRequestStatus stat;
+		shell.Run(stat);
+		User::WaitForRequest(stat);
+		LeaveIfErr(stat.Int(), _L("Failed to copy cenrep file"));
+		CleanupStack::PopAndDestroy(&shell);
+
+		const TPtrC name = args.Right(len+1);
+		Printf(_L("Settings backed up to '%S, use --restore option to restore.\r\n"), &name);
+		}
+	else if (iRestore)
+		{
+		TFileName args;
+		GetBackupFileNameL(args);
+		TInt len = args.Length();
+		//TEntry e;
+		//LeaveIfErr(FsL().Entry(args, e), _L("No backup file found"));
+		// Args should be: --exec 'cp E:\Private\10202be9\persists\10272efd.cre C:\Private\10202be9\persists\10272efd.cre'
+		args.Append(args);
+		args.Append('\'');
+		args[len] = 'C';
+		args.Insert(len, _L(" "));
+		args.Insert(0, _L("--exec 'cp -ro "));
+		
+		RChildProcess shell;
+		shell.CreateL(_L("fshell.exe"), args, IoSession(), Stdin(), Stdout(), Stderr());
+		CleanupClosePushL(shell);
+		TRequestStatus stat;
+		shell.Run(stat);
+		User::WaitForRequest(stat);
+		LeaveIfErr(stat.Int(), _L("Failed to copy cenrep file"));
+		CleanupStack::PopAndDestroy(&shell);
+
+		Printf(_L("Settings restored. You must reboot or restart cloggerserver to get the new settings\r\n"));
+		}
+	}
+
+void CCmdCloggerConfig::ArgumentsL(RCommandArgumentList& aArguments)
+	{
+	aArguments.AppendStringL(iTagName, _L("tag_name"));
+	aArguments.AppendUintL(iEnabledMask, _L("enabled_mask"));
+	}
+
+void CCmdCloggerConfig::OptionsL(RCommandOptionList& aOptions)
+	{
+	aOptions.AppendUintL(iGlobalOptions, _L("set-global"));
+	aOptions.AppendBoolL(iPersist, _L("persist"));
+	aOptions.AppendBoolL(iReset, _L("reset"));
+	aOptions.AppendUintL(iRotateOptions, _L("set-rotate"));
+	aOptions.AppendBoolL(iRotate, _L("rotate"));
+	aOptions.AppendBoolL(iFollow, _L("follow"));
+	aOptions.AppendIntL(iNumBuffers, _L("num-buffers"));
+	aOptions.AppendUintL((TUint&)iBufferSize, _L("buffer-size"));
+	aOptions.AppendBoolL(iWipe, _L("wipe"));
+	aOptions.AppendBoolL(iRdebug, _L("rdebug"));
+	aOptions.AppendBoolL(iBackup, _L("backup"));
+	aOptions.AppendBoolL(iRestore, _L("restore"));
+	aOptions.AppendBoolL(iDisableAll, _L("disable-all"));
+	aOptions.AppendBoolL(iEnableAll, _L("enable-all"));
+	}
+
+
+EXE_BOILER_PLATE(CCmdCloggerConfig)
+
+void CCmdCloggerConfig::PrintLogL()
+	{
+	// Because of how RCloggerLogConsumer API works we can only 'see' things in the clogger ChunkForBufs. This however
+	// won't be where the descriptor being logged will be unless buffered logging is enabled. To fix properly,
+	// the rdebug chunk would need to be mapped into the client, and also the Server's iSessionTempBuf and 
+	// CDebugRouterClient's iTempBuf would need to be moved to an accessible chunk
+	TUint opts = iClogger.GetGlobalOptions();
+	opts |= RClogger::EBufferLog;
+	iClogger.SetGlobalOptions(opts);
+
+	LeaveIfErr(iLogGetter.Connect(), _L("Couldn't connect to RCloggerLogConsumer"));
+	iTempBuffer.CreateL(2048);
+
+	TRequestStatus stat;
+	TPtrC8 logLine;
+	while (ETrue)
+		{
+		iLogGetter.GetNextLog(stat, logLine);
+		User::WaitForRequest(stat);
+		LeaveIfErr(stat.Int(), _L("GetNextLog returned error"));
+		
+		// CCommandBase::Write doesn't take 8-bit descriptor so write in iTempBuffer-sized chunks
+		TPtrC8 lineFrag(logLine);
+		const TInt buflen = iTempBuffer.MaxLength();
+		while (lineFrag.Length())
+			{
+			TPtrC8 frag = lineFrag.Left(buflen);
+			iTempBuffer.Copy(frag);
+			//HexDumpL(frag, iTempBuffer);
+			TInt err = Stdout().Write(iTempBuffer);
+			LeaveIfErr(err, _L("Write of %d bytes (%d total) failed"), iTempBuffer.Length(), logLine.Length());
+			lineFrag.Set(lineFrag.Mid(frag.Length()));
+			}
+		}
+	}
+
+void CCmdCloggerConfig::GetBackupFileNameL(TFileName& aName)
+	{
+	TInt err = KErrNone;
+	TInt theDrive = KErrNotFound;
+	// Figure out the first external media device
+	for (TInt drive = EDriveA; drive <= EDriveZ; drive++)
+		{
+		TVolumeInfo info;
+		err = FsL().Volume(info, drive);
+		if (err == KErrNone)
+			{
+			//LogNote(ELogDisks, _L8("Found drive %c iDrivaAtt=0x%x iType=0x%x"), 'A' + drive, info.iDrive.iDriveAtt, info.iDrive.iType);
+			}
+		if (err == KErrNone && ((info.iDrive.iDriveAtt & KDriveAttRemovable) || info.iDrive.iType == EMediaHardDisk)) // Added the check for hard disk so we can use _epoc_drive_d in the emulator
+			{
+			// Found one
+			theDrive = drive;
+			break;
+			}
+		}
+	LeaveIfErr(theDrive, _L("Couldn't find a removable drive to backup on to"));
+
+	aName = _L("?:\\private\\10202be9\\persists\\10272efd.cre");
+	TChar c;
+	Fs().DriveToChar(theDrive, c);
+	aName[0] = c;
+	}
+
+void CCmdCloggerConfig::SetAllL(TBool aEnabled)
+	{
+	CDesC16Array* tags = NULL;
+	RBuf8 states;
+	CleanupClosePushL(states);
+	iClogger.GetTagStatesL(tags, states);
+	CleanupStack::PushL(tags);
+	if (aEnabled)
+		{
+		states.Fill(TChar(0xff));
+		}
+	else
+		{
+		states.FillZ();
+		}
+	iClogger.SetTagStatesL(tags, states);
+	CleanupStack::PopAndDestroy(2, &states);
+	}