LCOV - code coverage report
Current view: top level - startupcache - StartupCache.h (source / functions) Hit Total Coverage
Test: output.info Lines: 2 15 13.3 %
Date: 2017-07-14 16:53:18 Functions: 2 28 7.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*-  Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef StartupCache_h_
       7             : #define StartupCache_h_
       8             : 
       9             : #include "nsClassHashtable.h"
      10             : #include "nsComponentManagerUtils.h"
      11             : #include "nsTArray.h"
      12             : #include "nsZipArchive.h"
      13             : #include "nsIStartupCache.h"
      14             : #include "nsITimer.h"
      15             : #include "nsIMemoryReporter.h"
      16             : #include "nsIObserverService.h"
      17             : #include "nsIObserver.h"
      18             : #include "nsIOutputStream.h"
      19             : #include "nsIFile.h"
      20             : #include "mozilla/Attributes.h"
      21             : #include "mozilla/MemoryReporting.h"
      22             : #include "mozilla/StaticPtr.h"
      23             : #include "mozilla/UniquePtr.h"
      24             : 
      25             : /**
      26             :  * The StartupCache is a persistent cache of simple key-value pairs,
      27             :  * where the keys are null-terminated c-strings and the values are
      28             :  * arbitrary data, passed as a (char*, size) tuple.
      29             :  *
      30             :  * Clients should use the GetSingleton() static method to access the cache. It
      31             :  * will be available from the end of XPCOM init (NS_InitXPCOM3 in XPCOMInit.cpp),
      32             :  * until XPCOM shutdown begins. The GetSingleton() method will return null if the cache
      33             :  * is unavailable. The cache is only provided for libxul builds --
      34             :  * it will fail to link in non-libxul builds. The XPCOM interface is provided
      35             :  * only to allow compiled-code tests; clients should avoid using it.
      36             :  *
      37             :  * The API provided is very simple: GetBuffer() returns a buffer that was previously
      38             :  * stored in the cache (if any), and PutBuffer() inserts a buffer into the cache.
      39             :  * GetBuffer returns a new buffer, and the caller must take ownership of it.
      40             :  * PutBuffer will assert if the client attempts to insert a buffer with the same name as
      41             :  * an existing entry. The cache makes a copy of the passed-in buffer, so client
      42             :  * retains ownership.
      43             :  *
      44             :  * InvalidateCache() may be called if a client suspects data corruption
      45             :  * or wishes to invalidate for any other reason. This will remove all existing cache data.
      46             :  * Additionally, the static method IgnoreDiskCache() can be called if it is
      47             :  * believed that the on-disk cache file is itself corrupt. This call implicitly
      48             :  * calls InvalidateCache (if the singleton has been initialized) to ensure any
      49             :  * data already read from disk is discarded. The cache will not load data from
      50             :  * the disk file until a successful write occurs.
      51             :  *
      52             :  * Finally, getDebugObjectOutputStream() allows debug code to wrap an objectstream
      53             :  * with a debug objectstream, to check for multiply-referenced objects. These will
      54             :  * generally fail to deserialize correctly, unless they are stateless singletons or the
      55             :  * client maintains their own object data map for deserialization.
      56             :  *
      57             :  * Writes before the final-ui-startup notification are placed in an intermediate
      58             :  * cache in memory, then written out to disk at a later time, to get writes off the
      59             :  * startup path. In any case, clients should not rely on being able to GetBuffer()
      60             :  * data that is written to the cache, since it may not have been written to disk or
      61             :  * another client may have invalidated the cache. In other words, it should be used as
      62             :  * a cache only, and not a reliable persistent store.
      63             :  *
      64             :  * Some utility functions are provided in StartupCacheUtils. These functions wrap the
      65             :  * buffers into object streams, which may be useful for serializing objects. Note
      66             :  * the above caution about multiply-referenced objects, though -- the streams are just
      67             :  * as 'dumb' as the underlying buffers about multiply-referenced objects. They just
      68             :  * provide some convenience in writing out data.
      69             :  */
      70             : 
      71             : namespace mozilla {
      72             : 
      73             : namespace scache {
      74             : 
      75             : struct CacheEntry
      76             : {
      77             :   UniquePtr<char[]> data;
      78             :   uint32_t size;
      79             : 
      80             :   CacheEntry() : size(0) { }
      81             : 
      82             :   // Takes possession of buf
      83          64 :   CacheEntry(UniquePtr<char[]> buf, uint32_t len) : data(Move(buf)), size(len) { }
      84             : 
      85           0 :   ~CacheEntry()
      86           0 :   {
      87           0 :   }
      88             : 
      89           0 :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
      90           0 :     return mallocSizeOf(this) + mallocSizeOf(data.get());
      91             :   }
      92             : };
      93             : 
      94             : // We don't want to refcount StartupCache, and ObserverService wants to
      95             : // refcount its listeners, so we'll let it refcount this instead.
      96           1 : class StartupCacheListener final : public nsIObserver
      97             : {
      98           0 :   ~StartupCacheListener() {}
      99             :   NS_DECL_THREADSAFE_ISUPPORTS
     100             :   NS_DECL_NSIOBSERVER
     101             : };
     102             : 
     103             : class StartupCache : public nsIMemoryReporter
     104             : {
     105             : 
     106             : friend class StartupCacheListener;
     107             : friend class StartupCacheWrapper;
     108             : 
     109             : public:
     110             :   NS_DECL_THREADSAFE_ISUPPORTS
     111             :   NS_DECL_NSIMEMORYREPORTER
     112             : 
     113             :   // StartupCache methods. See above comments for a more detailed description.
     114             : 
     115             :   // Returns a buffer that was previously stored, caller takes ownership.
     116             :   nsresult GetBuffer(const char* id, UniquePtr<char[]>* outbuf, uint32_t* length);
     117             : 
     118             :   // Stores a buffer. Caller keeps ownership, we make a copy.
     119             :   nsresult PutBuffer(const char* id, const char* inbuf, uint32_t length);
     120             : 
     121             :   // Removes the cache file.
     122             :   void InvalidateCache();
     123             : 
     124             :   // Signal that data should not be loaded from the cache file
     125             :   static void IgnoreDiskCache();
     126             : 
     127             :   // In DEBUG builds, returns a stream that will attempt to check for
     128             :   // and disallow multiple writes of the same object.
     129             :   nsresult GetDebugObjectOutputStream(nsIObjectOutputStream* aStream,
     130             :                                       nsIObjectOutputStream** outStream);
     131             : 
     132             :   static StartupCache* GetSingleton();
     133             :   static void DeleteSingleton();
     134             : 
     135             :   // This measures all the heap memory used by the StartupCache, i.e. it
     136             :   // excludes the mapping.
     137             :   size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     138             : 
     139             :   size_t SizeOfMapping();
     140             : 
     141             :   // FOR TESTING ONLY
     142             :   nsresult ResetStartupWriteTimer();
     143             :   bool StartupWriteComplete();
     144             : private:
     145             :   StartupCache();
     146             :   virtual ~StartupCache();
     147             : 
     148             :   nsresult LoadArchive();
     149             :   nsresult Init();
     150             :   void WriteToDisk();
     151             :   void WaitOnWriteThread();
     152             : 
     153             :   static nsresult InitSingleton();
     154             :   static void WriteTimeout(nsITimer *aTimer, void *aClosure);
     155             :   static void ThreadedWrite(void *aClosure);
     156             : 
     157             :   nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
     158             :   nsTArray<nsCString> mPendingWrites;
     159             :   RefPtr<nsZipArchive> mArchive;
     160             :   nsCOMPtr<nsIFile> mFile;
     161             : 
     162             :   nsCOMPtr<nsIObserverService> mObserverService;
     163             :   RefPtr<StartupCacheListener> mListener;
     164             :   nsCOMPtr<nsITimer> mTimer;
     165             : 
     166             :   bool mStartupWriteInitiated;
     167             : 
     168             :   static StaticRefPtr<StartupCache> gStartupCache;
     169             :   static bool gShutdownInitiated;
     170             :   static bool gIgnoreDiskCache;
     171             :   PRThread *mWriteThread;
     172             : #ifdef DEBUG
     173             :   nsTHashtable<nsISupportsHashKey> mWriteObjectMap;
     174             : #endif
     175             : };
     176             : 
     177             : // This debug outputstream attempts to detect if clients are writing multiple
     178             : // references to the same object. We only support that if that object
     179             : // is a singleton.
     180             : #ifdef DEBUG
     181             : class StartupCacheDebugOutputStream final
     182             :   : public nsIObjectOutputStream
     183             : {
     184           0 :   ~StartupCacheDebugOutputStream() {}
     185             : 
     186             :   NS_DECL_ISUPPORTS
     187             :   NS_DECL_NSIOBJECTOUTPUTSTREAM
     188             : 
     189           0 :   StartupCacheDebugOutputStream (nsIObjectOutputStream* binaryStream,
     190             :                                    nsTHashtable<nsISupportsHashKey>* objectMap)
     191           0 :   : mBinaryStream(binaryStream), mObjectMap(objectMap) { }
     192             : 
     193           0 :   NS_FORWARD_SAFE_NSIBINARYOUTPUTSTREAM(mBinaryStream)
     194           0 :   NS_FORWARD_SAFE_NSIOUTPUTSTREAM(mBinaryStream)
     195             : 
     196             :   bool CheckReferences(nsISupports* aObject);
     197             : 
     198             :   nsCOMPtr<nsIObjectOutputStream> mBinaryStream;
     199             :   nsTHashtable<nsISupportsHashKey> *mObjectMap;
     200             : };
     201             : #endif // DEBUG
     202             : 
     203             : // XPCOM wrapper interface provided for tests only.
     204             : #define NS_STARTUPCACHE_CID \
     205             :       {0xae4505a9, 0x87ab, 0x477c, \
     206             :       {0xb5, 0x77, 0xf9, 0x23, 0x57, 0xed, 0xa8, 0x84}}
     207             : // contract id: "@mozilla.org/startupcache/cache;1"
     208             : 
     209           0 : class StartupCacheWrapper final
     210             :   : public nsIStartupCache
     211             : {
     212           0 :   ~StartupCacheWrapper() {}
     213             : 
     214             :   NS_DECL_THREADSAFE_ISUPPORTS
     215             :   NS_DECL_NSISTARTUPCACHE
     216             : 
     217             :   static StartupCacheWrapper* GetSingleton();
     218             :   static StartupCacheWrapper *gStartupCacheWrapper;
     219             : };
     220             : 
     221             : } // namespace scache
     222             : } // namespace mozilla
     223             : 
     224             : #endif //StartupCache_h_

Generated by: LCOV version 1.13