mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 669410 - Make the url-classifier PrefixSet persistent on startup/shutdown. r=tony
This commit is contained in:
parent
8a3e4007ed
commit
3609767baa
@ -160,9 +160,9 @@
|
||||
#define NS_TYPEAHEADFIND_CID \
|
||||
{ 0xe7f70966, 0x9a37, 0x48d7, { 0x8a, 0xeb, 0x35, 0x99, 0x8f, 0x31, 0x09, 0x0e} }
|
||||
|
||||
// {6e9f759a-3f8d-4552-99ed-dbf0ea0a5f67}
|
||||
// {42ef1d52-3351-4973-98f8-d18f089bccfa}
|
||||
#define NS_URLCLASSIFIERPREFIXSET_CID \
|
||||
{ 0x6e9f759a, 0x3f8d, 0x4552, { 0x99, 0xed, 0xdb, 0xf0, 0xea, 0x0a, 0x5f, 0x67} }
|
||||
{ 0x42ef1d52, 0x3351, 0x4973, { 0x98, 0xf8, 0xd1, 0x8f, 0x08, 0x9b, 0xcc, 0xfa} }
|
||||
|
||||
// {5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6}
|
||||
#define NS_URLCLASSIFIERDBSERVICE_CID \
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIFile.idl"
|
||||
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, uuid(6e9f759a-3f8d-4552-99ed-dbf0ea0a5f67)]
|
||||
[scriptable, uuid(42ef1d52-3351-4973-98f8-d18f089bccfa)]
|
||||
interface nsIUrlClassifierPrefixSet : nsISupports
|
||||
{
|
||||
void setPrefixes([const, array, size_is(aLength)] in unsigned long aPrefixes,
|
||||
@ -12,4 +13,7 @@ interface nsIUrlClassifierPrefixSet : nsISupports
|
||||
boolean contains(in unsigned long aPrefix);
|
||||
boolean probe(in unsigned long aPrefix, inout boolean aReady);
|
||||
PRUint32 estimateSize();
|
||||
boolean isEmpty();
|
||||
void loadFromFile(in nsIFile aFile);
|
||||
void storeToFile(in nsIFile aFile);
|
||||
};
|
||||
|
@ -138,6 +138,9 @@ static const PRLogModuleInfo *gUrlClassifierDbServiceLog = nsnull;
|
||||
// and we start over.
|
||||
#define IMPLEMENTATION_VERSION 7
|
||||
|
||||
// Name of the persistent PrefixSet storage
|
||||
#define PREFIXSET_FILENAME "urlclassifier.pset"
|
||||
|
||||
#define MAX_HOST_COMPONENTS 5
|
||||
#define MAX_PATH_COMPONENTS 4
|
||||
|
||||
@ -1192,14 +1195,16 @@ private:
|
||||
PRInt32 count,
|
||||
nsTArray<nsUrlClassifierLookupResult>& results);
|
||||
|
||||
// Construct a Prefix Tree with known prefixes
|
||||
nsresult ConstructPrefixTree();
|
||||
// Construct a Prefix Set with known prefixes
|
||||
nsresult LoadPrefixSet(nsCOMPtr<nsIFile> & aFile);
|
||||
nsresult ConstructPrefixSet();
|
||||
|
||||
// Set the SQLite cache size
|
||||
nsresult SetCacheSize(mozIStorageConnection * aConnection,
|
||||
PRInt32 aCacheSize);
|
||||
|
||||
nsCOMPtr<nsIFile> mDBFile;
|
||||
nsCOMPtr<nsIFile> mPSFile;
|
||||
|
||||
nsCOMPtr<nsICryptoHash> mCryptoHash;
|
||||
|
||||
@ -1360,9 +1365,15 @@ nsUrlClassifierDBServiceWorker::Init(PRInt32 gethashNoise,
|
||||
|
||||
if (NS_FAILED(rv)) return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
rv = mDBFile->Clone(getter_AddRefs(mPSFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBFile->Append(NS_LITERAL_STRING(DATABASE_FILENAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mPSFile->Append(NS_LITERAL_STRING(PREFIXSET_FILENAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ResetUpdate();
|
||||
|
||||
mTableFreshness.Init();
|
||||
@ -1399,7 +1410,7 @@ nsUrlClassifierDBService::CheckCleanHost(const nsACString &spec,
|
||||
nsUrlClassifierDomainHash hostKeyHash;
|
||||
hostKeyHash.FromPlaintext(lookupHosts[i], mHash);
|
||||
|
||||
// First probe the Prefix Tree for presence
|
||||
// First probe the PrefixSet for presence
|
||||
PRUint32 domainkey = hostKeyHash.ToUint32() ^ ENCODE_DOMAIN_MAGIC;
|
||||
|
||||
PRBool found;
|
||||
@ -3131,7 +3142,7 @@ nsUrlClassifierDBServiceWorker::ApplyUpdate()
|
||||
|
||||
if (NS_SUCCEEDED(mUpdateStatus)) {
|
||||
// Reconstruct the prefix tree from the DB
|
||||
nsresult rv = ConstructPrefixTree();
|
||||
nsresult rv = ConstructPrefixSet();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -3219,6 +3230,7 @@ nsUrlClassifierDBServiceWorker::ResetDatabase()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDBFile->Remove(PR_FALSE);
|
||||
mPSFile->Remove(PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3425,9 +3437,8 @@ nsUrlClassifierDBServiceWorker::OpenDb()
|
||||
mCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG(("SB construcing Prefix Tree\n"));
|
||||
|
||||
rv = ConstructPrefixTree();
|
||||
LOG(("loading Prefix Set\n"));
|
||||
rv = LoadPrefixSet(mPSFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
@ -3495,7 +3506,7 @@ nsresult nsUrlClassifierStore::ReadPrefixes(nsTArray<PRUint32>& array)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsUrlClassifierDBServiceWorker::ConstructPrefixTree()
|
||||
nsUrlClassifierDBServiceWorker::ConstructPrefixSet()
|
||||
{
|
||||
nsTArray<PRUint32> array;
|
||||
nsresult rv = mMainStore.ReadPrefixes(array);
|
||||
@ -3511,6 +3522,39 @@ nsUrlClassifierDBServiceWorker::ConstructPrefixTree()
|
||||
// construct new one
|
||||
rv = mPrefixSet->SetPrefixes(array.Elements(), array.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// store the new tree to disk
|
||||
rv = mPrefixSet->StoreToFile(mPSFile);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to store the prefixset");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsUrlClassifierDBServiceWorker::LoadPrefixSet(nsCOMPtr<nsIFile> & aFile)
|
||||
{
|
||||
PRBool empty;
|
||||
nsresult rv = mPrefixSet->IsEmpty(&empty);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!empty) {
|
||||
LOG(("PrefixSet already loaded, not loading again"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool exists;
|
||||
rv = aFile->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
LOG(("stored PrefixSet exists, loading from disk"));
|
||||
rv = mPrefixSet->LoadFromFile(aFile);
|
||||
}
|
||||
if (!exists || NS_FAILED(rv)) {
|
||||
LOG(("no (usable) stored PrefixSet found, constructing from store"));
|
||||
ConstructPrefixSet();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRUint32 size = 0;
|
||||
rv = mPrefixSet->EstimateSize(&size);
|
||||
@ -4310,6 +4354,7 @@ nsUrlClassifierDBService::Shutdown()
|
||||
if (mWorker) {
|
||||
rv = mWorkerProxy->CancelUpdate();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post cancel update event");
|
||||
|
||||
rv = mWorkerProxy->CloseDb();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post close db event");
|
||||
}
|
||||
|
@ -40,13 +40,17 @@
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsUrlClassifierPrefixSet.h"
|
||||
#include "nsIUrlClassifierPrefixSet.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "prlog.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -61,11 +65,11 @@ static const PRLogModuleInfo *gUrlClassifierPrefixSetLog = nsnull;
|
||||
#define LOG_ENABLED() (PR_FALSE)
|
||||
#endif
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSet);
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSet)
|
||||
|
||||
nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
|
||||
: mPrefixTreeLock("mPrefixTreeLock"),
|
||||
mTreeIsReady(mPrefixTreeLock, "mTreeIsReady"),
|
||||
: mPrefixSetLock("mPrefixSetLock"),
|
||||
mSetIsReady(mPrefixSetLock, "mSetIsReady"),
|
||||
mHasPrefixes(PR_FALSE)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
@ -79,7 +83,7 @@ NS_IMETHODIMP
|
||||
nsUrlClassifierPrefixSet::SetPrefixes(const PRUint32 * aArray, PRUint32 aLength)
|
||||
{
|
||||
{
|
||||
MutexAutoLock lock(mPrefixTreeLock);
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
if (mHasPrefixes) {
|
||||
LOG(("Clearing PrefixSet"));
|
||||
mDeltas.Clear();
|
||||
@ -136,7 +140,7 @@ nsUrlClassifierPrefixSet::AddPrefixes(const PRUint32 * prefixes, PRUint32 aLengt
|
||||
LOG(("Total number of indices: %d", mNewIndexPrefixes.Length()));
|
||||
LOG(("Total number of deltas: %d", mNewDeltas.Length()));
|
||||
|
||||
MutexAutoLock lock(mPrefixTreeLock);
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
|
||||
// This just swaps some pointers
|
||||
mIndexPrefixes.SwapElements(mNewIndexPrefixes);
|
||||
@ -144,7 +148,7 @@ nsUrlClassifierPrefixSet::AddPrefixes(const PRUint32 * prefixes, PRUint32 aLengt
|
||||
mDeltas.SwapElements(mNewDeltas);
|
||||
|
||||
mHasPrefixes = PR_TRUE;
|
||||
mTreeIsReady.NotifyAll();
|
||||
mSetIsReady.NotifyAll();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -217,7 +221,7 @@ nsUrlClassifierPrefixSet::Contains(PRUint32 aPrefix, PRBool * aFound)
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierPrefixSet::EstimateSize(PRUint32 * aSize)
|
||||
{
|
||||
MutexAutoLock lock(mPrefixTreeLock);
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
*aSize = sizeof(PRBool);
|
||||
if (mHasPrefixes) {
|
||||
*aSize += sizeof(PRUint16) * mDeltas.Length();
|
||||
@ -227,17 +231,25 @@ nsUrlClassifierPrefixSet::EstimateSize(PRUint32 * aSize)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierPrefixSet::IsEmpty(PRBool * aEmpty)
|
||||
{
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
*aEmpty = !mHasPrefixes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierPrefixSet::Probe(PRUint32 aPrefix, PRBool * aReady, PRBool * aFound)
|
||||
{
|
||||
MutexAutoLock lock(mPrefixTreeLock);
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
|
||||
// check whether we are opportunistically probing or should wait
|
||||
if (*aReady) {
|
||||
// we should block until we are ready
|
||||
while (!mHasPrefixes) {
|
||||
LOG(("Tree is empty, probe must wait"));
|
||||
mTreeIsReady.Wait();
|
||||
LOG(("Set is empty, probe must wait"));
|
||||
mSetIsReady.Wait();
|
||||
}
|
||||
} else {
|
||||
// opportunistic probe -> check if set is loaded
|
||||
@ -253,3 +265,126 @@ nsUrlClassifierPrefixSet::Probe(PRUint32 aPrefix, PRBool * aReady, PRBool * aFou
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose & fileFd)
|
||||
{
|
||||
PRUint32 magic;
|
||||
PRInt32 read;
|
||||
|
||||
read = PR_Read(fileFd, &magic, sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
|
||||
|
||||
if (magic == PREFIXSET_VERSION_MAGIC) {
|
||||
PRUint32 indexSize;
|
||||
PRUint32 deltaSize;
|
||||
|
||||
read = PR_Read(fileFd, &indexSize, sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
|
||||
read = PR_Read(fileFd, &deltaSize, sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
|
||||
|
||||
if (indexSize == 0) {
|
||||
LOG(("stored PrefixSet is empty!"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsTArray<PRUint32> mNewIndexPrefixes;
|
||||
nsTArray<PRUint32> mNewIndexStarts;
|
||||
nsTArray<PRUint16> mNewDeltas;
|
||||
|
||||
mNewIndexStarts.SetLength(indexSize);
|
||||
mNewIndexPrefixes.SetLength(indexSize);
|
||||
mNewDeltas.SetLength(deltaSize);
|
||||
|
||||
read = PR_Read(fileFd, mNewIndexPrefixes.Elements(), indexSize*sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
|
||||
read = PR_Read(fileFd, mNewIndexStarts.Elements(), indexSize*sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
|
||||
if (deltaSize > 0) {
|
||||
read = PR_Read(fileFd, mNewDeltas.Elements(), deltaSize*sizeof(PRUint16));
|
||||
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
|
||||
mIndexPrefixes.SwapElements(mNewIndexPrefixes);
|
||||
mIndexStarts.SwapElements(mNewIndexStarts);
|
||||
mDeltas.SwapElements(mNewDeltas);
|
||||
|
||||
mHasPrefixes = PR_TRUE;
|
||||
mSetIsReady.NotifyAll();
|
||||
} else {
|
||||
LOG(("Version magic mismatch, not loading"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOG(("Loading PrefixSet successful"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierPrefixSet::LoadFromFile(nsIFile * aFile)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoFDClose fileFd;
|
||||
rv = file->OpenNSPRFileDesc(PR_RDONLY, 0, &fileFd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return LoadFromFd(fileFd);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose & fileFd)
|
||||
{
|
||||
PRInt32 written;
|
||||
PRUint32 magic = PREFIXSET_VERSION_MAGIC;
|
||||
written = PR_Write(fileFd, &magic, sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint32 indexSize = mIndexStarts.Length();
|
||||
PRUint32 deltaSize = mDeltas.Length();
|
||||
written = PR_Write(fileFd, &indexSize, sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
|
||||
written = PR_Write(fileFd, &deltaSize, sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
|
||||
|
||||
written = PR_Write(fileFd, mIndexPrefixes.Elements(), indexSize * sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
|
||||
written = PR_Write(fileFd, mIndexStarts.Elements(), indexSize * sizeof(PRUint32));
|
||||
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
|
||||
if (deltaSize > 0) {
|
||||
written = PR_Write(fileFd, mDeltas.Elements(), deltaSize * sizeof(PRUint16));
|
||||
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
LOG(("Saving PrefixSet successful\n"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierPrefixSet::StoreToFile(nsIFile * aFile)
|
||||
{
|
||||
if (!mHasPrefixes) {
|
||||
LOG(("Attempt to serialize empty PrefixSet"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILocalFile> file(do_QueryInterface(aFile, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoFDClose fileFd;
|
||||
rv = file->OpenNSPRFileDesc(PR_RDWR | PR_TRUNCATE | PR_CREATE_FILE,
|
||||
0644, &fileFd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MutexAutoLock lock(mPrefixSetLock);
|
||||
|
||||
return StoreToFd(fileFd);
|
||||
}
|
||||
|
@ -43,10 +43,12 @@
|
||||
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIUrlClassifierPrefixSet.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/CondVar.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
|
||||
class nsUrlClassifierPrefixSet : public nsIUrlClassifierPrefixSet
|
||||
{
|
||||
@ -57,7 +59,7 @@ public:
|
||||
// Can send an empty Array to clean the tree
|
||||
NS_IMETHOD SetPrefixes(const PRUint32* aArray, PRUint32 aLength);
|
||||
// Given prefixes must be in sorted order and bigger than
|
||||
// anything currently in the Prefix Tree
|
||||
// anything currently in the Prefix Set
|
||||
NS_IMETHOD AddPrefixes(const PRUint32* aArray, PRUint32 aLength);
|
||||
// Does the PrefixSet contain this prefix? not thread-safe
|
||||
NS_IMETHOD Contains(PRUint32 aPrefix, PRBool* aFound);
|
||||
@ -66,17 +68,23 @@ public:
|
||||
// if not set, we will return in aReady whether we were ready or not
|
||||
NS_IMETHOD Probe(PRUint32 aPrefix, PRBool* aReady, PRBool* aFound);
|
||||
NS_IMETHOD EstimateSize(PRUint32* aSize);
|
||||
NS_IMETHOD IsEmpty(PRBool * aEmpty);
|
||||
NS_IMETHOD LoadFromFile(nsIFile * aFile);
|
||||
NS_IMETHOD StoreToFile(nsIFile * aFile);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
protected:
|
||||
static const PRUint32 DELTAS_LIMIT = 100;
|
||||
static const PRUint32 MAX_INDEX_DIFF = (1 << 16);
|
||||
static const PRUint32 PREFIXSET_VERSION_MAGIC = 1;
|
||||
|
||||
mozilla::Mutex mPrefixTreeLock;
|
||||
mozilla::CondVar mTreeIsReady;
|
||||
mozilla::Mutex mPrefixSetLock;
|
||||
mozilla::CondVar mSetIsReady;
|
||||
|
||||
PRUint32 BinSearch(PRUint32 start, PRUint32 end, PRUint32 target);
|
||||
nsresult LoadFromFd(mozilla::AutoFDClose & fileFd);
|
||||
nsresult StoreToFd(mozilla::AutoFDClose & fileFd);
|
||||
|
||||
// boolean indicating whether |setPrefixes| has been
|
||||
// called with a non-empty array.
|
||||
|
Loading…
Reference in New Issue
Block a user