diff -r 000000000000 -r 7f656887cf89 commands/ffstrace/ffstraceplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/ffstrace/ffstraceplugin.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,230 @@ +// ffstraceplugin.cpp +// +// Copyright (c) 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 +#include +#include +#include + +//#define LOG_FUNC() RDebug::Printf(__PRETTY_FUNCTION__) +//#define LOG(args...) RDebug::Printf(args) +//#define LOGW(args...) RDebug::Print(args) +#define LOG_FUNC() +#define LOG(args...) +#define LOGW(args...) + + +NONSHARABLE_CLASS(CFfsTracerPluginFactory) : public CFsPluginFactory + { +public: + static CFfsTracerPluginFactory* NewL(); + + // from CFsPluginFactory + virtual TInt Install(); + virtual CFsPlugin* NewPluginL(); + virtual TInt UniquePosition(); + +private: + CFfsTracerPluginFactory(); + }; + +NONSHARABLE_CLASS(CFfsTracerFsPlugin) : public CFsPlugin + { +public: + static CFfsTracerFsPlugin* NewL(); + virtual ~CFfsTracerFsPlugin(); + + // from CFsPlugin + virtual void InitialiseL(); + TInt SessionDisconnect(CSessionFs* aSession); + virtual TInt DoRequestL(TFsPluginRequest& aRequest); + virtual CFsPluginConn* NewPluginConnL(); +private: + CFfsTracerFsPlugin(); + }; + +class CFfsTracerFsPluginConn : public CFsPluginConn + { +public: + CFfsTracerFsPluginConn(); + + // from CFsPluginConn + virtual TInt DoControl(CFsPluginConnRequest& aRequest); + virtual void DoRequest(CFsPluginConnRequest& aRequest); + virtual void DoCancel(TInt aReqMask); + }; + +extern "C" EXPORT_C CFsPluginFactory* CreateFileSystem() + { + return CFfsTracerPluginFactory::NewL(); + } + +CFfsTracerPluginFactory* CFfsTracerPluginFactory::NewL() + { + return(new(ELeave) CFfsTracerPluginFactory()); + } + +CFfsTracerPluginFactory::CFfsTracerPluginFactory() + { + } + +_LIT(KFfsTracerPluginName, "FfsTracePlugin"); + +TInt CFfsTracerPluginFactory::Install() + { + LOG_FUNC(); + iSupportedDrives = 0x7FFFFFF; // KPluginSupportAllDrives | KPluginVersionTwo. Not specified symbolically to be compatible with fileservers that didn't support v2 plugins + + TInt err; + err = SetName(&KFfsTracerPluginName); + LOG(" returned %d", err); + return err; + } + +CFsPlugin* CFfsTracerPluginFactory::NewPluginL() + { + return CFfsTracerFsPlugin::NewL(); + } + +TInt CFfsTracerPluginFactory::UniquePosition() + { + return 1; // Isn't used, apparently + } + +// + +CFfsTracerFsPluginConn::CFfsTracerFsPluginConn() + { + } + +TInt CFfsTracerFsPluginConn::DoControl(CFsPluginConnRequest& /*aRequest*/) + { + return KErrNone; + } + +void CFfsTracerFsPluginConn::DoRequest(CFsPluginConnRequest& /*aRequest*/) + { + } + +void CFfsTracerFsPluginConn::DoCancel(TInt /*aReqMask*/) + { + } + +// + +CFfsTracerFsPlugin* CFfsTracerFsPlugin::NewL() + { + return new(ELeave) CFfsTracerFsPlugin(); + } + +CFfsTracerFsPlugin::CFfsTracerFsPlugin() + { + LOG_FUNC(); + } + +static const TFsMessage KMessages[] = + { + EFsDelete, + EFsRename, + EFsReplace, + EFsEntry, + EFsFileSubClose, + EFsFileOpen, + EFsFileCreate, + EFsFileReplace, + EFsFileTemp, + EFsFileRename, + }; +static const TInt KMessageCount = sizeof(KMessages) / sizeof(TFsMessage); + +CFfsTracerFsPlugin::~CFfsTracerFsPlugin() + { + LOG_FUNC(); + for (TInt i = 0; i < KMessageCount; i++) + { + UnregisterIntercept(KMessages[i], CFsPlugin::EPrePostIntercept); + } + } + +void CFfsTracerFsPlugin::InitialiseL() + { + // intercept all calls at start + for (TInt i = 0; i < KMessageCount; i++) + { + RegisterIntercept(KMessages[i], CFsPlugin::EPrePostIntercept); + } + } + +TInt CFfsTracerFsPlugin::SessionDisconnect(CSessionFs* /*aSession*/) + { + // CSessionFs is a private class! It's in the main file server and + // has no exported methods! What's the use of passing it here? + return KErrNone; + } + +CFsPluginConn* CFfsTracerFsPlugin::NewPluginConnL() + { + LOG_FUNC(); + return new(ELeave) CFfsTracerFsPluginConn(); + } + +TInt CFfsTracerFsPlugin::DoRequestL(TFsPluginRequest& aRequest) + { + // This is where it all happens + + TInt subcat = 0; + TInt fn = aRequest.Function(); + // Map from FS opcodes to the compacted btrace ones + switch (fn) + { + case EFsDelete: subcat = BTrace::EFfsDelete; break; + case EFsRename: subcat = BTrace::EFfsRename; break; + case EFsReplace: subcat = BTrace::EFfsReplace; break; + case EFsEntry: subcat = BTrace::EFfsEntry; break; + case EFsFileSubClose: subcat = BTrace::EFfsFileSubClose; break; + case EFsFileOpen: subcat = BTrace::EFfsFileOpen; break; + case EFsFileCreate: subcat = BTrace::EFfsFileCreate; break; + case EFsFileReplace: subcat = BTrace::EFfsFileReplace; break; + case EFsFileTemp: subcat = BTrace::EFfsFileTemp; break; + case EFsFileRename: subcat = BTrace::EFfsFileRename; break; + default: + // An operation we're not interested in + return KErrNone; + } + if (aRequest.IsPostOperation()) subcat |= BTrace::EFfsPost; + + TBuf<513> name; // Twice as big as a max filename because for renames we need it to fit two TFileNames + GetName(&aRequest, name); + + if (fn == EFsRename || fn == EFsFileRename) + { + name.Append(TChar(0)); + TPtr newName((TUint16*)(name.Ptr() + name.Length()), 0, name.MaxLength() - name.Length()); + GetNewName(&aRequest, newName); + LOGW(_L("new name is %S"), &newName); + name.SetLength(name.Length() + newName.Length()); + } + + // Only try to use request.Message() if it's a valid handle + TUint threadId = 0xFFFFFFFFu; + if(aRequest.Message().Handle() != KNullHandle) + { + RThread clientThread; + aRequest.Message().Client(clientThread, EOwnerThread); + threadId = clientThread.Id(); + clientThread.Close(); + } + + BTraceBig(BTrace::EFfsTrace, subcat, threadId, name.Ptr(), name.Size()); + + return KErrNone; + }