mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1173439 P5 Cache should index on a hash instead of the url itself. r=ehsan
This commit is contained in:
parent
7674db423c
commit
96563d1764
120
dom/cache/DBSchema.cpp
vendored
120
dom/cache/DBSchema.cpp
vendored
@ -170,6 +170,7 @@ static nsresult DeleteEntries(mozIStorageConnection* aConn,
|
||||
nsTArray<IdCount>& aDeletedSecurityIdListOut,
|
||||
uint32_t aPos=0, int32_t aLen=-1);
|
||||
static nsresult InsertSecurityInfo(mozIStorageConnection* aConn,
|
||||
nsICryptoHash* aCrypto,
|
||||
const nsACString& aData, int32_t *aIdOut);
|
||||
static nsresult DeleteSecurityInfo(mozIStorageConnection* aConn, int32_t aId,
|
||||
int32_t aCount);
|
||||
@ -199,6 +200,8 @@ static nsresult CreateAndBindKeyStatement(mozIStorageConnection* aConn,
|
||||
const char* aQueryFormat,
|
||||
const nsAString& aKey,
|
||||
mozIStorageStatement** aStateOut);
|
||||
static nsresult HashCString(nsICryptoHash* aCrypto, const nsACString& aIn,
|
||||
nsACString& aOut);
|
||||
} // anonymous namespace
|
||||
|
||||
nsresult
|
||||
@ -262,7 +265,9 @@ CreateSchema(mozIStorageConnection* aConn)
|
||||
"id INTEGER NOT NULL PRIMARY KEY, "
|
||||
"request_method TEXT NOT NULL, "
|
||||
"request_url_no_query TEXT NOT NULL, "
|
||||
"request_url_no_query_hash BLOB NOT NULL, " // first 8-bytes of sha1 hash
|
||||
"request_url_query TEXT NOT NULL, "
|
||||
"request_url_query_hash BLOB NOT NULL, " // first 8-bytes of sha1 hash
|
||||
"request_referrer TEXT NOT NULL, "
|
||||
"request_headers_guard INTEGER NOT NULL, "
|
||||
"request_mode INTEGER NOT NULL, "
|
||||
@ -286,10 +291,18 @@ CreateSchema(mozIStorageConnection* aConn)
|
||||
));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
// TODO: see if we can remove these indices on TEXT columns (bug 1110458)
|
||||
// Create an index to support the QueryCache() matching algorithm. This
|
||||
// needs to quickly find entries in a given Cache that match the request
|
||||
// URL. The url query is separated in order to support the ignoreSearch
|
||||
// option. Finally, we index hashes of the URL values instead of the
|
||||
// actual strings to avoid excessive disk bloat. The index will duplicate
|
||||
// the contents of the columsn in the index. The hash index will prune
|
||||
// the vast majority of values from the query result so that normal
|
||||
// scanning only has to be done on a few values to find an exact URL match.
|
||||
rv = aConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE INDEX entries_request_url_no_query_index "
|
||||
"ON entries (request_url_no_query);"
|
||||
"CREATE INDEX entries_request_match_index "
|
||||
"ON entries (cache_id, request_url_no_query_hash, "
|
||||
"request_url_query_hash);"
|
||||
));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
@ -930,9 +943,15 @@ QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
"LEFT OUTER JOIN response_headers ON entries.id=response_headers.entry_id "
|
||||
"AND response_headers.name='vary' "
|
||||
"WHERE entries.cache_id=:cache_id "
|
||||
"AND entries.request_url_no_query=:url_no_query "
|
||||
"AND entries.request_url_no_query_hash=:url_no_query_hash "
|
||||
);
|
||||
|
||||
if (!aParams.ignoreSearch()) {
|
||||
query.AppendLiteral("AND entries.request_url_query_hash=:url_query_hash ");
|
||||
}
|
||||
|
||||
query.AppendLiteral("AND entries.request_url_no_query=:url_no_query ");
|
||||
|
||||
if (!aParams.ignoreSearch()) {
|
||||
query.AppendLiteral("AND entries.request_url_query=:url_query ");
|
||||
}
|
||||
@ -946,6 +965,28 @@ QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsCOMPtr<nsICryptoHash> crypto =
|
||||
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsAutoCString urlWithoutQueryHash;
|
||||
rv = HashCString(crypto, aRequest.urlWithoutQuery(), urlWithoutQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindUTF8StringAsBlobByName(NS_LITERAL_CSTRING("url_no_query_hash"),
|
||||
urlWithoutQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
if (!aParams.ignoreSearch()) {
|
||||
nsAutoCString urlQueryHash;
|
||||
rv = HashCString(crypto, aRequest.urlQuery(), urlQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindUTF8StringAsBlobByName(NS_LITERAL_CSTRING("url_query_hash"),
|
||||
urlQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
}
|
||||
|
||||
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("url_no_query"),
|
||||
aRequest.urlWithoutQuery());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
@ -1216,10 +1257,11 @@ DeleteEntries(mozIStorageConnection* aConn,
|
||||
}
|
||||
|
||||
nsresult
|
||||
InsertSecurityInfo(mozIStorageConnection* aConn, const nsACString& aData,
|
||||
int32_t *aIdOut)
|
||||
InsertSecurityInfo(mozIStorageConnection* aConn, nsICryptoHash* aCrypto,
|
||||
const nsACString& aData, int32_t *aIdOut)
|
||||
{
|
||||
MOZ_ASSERT(aConn);
|
||||
MOZ_ASSERT(aCrypto);
|
||||
MOZ_ASSERT(aIdOut);
|
||||
MOZ_ASSERT(!aData.IsEmpty());
|
||||
|
||||
@ -1227,24 +1269,10 @@ InsertSecurityInfo(mozIStorageConnection* aConn, const nsACString& aData,
|
||||
// the full blob would be quite expensive. Instead, we index a small
|
||||
// hash value. Calculate this hash as the first 8 bytes of the SHA1 of
|
||||
// the full data.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICryptoHash> crypto =
|
||||
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
nsAutoCString hash;
|
||||
nsresult rv = HashCString(aCrypto, aData, hash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = crypto->Init(nsICryptoHash::SHA1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = crypto->Update(reinterpret_cast<const uint8_t*>(aData.BeginReading()),
|
||||
aData.Length());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsAutoCString fullHash;
|
||||
rv = crypto->Finish(false /* based64 result */, fullHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsDependentCSubstring hash(fullHash, 0, 8);
|
||||
|
||||
// Next, search for an existing entry for this blob by comparing the hash
|
||||
// value first and then the full data. SQLite is smart enough to use
|
||||
// the index on the hash to search the table before doing the expensive
|
||||
@ -1414,10 +1442,14 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
MOZ_ASSERT(aConn);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
int32_t securityId = -1;
|
||||
|
||||
nsCOMPtr<nsICryptoHash> crypto =
|
||||
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
int32_t securityId = -1;
|
||||
if (!aResponse.channelInfo().securityInfo().IsEmpty()) {
|
||||
rv = InsertSecurityInfo(aConn,
|
||||
rv = InsertSecurityInfo(aConn, crypto,
|
||||
aResponse.channelInfo().securityInfo(),
|
||||
&securityId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
@ -1428,7 +1460,9 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
"INSERT INTO entries ("
|
||||
"request_method, "
|
||||
"request_url_no_query, "
|
||||
"request_url_no_query_hash, "
|
||||
"request_url_query, "
|
||||
"request_url_query_hash, "
|
||||
"request_referrer, "
|
||||
"request_headers_guard, "
|
||||
"request_mode, "
|
||||
@ -1449,7 +1483,9 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
") VALUES ("
|
||||
":request_method, "
|
||||
":request_url_no_query, "
|
||||
":request_url_no_query_hash, "
|
||||
":request_url_query, "
|
||||
":request_url_query_hash, "
|
||||
":request_referrer, "
|
||||
":request_headers_guard, "
|
||||
":request_mode, "
|
||||
@ -1479,10 +1515,26 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
|
||||
aRequest.urlWithoutQuery());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsAutoCString urlWithoutQueryHash;
|
||||
rv = HashCString(crypto, aRequest.urlWithoutQuery(), urlWithoutQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindUTF8StringAsBlobByName(
|
||||
NS_LITERAL_CSTRING("request_url_no_query_hash"), urlWithoutQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("request_url_query"),
|
||||
aRequest.urlQuery());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsAutoCString urlQueryHash;
|
||||
rv = HashCString(crypto, aRequest.urlQuery(), urlQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindUTF8StringAsBlobByName(
|
||||
NS_LITERAL_CSTRING("request_url_query_hash"), urlQueryHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = state->BindStringByName(NS_LITERAL_CSTRING("request_referrer"),
|
||||
aRequest.referrer());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
@ -1945,6 +1997,26 @@ CreateAndBindKeyStatement(mozIStorageConnection* aConn,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HashCString(nsICryptoHash* aCrypto, const nsACString& aIn, nsACString& aOut)
|
||||
{
|
||||
MOZ_ASSERT(aCrypto);
|
||||
|
||||
nsresult rv = aCrypto->Init(nsICryptoHash::SHA1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
rv = aCrypto->Update(reinterpret_cast<const uint8_t*>(aIn.BeginReading()),
|
||||
aIn.Length());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
nsAutoCString fullHash;
|
||||
rv = aCrypto->Finish(false /* based64 result */, fullHash);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
aOut = Substring(fullHash, 0, 8);
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // anonymouns namespace
|
||||
|
||||
nsresult
|
||||
|
Loading…
Reference in New Issue
Block a user