/usr/include/thunderbird/mozilla/DataStorage.h is in thunderbird-dev 1:52.8.0-1~deb8u1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_DataStorage_h
#define mozilla_DataStorage_h
#include "mozilla/Monitor.h"
#include "mozilla/Mutex.h"
#include "mozilla/StaticPtr.h"
#include "nsCOMPtr.h"
#include "nsDataHashtable.h"
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsITimer.h"
#include "nsRefPtrHashtable.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
class DataStorageItem;
}
/**
* DataStorage is a threadsafe, generic, narrow string-based hash map that
* persists data on disk and additionally handles temporary and private data.
* However, if used in a context where there is no profile directory, data
* will not be persisted.
*
* Its lifecycle is as follows:
* - Allocate with a filename (this is or will eventually be a file in the
* profile directory, if the profile exists).
* - Call Init() from the main thread. This spins off an asynchronous read
* of the backing file.
* - Eventually observers of the topic "data-storage-ready" will be notified
* with the backing filename as the data in the notification when this
* has completed.
* - Should the profile directory not be available, (e.g. in xpcshell),
* DataStorage will not initially read any persistent data. The
* "data-storage-ready" event will still be emitted. This follows semantics
* similar to the permission manager and allows tests that test
* unrelated components to proceed without a profile.
* - When any persistent data changes, a timer is initialized that will
* eventually asynchronously write all persistent data to the backing file.
* When this happens, observers will be notified with the topic
* "data-storage-written" and the backing filename as the data.
* It is possible to receive a "data-storage-written" event while there exist
* pending persistent data changes. However, those changes will cause the
* timer to be reinitialized and another "data-storage-written" event will
* be sent.
* - When DataStorage observes the topic "profile-before-change" in
* anticipation of shutdown, all persistent data is synchronously written to
* the backing file. The worker thread responsible for these writes is then
* disabled to prevent further writes to that file (the delayed-write timer
* is cancelled when this happens).
* - For testing purposes, the preference "test.datastorage.write_timer_ms" can
* be set to cause the asynchronous writing of data to happen more quickly.
* - To prevent unbounded memory and disk use, the number of entries in each
* table is limited to 1024. Evictions are handled in by a modified LRU scheme
* (see implementation comments).
* - NB: Instances of DataStorage have long lifetimes because they are strong
* observers of events and won't go away until the observer service does.
*
* For each key/value:
* - The key must be a non-empty string containing no instances of '\t' or '\n'
* (this is a limitation of how the data is stored and will be addressed in
* the future).
* - The key must have a length no more than 256.
* - The value must not contain '\n' and must have a length no more than 1024.
* (the length limits are to prevent unbounded disk and memory usage)
*/
/**
* Data that is DataStorage_Persistent is saved on disk. DataStorage_Temporary
* and DataStorage_Private are not saved. DataStorage_Private is meant to
* only be set and accessed from private contexts. It will be cleared upon
* observing the event "last-pb-context-exited".
*/
enum DataStorageType {
DataStorage_Persistent,
DataStorage_Temporary,
DataStorage_Private
};
class DataStorage : public nsIObserver
{
typedef dom::DataStorageItem DataStorageItem;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
// If there is a profile directory, there is or will eventually be a file
// by the name specified by aFilename there.
static already_AddRefed<DataStorage> Get(const nsString& aFilename);
static already_AddRefed<DataStorage> GetIfExists(const nsString& aFilename);
// Initializes the DataStorage. Must be called before using.
// aDataWillPersist returns whether or not data can be persistently saved.
nsresult Init(/*out*/bool& aDataWillPersist);
// Given a key and a type of data, returns a value. Returns an empty string if
// the key is not present for that type of data. If Get is called before the
// "data-storage-ready" event is observed, it will block. NB: It is not
// currently possible to differentiate between missing data and data that is
// the empty string.
nsCString Get(const nsCString& aKey, DataStorageType aType);
// Give a key, value, and type of data, adds an entry as appropriate.
// Updates existing entries.
nsresult Put(const nsCString& aKey, const nsCString& aValue,
DataStorageType aType);
// Given a key and type of data, removes an entry if present.
void Remove(const nsCString& aKey, DataStorageType aType);
// Removes all entries of all types of data.
nsresult Clear();
// Read all of the data items.
void GetAll(InfallibleTArray<DataStorageItem>* aItems);
private:
explicit DataStorage(const nsString& aFilename);
virtual ~DataStorage();
class Writer;
class Reader;
class Entry
{
public:
Entry();
bool UpdateScore();
uint32_t mScore;
int32_t mLastAccessed; // the last accessed time in days since the epoch
nsCString mValue;
};
// Utility class for scanning tables for an entry to evict.
class KeyAndEntry
{
public:
nsCString mKey;
Entry mEntry;
};
typedef nsDataHashtable<nsCStringHashKey, Entry> DataStorageTable;
typedef nsRefPtrHashtable<nsStringHashKey, DataStorage> DataStorages;
void WaitForReady();
nsresult AsyncWriteData(const MutexAutoLock& aProofOfLock);
nsresult AsyncReadData(bool& aHaveProfileDir,
const MutexAutoLock& aProofOfLock);
nsresult AsyncSetTimer(const MutexAutoLock& aProofOfLock);
nsresult DispatchShutdownTimer(const MutexAutoLock& aProofOfLock);
static nsresult ValidateKeyAndValue(const nsCString& aKey,
const nsCString& aValue);
static void TimerCallback(nsITimer* aTimer, void* aClosure);
void SetTimer();
void ShutdownTimer();
void NotifyObservers(const char* aTopic);
bool GetInternal(const nsCString& aKey, Entry* aEntry, DataStorageType aType,
const MutexAutoLock& aProofOfLock);
nsresult PutInternal(const nsCString& aKey, Entry& aEntry,
DataStorageType aType,
const MutexAutoLock& aProofOfLock);
void MaybeEvictOneEntry(DataStorageType aType,
const MutexAutoLock& aProofOfLock);
DataStorageTable& GetTableForType(DataStorageType aType,
const MutexAutoLock& aProofOfLock);
void ReadAllFromTable(DataStorageType aType,
InfallibleTArray<DataStorageItem>* aItems,
const MutexAutoLock& aProofOfLock);
Mutex mMutex; // This mutex protects access to the following members:
DataStorageTable mPersistentDataTable;
DataStorageTable mTemporaryDataTable;
DataStorageTable mPrivateDataTable;
nsCOMPtr<nsIThread> mWorkerThread;
nsCOMPtr<nsIFile> mBackingFile;
nsCOMPtr<nsITimer> mTimer; // All uses after init must be on the worker thread
uint32_t mTimerDelay; // in milliseconds
bool mPendingWrite; // true if a write is needed but hasn't been dispatched
bool mShuttingDown;
bool mInitCalled; // Indicates that Init() has been called.
// (End list of members protected by mMutex)
Monitor mReadyMonitor; // Do not acquire this at the same time as mMutex.
bool mReady; // Indicates that saved data has been read and Get can proceed.
const nsString mFilename;
static StaticAutoPtr<DataStorages> sDataStorages;
};
} // namespace mozilla
#endif // mozilla_DataStorage_h
|