1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /**
8  * IOInterposeObserver recording statistics of main-thread I/O during execution,
9  * aimed at consumption by TelemetryImpl
10  */
11 
12 #ifndef TelemetryIOInterposeObserver_h__
13 #define TelemetryIOInterposeObserver_h__
14 
15 #include "core/TelemetryCommon.h"
16 #include "jsapi.h"
17 #include "mozilla/IOInterposer.h"
18 #include "nsBaseHashtable.h"
19 #include "nsClassHashtable.h"
20 #include "nsHashKeys.h"
21 #include "nsTArray.h"
22 #include "nsTHashtable.h"
23 
24 namespace mozilla {
25 namespace Telemetry {
26 
27 class TelemetryIOInterposeObserver : public IOInterposeObserver {
28   /** File-level statistics structure */
29   struct FileStats {
FileStatsFileStats30     FileStats()
31         : creates(0), reads(0), writes(0), fsyncs(0), stats(0), totalTime(0) {}
32     uint32_t creates; /** Number of create/open operations */
33     uint32_t reads;   /** Number of read operations */
34     uint32_t writes;  /** Number of write operations */
35     uint32_t fsyncs;  /** Number of fsync operations */
36     uint32_t stats;   /** Number of stat operations */
37     double totalTime; /** Accumulated duration of all operations */
38   };
39 
40   struct SafeDir {
SafeDirSafeDir41     SafeDir(const nsAString& aPath, const nsAString& aSubstName)
42         : mPath(aPath), mSubstName(aSubstName) {}
SizeOfExcludingThisSafeDir43     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
44       return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
45              mSubstName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
46     }
47     nsString mPath;      /** Path to the directory */
48     nsString mSubstName; /** Name to substitute with */
49   };
50 
51  public:
52   explicit TelemetryIOInterposeObserver(nsIFile* aXreDir);
53 
54   /**
55    * An implementation of Observe that records statistics of all
56    * file IO operations.
57    */
58   void Observe(Observation& aOb) override;
59 
60   /**
61    * Reflect recorded file IO statistics into Javascript
62    */
63   bool ReflectIntoJS(JSContext* cx, JS::Handle<JSObject*> rootObj);
64 
65   /**
66    * Adds a path for inclusion in main thread I/O report.
67    * @param aPath Directory path
68    * @param aSubstName Name to substitute for aPath for privacy reasons
69    */
70   void AddPath(const nsAString& aPath, const nsAString& aSubstName);
71 
72   /**
73    * Get size of hash table with file stats
74    */
75   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
76 
77   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
78 
79  private:
80   enum Stage { STAGE_STARTUP = 0, STAGE_NORMAL, STAGE_SHUTDOWN, NUM_STAGES };
NextStage(Stage aStage)81   static inline Stage NextStage(Stage aStage) {
82     switch (aStage) {
83       case STAGE_STARTUP:
84         return STAGE_NORMAL;
85       case STAGE_NORMAL:
86         return STAGE_SHUTDOWN;
87       case STAGE_SHUTDOWN:
88         return STAGE_SHUTDOWN;
89       default:
90         return NUM_STAGES;
91     }
92   }
93 
94   struct FileStatsByStage {
95     FileStats mStats[NUM_STAGES];
96   };
97   typedef nsBaseHashtableET<nsStringHashKey, FileStatsByStage> FileIOEntryType;
98 
99   // Statistics for each filename
100   Common::AutoHashtable<FileIOEntryType> mFileStats;
101   // Container for allowed directories
102   nsTArray<SafeDir> mSafeDirs;
103   Stage mCurStage;
104 
105   /**
106    * Reflect a FileIOEntryType object to a Javascript property on obj with
107    * filename as key containing array:
108    * [totalTime, creates, reads, writes, fsyncs, stats]
109    */
110   static bool ReflectFileStats(FileIOEntryType* entry, JSContext* cx,
111                                JS::Handle<JSObject*> obj);
112 };
113 
114 }  // namespace Telemetry
115 }  // namespace mozilla
116 
117 #endif  // TelemetryIOInterposeObserver_h__
118