mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backout bff74cecc67c, ffe0edb2aae7, b60b7c267cef, 6da154b43265, bcf6fd3ab9bb (bug 1182961 parts 1--5) for possible intermittent failures and performance problems.
a=bustage
This commit is contained in:
parent
de4e7b8407
commit
90c3d013d4
@ -427,13 +427,37 @@ CacheFileHandles::RemoveHandle(CacheFileHandle *aHandle)
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
GetAllHandlesEnum(CacheFileHandles::HandleHashKey* aEntry, void *aClosure)
|
||||
{
|
||||
nsTArray<nsRefPtr<CacheFileHandle> > *array =
|
||||
static_cast<nsTArray<nsRefPtr<CacheFileHandle> > *>(aClosure);
|
||||
|
||||
aEntry->GetHandles(*array);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
CacheFileHandles::GetAllHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval)
|
||||
{
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThreadOrCeased());
|
||||
for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Get()->GetHandles(*_retval);
|
||||
mTable.EnumerateEntries(&GetAllHandlesEnum, _retval);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
GetActiveHandlesEnum(CacheFileHandles::HandleHashKey* aEntry, void *aClosure)
|
||||
{
|
||||
nsTArray<nsRefPtr<CacheFileHandle> > *array =
|
||||
static_cast<nsTArray<nsRefPtr<CacheFileHandle> > *>(aClosure);
|
||||
|
||||
nsRefPtr<CacheFileHandle> handle = aEntry->GetNewestHandle();
|
||||
MOZ_ASSERT(handle);
|
||||
|
||||
if (!handle->IsDoomed()) {
|
||||
array->AppendElement(handle);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
@ -441,14 +465,7 @@ CacheFileHandles::GetActiveHandles(
|
||||
nsTArray<nsRefPtr<CacheFileHandle> > *_retval)
|
||||
{
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThreadOrCeased());
|
||||
for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<CacheFileHandle> handle = iter.Get()->GetNewestHandle();
|
||||
MOZ_ASSERT(handle);
|
||||
|
||||
if (!handle->IsDoomed()) {
|
||||
_retval->AppendElement(handle);
|
||||
}
|
||||
}
|
||||
mTable.EnumerateEntries(&GetActiveHandlesEnum, _retval);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -629,7 +629,7 @@ CacheIndex::EnsureEntryExists(const SHA1Sum::Hash *aHash)
|
||||
} else if (index->mState == READY ||
|
||||
(entryRemoved && !entry->IsFresh())) {
|
||||
// Removed non-fresh entries can be present as a result of
|
||||
// MergeJournal()
|
||||
// ProcessJournalEntry()
|
||||
LOG(("CacheIndex::EnsureEntryExists() - Didn't find entry that should"
|
||||
" exist, update is needed"));
|
||||
index->mIndexNeedsUpdate = true;
|
||||
@ -848,7 +848,7 @@ CacheIndex::RemoveEntry(const SHA1Sum::Hash *aHash)
|
||||
} else if (index->mState == READY ||
|
||||
(entryRemoved && !entry->IsFresh())) {
|
||||
// Removed non-fresh entries can be present as a result of
|
||||
// MergeJournal()
|
||||
// ProcessJournalEntry()
|
||||
LOG(("CacheIndex::RemoveEntry() - Didn't find entry that should exist"
|
||||
", update is needed"));
|
||||
index->mIndexNeedsUpdate = true;
|
||||
@ -1488,58 +1488,64 @@ CacheIndex::ProcessPendingOperations()
|
||||
|
||||
AssertOwnsLock();
|
||||
|
||||
for (auto iter = mPendingUpdates.Iter(); !iter.Done(); iter.Next()) {
|
||||
CacheIndexEntryUpdate* update = iter.Get();
|
||||
|
||||
LOG(("CacheIndex::ProcessPendingOperations() [hash=%08x%08x%08x%08x%08x]",
|
||||
LOGSHA1(update->Hash())));
|
||||
|
||||
MOZ_ASSERT(update->IsFresh());
|
||||
|
||||
CacheIndexEntry* entry = mIndex.GetEntry(*update->Hash());
|
||||
|
||||
{
|
||||
CacheIndexEntryAutoManage emng(update->Hash(), this);
|
||||
emng.DoNotSearchInUpdates();
|
||||
|
||||
if (update->IsRemoved()) {
|
||||
if (entry) {
|
||||
if (entry->IsRemoved()) {
|
||||
MOZ_ASSERT(entry->IsFresh());
|
||||
MOZ_ASSERT(entry->IsDirty());
|
||||
} else if (!entry->IsDirty() && entry->IsFileEmpty()) {
|
||||
// Entries with empty file are not stored in index on disk. Just
|
||||
// remove the entry, but only in case the entry is not dirty, i.e.
|
||||
// the entry file was empty when we wrote the index.
|
||||
mIndex.RemoveEntry(*update->Hash());
|
||||
entry = nullptr;
|
||||
} else {
|
||||
entry->MarkRemoved();
|
||||
entry->MarkDirty();
|
||||
entry->MarkFresh();
|
||||
}
|
||||
}
|
||||
} else if (entry) {
|
||||
// Some information in mIndex can be newer than in mPendingUpdates (see
|
||||
// bug 1074832). This will copy just those values that were really
|
||||
// updated.
|
||||
update->ApplyUpdate(entry);
|
||||
} else {
|
||||
// There is no entry in mIndex, copy all information from
|
||||
// mPendingUpdates to mIndex.
|
||||
entry = mIndex.PutEntry(*update->Hash());
|
||||
*entry = *update;
|
||||
}
|
||||
}
|
||||
|
||||
iter.Remove();
|
||||
}
|
||||
mPendingUpdates.EnumerateEntries(&CacheIndex::UpdateEntryInIndex, this);
|
||||
|
||||
MOZ_ASSERT(mPendingUpdates.Count() == 0);
|
||||
|
||||
EnsureCorrectStats();
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::UpdateEntryInIndex(CacheIndexEntryUpdate *aEntry, void* aClosure)
|
||||
{
|
||||
CacheIndex *index = static_cast<CacheIndex *>(aClosure);
|
||||
|
||||
LOG(("CacheFile::UpdateEntryInIndex() [hash=%08x%08x%08x%08x%08x]",
|
||||
LOGSHA1(aEntry->Hash())));
|
||||
|
||||
MOZ_ASSERT(aEntry->IsFresh());
|
||||
|
||||
CacheIndexEntry *entry = index->mIndex.GetEntry(*aEntry->Hash());
|
||||
|
||||
CacheIndexEntryAutoManage emng(aEntry->Hash(), index);
|
||||
emng.DoNotSearchInUpdates();
|
||||
|
||||
if (aEntry->IsRemoved()) {
|
||||
if (entry) {
|
||||
if (entry->IsRemoved()) {
|
||||
MOZ_ASSERT(entry->IsFresh());
|
||||
MOZ_ASSERT(entry->IsDirty());
|
||||
} else if (!entry->IsDirty() && entry->IsFileEmpty()) {
|
||||
// Entries with empty file are not stored in index on disk. Just remove
|
||||
// the entry, but only in case the entry is not dirty, i.e. the entry
|
||||
// file was empty when we wrote the index.
|
||||
index->mIndex.RemoveEntry(*aEntry->Hash());
|
||||
entry = nullptr;
|
||||
} else {
|
||||
entry->MarkRemoved();
|
||||
entry->MarkDirty();
|
||||
entry->MarkFresh();
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
if (entry) {
|
||||
// Some information in mIndex can be newer than in mPendingUpdates (see bug
|
||||
// 1074832). This will copy just those values that were really updated.
|
||||
aEntry->ApplyUpdate(entry);
|
||||
} else {
|
||||
// There is no entry in mIndex, copy all information from mPendingUpdates
|
||||
// to mIndex.
|
||||
entry = index->mIndex.PutEntry(*aEntry->Hash());
|
||||
*entry = *aEntry;
|
||||
}
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIndex::WriteIndexToDiskIfNeeded()
|
||||
{
|
||||
@ -1604,6 +1610,21 @@ CacheIndex::WriteIndexToDisk()
|
||||
mSkipEntries = 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct WriteRecordsHelper
|
||||
{
|
||||
char *mBuf;
|
||||
uint32_t mSkip;
|
||||
uint32_t mProcessMax;
|
||||
uint32_t mProcessed;
|
||||
#ifdef DEBUG
|
||||
bool mHasMore;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
CacheIndex::WriteRecords()
|
||||
{
|
||||
@ -1626,49 +1647,27 @@ CacheIndex::WriteRecords()
|
||||
}
|
||||
uint32_t hashOffset = mRWBufPos;
|
||||
|
||||
char* buf = mRWBuf + mRWBufPos;
|
||||
uint32_t skip = mSkipEntries;
|
||||
uint32_t processMax = (mRWBufSize - mRWBufPos) / sizeof(CacheIndexRecord);
|
||||
MOZ_ASSERT(processMax != 0 || mProcessEntries == 0); // TODO make sure we can write an empty index
|
||||
uint32_t processed = 0;
|
||||
WriteRecordsHelper data;
|
||||
data.mBuf = mRWBuf + mRWBufPos;
|
||||
data.mSkip = mSkipEntries;
|
||||
data.mProcessMax = (mRWBufSize - mRWBufPos) / sizeof(CacheIndexRecord);
|
||||
MOZ_ASSERT(data.mProcessMax != 0 || mProcessEntries == 0); // TODO make sure we can write an empty index
|
||||
data.mProcessed = 0;
|
||||
#ifdef DEBUG
|
||||
bool hasMore = false;
|
||||
data.mHasMore = false;
|
||||
#endif
|
||||
for (auto iter = mIndex.Iter(); !iter.Done(); iter.Next()) {
|
||||
CacheIndexEntry* entry = iter.Get();
|
||||
if (entry->IsRemoved() ||
|
||||
!entry->IsInitialized() ||
|
||||
entry->IsFileEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (processed == processMax) {
|
||||
#ifdef DEBUG
|
||||
hasMore = true;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
entry->WriteToBuf(buf);
|
||||
buf += sizeof(CacheIndexRecord);
|
||||
processed++;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mRWBufPos != static_cast<uint32_t>(buf - mRWBuf) ||
|
||||
mIndex.EnumerateEntries(&CacheIndex::CopyRecordsToRWBuf, &data);
|
||||
MOZ_ASSERT(mRWBufPos != static_cast<uint32_t>(data.mBuf - mRWBuf) ||
|
||||
mProcessEntries == 0);
|
||||
mRWBufPos = buf - mRWBuf;
|
||||
mSkipEntries += processed;
|
||||
mRWBufPos = data.mBuf - mRWBuf;
|
||||
mSkipEntries += data.mProcessed;
|
||||
MOZ_ASSERT(mSkipEntries <= mProcessEntries);
|
||||
|
||||
mRWHash->Update(mRWBuf + hashOffset, mRWBufPos - hashOffset);
|
||||
|
||||
if (mSkipEntries == mProcessEntries) {
|
||||
MOZ_ASSERT(!hasMore);
|
||||
MOZ_ASSERT(!data.mHasMore);
|
||||
|
||||
// We've processed all records
|
||||
if (mRWBufPos + sizeof(CacheHash::Hash32_t) > mRWBufSize) {
|
||||
@ -1680,7 +1679,7 @@ CacheIndex::WriteRecords()
|
||||
NetworkEndian::writeUint32(mRWBuf + mRWBufPos, mRWHash->GetHash());
|
||||
mRWBufPos += sizeof(CacheHash::Hash32_t);
|
||||
} else {
|
||||
MOZ_ASSERT(hasMore);
|
||||
MOZ_ASSERT(data.mHasMore);
|
||||
}
|
||||
|
||||
rv = CacheFileIOManager::Write(mIndexHandle, fileOffset, mRWBuf, mRWBufPos,
|
||||
@ -1711,25 +1710,7 @@ CacheIndex::FinishWrite(bool aSucceeded)
|
||||
// Opening of the file must not be in progress if writing succeeded.
|
||||
MOZ_ASSERT(!mIndexFileOpener);
|
||||
|
||||
for (auto iter = mIndex.Iter(); !iter.Done(); iter.Next()) {
|
||||
CacheIndexEntry* entry = iter.Get();
|
||||
|
||||
bool remove = false;
|
||||
{
|
||||
CacheIndexEntryAutoManage emng(entry->Hash(), this);
|
||||
|
||||
if (entry->IsRemoved()) {
|
||||
emng.DoNotSearchInIndex();
|
||||
remove = true;
|
||||
} else if (entry->IsDirty()) {
|
||||
entry->ClearDirty();
|
||||
}
|
||||
}
|
||||
if (remove) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
mIndex.EnumerateEntries(&CacheIndex::ApplyIndexChanges, this);
|
||||
mIndexOnDiskIsValid = true;
|
||||
} else {
|
||||
if (mIndexFileOpener) {
|
||||
@ -1750,6 +1731,62 @@ CacheIndex::FinishWrite(bool aSucceeded)
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::CopyRecordsToRWBuf(CacheIndexEntry *aEntry, void* aClosure)
|
||||
{
|
||||
if (aEntry->IsRemoved()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
if (!aEntry->IsInitialized()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
if (aEntry->IsFileEmpty()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
WriteRecordsHelper *data = static_cast<WriteRecordsHelper *>(aClosure);
|
||||
if (data->mSkip) {
|
||||
data->mSkip--;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
if (data->mProcessed == data->mProcessMax) {
|
||||
#ifdef DEBUG
|
||||
data->mHasMore = true;
|
||||
#endif
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
aEntry->WriteToBuf(data->mBuf);
|
||||
data->mBuf += sizeof(CacheIndexRecord);
|
||||
data->mProcessed++;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::ApplyIndexChanges(CacheIndexEntry *aEntry, void* aClosure)
|
||||
{
|
||||
CacheIndex *index = static_cast<CacheIndex *>(aClosure);
|
||||
|
||||
CacheIndexEntryAutoManage emng(aEntry->Hash(), index);
|
||||
|
||||
if (aEntry->IsRemoved()) {
|
||||
emng.DoNotSearchInIndex();
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
if (aEntry->IsDirty()) {
|
||||
aEntry->ClearDirty();
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheIndex::GetFile(const nsACString &aName, nsIFile **_retval)
|
||||
{
|
||||
@ -1934,13 +1971,7 @@ CacheIndex::WriteLogToDisk()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
WriteLogHelper wlh(fd);
|
||||
for (auto iter = mIndex.Iter(); !iter.Done(); iter.Next()) {
|
||||
CacheIndexEntry* entry = iter.Get();
|
||||
if (entry->IsRemoved() || entry->IsDirty()) {
|
||||
wlh.AddEntry(entry);
|
||||
}
|
||||
iter.Remove();
|
||||
}
|
||||
mIndex.EnumerateEntries(&CacheIndex::WriteEntryToLog, &wlh);
|
||||
|
||||
rv = wlh.Finish();
|
||||
PR_Close(fd);
|
||||
@ -1973,6 +2004,19 @@ CacheIndex::WriteLogToDisk()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::WriteEntryToLog(CacheIndexEntry *aEntry, void* aClosure)
|
||||
{
|
||||
WriteLogHelper *wlh = static_cast<WriteLogHelper *>(aClosure);
|
||||
|
||||
if (aEntry->IsRemoved() || aEntry->IsDirty()) {
|
||||
wlh->AddEntry(aEntry);
|
||||
}
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
CacheIndex::ReadIndexFromDisk()
|
||||
{
|
||||
@ -2309,46 +2353,48 @@ CacheIndex::MergeJournal()
|
||||
|
||||
AssertOwnsLock();
|
||||
|
||||
for (auto iter = mTmpJournal.Iter(); !iter.Done(); iter.Next()) {
|
||||
CacheIndexEntry* entry = iter.Get();
|
||||
|
||||
LOG(("CacheIndex::MergeJournal() [hash=%08x%08x%08x%08x%08x]",
|
||||
LOGSHA1(entry->Hash())));
|
||||
|
||||
CacheIndexEntry* entry2 = mIndex.GetEntry(*entry->Hash());
|
||||
|
||||
CacheIndexEntryAutoManage emng(entry->Hash(), this);
|
||||
|
||||
if (entry->IsRemoved()) {
|
||||
if (entry2) {
|
||||
entry2->MarkRemoved();
|
||||
entry2->MarkDirty();
|
||||
}
|
||||
} else {
|
||||
if (!entry2) {
|
||||
entry2 = mIndex.PutEntry(*entry->Hash());
|
||||
}
|
||||
|
||||
*entry2 = *entry;
|
||||
entry2->MarkDirty();
|
||||
}
|
||||
|
||||
iter.Remove();
|
||||
}
|
||||
mTmpJournal.EnumerateEntries(&CacheIndex::ProcessJournalEntry, this);
|
||||
|
||||
MOZ_ASSERT(mTmpJournal.Count() == 0);
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::ProcessJournalEntry(CacheIndexEntry *aEntry, void* aClosure)
|
||||
{
|
||||
CacheIndex *index = static_cast<CacheIndex *>(aClosure);
|
||||
|
||||
LOG(("CacheIndex::ProcessJournalEntry() [hash=%08x%08x%08x%08x%08x]",
|
||||
LOGSHA1(aEntry->Hash())));
|
||||
|
||||
CacheIndexEntry *entry = index->mIndex.GetEntry(*aEntry->Hash());
|
||||
|
||||
CacheIndexEntryAutoManage emng(aEntry->Hash(), index);
|
||||
|
||||
if (aEntry->IsRemoved()) {
|
||||
if (entry) {
|
||||
entry->MarkRemoved();
|
||||
entry->MarkDirty();
|
||||
}
|
||||
} else {
|
||||
if (!entry) {
|
||||
entry = index->mIndex.PutEntry(*aEntry->Hash());
|
||||
}
|
||||
|
||||
*entry = *aEntry;
|
||||
entry->MarkDirty();
|
||||
}
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
CacheIndex::EnsureNoFreshEntry()
|
||||
{
|
||||
#ifdef DEBUG_STATS
|
||||
CacheIndexStats debugStats;
|
||||
debugStats.DisableLogging();
|
||||
for (auto iter = mIndex.Iter(); !iter.Done(); iter.Next()) {
|
||||
debugStats.BeforeChange(nullptr);
|
||||
debugStats.AfterChange(iter.Get());
|
||||
}
|
||||
mIndex.EnumerateEntries(&CacheIndex::SumIndexStats, &debugStats);
|
||||
MOZ_ASSERT(debugStats.Fresh() == 0);
|
||||
#endif
|
||||
}
|
||||
@ -2360,14 +2406,21 @@ CacheIndex::EnsureCorrectStats()
|
||||
MOZ_ASSERT(mPendingUpdates.Count() == 0);
|
||||
CacheIndexStats debugStats;
|
||||
debugStats.DisableLogging();
|
||||
for (auto iter = mIndex.Iter(); !iter.Done(); iter.Next()) {
|
||||
debugStats.BeforeChange(nullptr);
|
||||
debugStats.AfterChange(iter.Get());
|
||||
}
|
||||
mIndex.EnumerateEntries(&CacheIndex::SumIndexStats, &debugStats);
|
||||
MOZ_ASSERT(debugStats == mIndexStats);
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::SumIndexStats(CacheIndexEntry *aEntry, void* aClosure)
|
||||
{
|
||||
CacheIndexStats *stats = static_cast<CacheIndexStats *>(aClosure);
|
||||
stats->BeforeChange(nullptr);
|
||||
stats->AfterChange(aEntry);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
CacheIndex::FinishRead(bool aSucceeded)
|
||||
{
|
||||
@ -2424,7 +2477,7 @@ CacheIndex::FinishRead(bool aSucceeded)
|
||||
EnsureNoFreshEntry();
|
||||
ProcessPendingOperations();
|
||||
// Remove all entries that we haven't seen during this session
|
||||
RemoveNonFreshEntries();
|
||||
mIndex.EnumerateEntries(&CacheIndex::RemoveNonFreshEntries, this);
|
||||
StartUpdatingIndex(true);
|
||||
return;
|
||||
}
|
||||
@ -3012,7 +3065,7 @@ CacheIndex::FinishUpdate(bool aSucceeded)
|
||||
// If we've iterated over all entries successfully then all entries that
|
||||
// really exist on the disk are now marked as fresh. All non-fresh entries
|
||||
// don't exist anymore and must be removed from the index.
|
||||
RemoveNonFreshEntries();
|
||||
mIndex.EnumerateEntries(&CacheIndex::RemoveNonFreshEntries, this);
|
||||
}
|
||||
|
||||
// Make sure we won't start update. If the build or update failed, there is no
|
||||
@ -3023,25 +3076,23 @@ CacheIndex::FinishUpdate(bool aSucceeded)
|
||||
mLastDumpTime = TimeStamp::NowLoRes(); // Do not dump new index immediately
|
||||
}
|
||||
|
||||
void
|
||||
CacheIndex::RemoveNonFreshEntries()
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheIndex::RemoveNonFreshEntries(CacheIndexEntry *aEntry, void* aClosure)
|
||||
{
|
||||
for (auto iter = mIndex.Iter(); !iter.Done(); iter.Next()) {
|
||||
CacheIndexEntry* entry = iter.Get();
|
||||
if (entry->IsFresh()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(("CacheIndex::RemoveNonFreshEntries() - Removing entry. "
|
||||
"[hash=%08x%08x%08x%08x%08x]", LOGSHA1(entry->Hash())));
|
||||
|
||||
{
|
||||
CacheIndexEntryAutoManage emng(entry->Hash(), this);
|
||||
emng.DoNotSearchInIndex();
|
||||
}
|
||||
|
||||
iter.Remove();
|
||||
if (aEntry->IsFresh()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
LOG(("CacheFile::RemoveNonFreshEntries() - Removing entry. "
|
||||
"[hash=%08x%08x%08x%08x%08x]", LOGSHA1(aEntry->Hash())));
|
||||
|
||||
CacheIndex *index = static_cast<CacheIndex *>(aClosure);
|
||||
|
||||
CacheIndexEntryAutoManage emng(aEntry->Hash(), index);
|
||||
emng.DoNotSearchInIndex();
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -723,6 +723,8 @@ private:
|
||||
|
||||
// Merge all pending operations from mPendingUpdates into mIndex.
|
||||
void ProcessPendingOperations();
|
||||
static PLDHashOperator UpdateEntryInIndex(CacheIndexEntryUpdate *aEntry,
|
||||
void* aClosure);
|
||||
|
||||
// Following methods perform writing of the index file.
|
||||
//
|
||||
@ -743,6 +745,11 @@ private:
|
||||
// Finalizes writing process.
|
||||
void FinishWrite(bool aSucceeded);
|
||||
|
||||
static PLDHashOperator CopyRecordsToRWBuf(CacheIndexEntry *aEntry,
|
||||
void* aClosure);
|
||||
static PLDHashOperator ApplyIndexChanges(CacheIndexEntry *aEntry,
|
||||
void* aClosure);
|
||||
|
||||
// Following methods perform writing of the journal during shutdown. All these
|
||||
// methods must be called only during shutdown since they write/delete files
|
||||
// directly on the main thread instead of using CacheFileIOManager that does
|
||||
@ -756,6 +763,9 @@ private:
|
||||
// Writes journal to the disk and clears dirty flag in index header.
|
||||
nsresult WriteLogToDisk();
|
||||
|
||||
static PLDHashOperator WriteEntryToLog(CacheIndexEntry *aEntry,
|
||||
void* aClosure);
|
||||
|
||||
// Following methods perform reading of the index from the disk.
|
||||
//
|
||||
// Index is read at startup just after initializing the CacheIndex. There are
|
||||
@ -810,9 +820,13 @@ private:
|
||||
// In debug build this method is called after processing pending operations
|
||||
// to make sure mIndexStats contains correct information.
|
||||
void EnsureCorrectStats();
|
||||
static PLDHashOperator SumIndexStats(CacheIndexEntry *aEntry, void* aClosure);
|
||||
// Finalizes reading process.
|
||||
void FinishRead(bool aSucceeded);
|
||||
|
||||
static PLDHashOperator ProcessJournalEntry(CacheIndexEntry *aEntry,
|
||||
void* aClosure);
|
||||
|
||||
// Following methods perform updating and building of the index.
|
||||
// Timer callback that starts update or build process.
|
||||
static void DelayedUpdate(nsITimer *aTimer, void *aClosure);
|
||||
@ -839,7 +853,8 @@ private:
|
||||
// Finalizes update or build process.
|
||||
void FinishUpdate(bool aSucceeded);
|
||||
|
||||
void RemoveNonFreshEntries();
|
||||
static PLDHashOperator RemoveNonFreshEntries(CacheIndexEntry *aEntry,
|
||||
void* aClosure);
|
||||
|
||||
enum EState {
|
||||
// Initial state in which the index is not usable
|
||||
|
@ -1442,6 +1442,25 @@ nsCookieService::HandleCorruptDB(DBState* aDBState)
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
RebuildDBCallback(nsCookieEntry *aEntry,
|
||||
void *aArg)
|
||||
{
|
||||
mozIStorageBindingParamsArray* paramsArray =
|
||||
static_cast<mozIStorageBindingParamsArray*>(aArg);
|
||||
|
||||
const nsCookieEntry::ArrayType &cookies = aEntry->GetCookies();
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
|
||||
nsCookie* cookie = cookies[i];
|
||||
|
||||
if (!cookie->IsSession()) {
|
||||
bindCookieParameters(paramsArray, nsCookieKey(aEntry), cookie);
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsCookieService::RebuildCorruptDB(DBState* aDBState)
|
||||
{
|
||||
@ -1495,18 +1514,7 @@ nsCookieService::RebuildCorruptDB(DBState* aDBState)
|
||||
mozIStorageAsyncStatement* stmt = aDBState->stmtInsert;
|
||||
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
|
||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||
for (auto iter = aDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCookieEntry* entry = iter.Get();
|
||||
|
||||
const nsCookieEntry::ArrayType& cookies = entry->GetCookies();
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
|
||||
nsCookie* cookie = cookies[i];
|
||||
|
||||
if (!cookie->IsSession()) {
|
||||
bindCookieParameters(paramsArray, nsCookieKey(entry), cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
aDBState->hostTable.EnumerateEntries(RebuildDBCallback, paramsArray.get());
|
||||
|
||||
// Make sure we've got something to write. If we don't, we're done.
|
||||
uint32_t length;
|
||||
@ -1945,6 +1953,20 @@ nsCookieService::RemoveAll()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
COMArrayCallback(nsCookieEntry *aEntry,
|
||||
void *aArg)
|
||||
{
|
||||
nsCOMArray<nsICookie> *data = static_cast<nsCOMArray<nsICookie> *>(aArg);
|
||||
|
||||
const nsCookieEntry::ArrayType &cookies = aEntry->GetCookies();
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
|
||||
data->AppendObject(cookies[i]);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetEnumerator(nsISimpleEnumerator **aEnumerator)
|
||||
{
|
||||
@ -1956,12 +1978,7 @@ nsCookieService::GetEnumerator(nsISimpleEnumerator **aEnumerator)
|
||||
EnsureReadComplete();
|
||||
|
||||
nsCOMArray<nsICookie> cookieList(mDBState->cookieCount);
|
||||
for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
const nsCookieEntry::ArrayType& cookies = iter.Get()->GetCookies();
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
|
||||
cookieList.AppendObject(cookies[i]);
|
||||
}
|
||||
}
|
||||
mDBState->hostTable.EnumerateEntries(COMArrayCallback, &cookieList);
|
||||
|
||||
return NS_NewArrayEnumerator(aEnumerator, cookieList);
|
||||
}
|
||||
@ -3663,6 +3680,45 @@ nsCookieService::RemoveAllFromMemory()
|
||||
mDBState->cookieOldestTime = INT64_MAX;
|
||||
}
|
||||
|
||||
// stores temporary data for enumerating over the hash entries,
|
||||
// since enumeration is done using callback functions
|
||||
struct nsPurgeData
|
||||
{
|
||||
typedef nsTArray<nsListIter> ArrayType;
|
||||
|
||||
nsPurgeData(int64_t aCurrentTime,
|
||||
int64_t aPurgeTime,
|
||||
ArrayType &aPurgeList,
|
||||
nsIMutableArray *aRemovedList,
|
||||
mozIStorageBindingParamsArray *aParamsArray)
|
||||
: currentTime(aCurrentTime)
|
||||
, purgeTime(aPurgeTime)
|
||||
, oldestTime(INT64_MAX)
|
||||
, purgeList(aPurgeList)
|
||||
, removedList(aRemovedList)
|
||||
, paramsArray(aParamsArray)
|
||||
{
|
||||
}
|
||||
|
||||
// the current time, in seconds
|
||||
int64_t currentTime;
|
||||
|
||||
// lastAccessed time older than which cookies are eligible for purge
|
||||
int64_t purgeTime;
|
||||
|
||||
// lastAccessed time of the oldest cookie found during purge, to update our indicator
|
||||
int64_t oldestTime;
|
||||
|
||||
// list of cookies over the age limit, for purging
|
||||
ArrayType &purgeList;
|
||||
|
||||
// list of all cookies we've removed, for notification
|
||||
nsIMutableArray *removedList;
|
||||
|
||||
// The array of parameters to be bound to the statement for deletion later.
|
||||
mozIStorageBindingParamsArray *paramsArray;
|
||||
};
|
||||
|
||||
// comparator class for lastaccessed times of cookies.
|
||||
class CompareCookiesByAge {
|
||||
public:
|
||||
@ -3703,6 +3759,42 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
purgeCookiesCallback(nsCookieEntry *aEntry,
|
||||
void *aArg)
|
||||
{
|
||||
nsPurgeData &data = *static_cast<nsPurgeData*>(aArg);
|
||||
|
||||
const nsCookieEntry::ArrayType &cookies = aEntry->GetCookies();
|
||||
mozIStorageBindingParamsArray *array = data.paramsArray;
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ) {
|
||||
nsListIter iter(aEntry, i);
|
||||
nsCookie *cookie = cookies[i];
|
||||
|
||||
// check if the cookie has expired
|
||||
if (cookie->Expiry() <= data.currentTime) {
|
||||
data.removedList->AppendElement(cookie, false);
|
||||
COOKIE_LOGEVICTED(cookie, "Cookie expired");
|
||||
|
||||
// remove from list; do not increment our iterator
|
||||
gCookieService->RemoveCookieFromList(iter, array);
|
||||
|
||||
} else {
|
||||
// check if the cookie is over the age limit
|
||||
if (cookie->LastAccessed() <= data.purgeTime) {
|
||||
data.purgeList.AppendElement(iter);
|
||||
|
||||
} else if (cookie->LastAccessed() < data.oldestTime) {
|
||||
// reset our indicator
|
||||
data.oldestTime = cookie->LastAccessed();
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// purges expired and old cookies in a batch operation.
|
||||
already_AddRefed<nsIArray>
|
||||
nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec)
|
||||
@ -3715,8 +3807,7 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec)
|
||||
("PurgeCookies(): beginning purge with %ld cookies and %lld oldest age",
|
||||
mDBState->cookieCount, aCurrentTimeInUsec - mDBState->cookieOldestTime));
|
||||
|
||||
typedef nsAutoTArray<nsListIter, kMaxNumberOfCookies> PurgeList;
|
||||
PurgeList purgeList;
|
||||
nsAutoTArray<nsListIter, kMaxNumberOfCookies> purgeList;
|
||||
|
||||
nsCOMPtr<nsIMutableArray> removedList = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
|
||||
@ -3728,40 +3819,9 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec)
|
||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||
}
|
||||
|
||||
int64_t currentTime = aCurrentTimeInUsec / PR_USEC_PER_SEC;
|
||||
int64_t purgeTime = aCurrentTimeInUsec - mCookiePurgeAge;
|
||||
int64_t oldestTime = INT64_MAX;
|
||||
|
||||
for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCookieEntry* entry = iter.Get();
|
||||
|
||||
const nsCookieEntry::ArrayType &cookies = entry->GetCookies();
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ) {
|
||||
nsListIter iter(entry, i);
|
||||
nsCookie* cookie = cookies[i];
|
||||
|
||||
// check if the cookie has expired
|
||||
if (cookie->Expiry() <= currentTime) {
|
||||
removedList->AppendElement(cookie, false);
|
||||
COOKIE_LOGEVICTED(cookie, "Cookie expired");
|
||||
|
||||
// remove from list; do not increment our iterator
|
||||
gCookieService->RemoveCookieFromList(iter, paramsArray);
|
||||
|
||||
} else {
|
||||
// check if the cookie is over the age limit
|
||||
if (cookie->LastAccessed() <= purgeTime) {
|
||||
purgeList.AppendElement(iter);
|
||||
|
||||
} else if (cookie->LastAccessed() < oldestTime) {
|
||||
// reset our indicator
|
||||
oldestTime = cookie->LastAccessed();
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsPurgeData data(aCurrentTimeInUsec / PR_USEC_PER_SEC,
|
||||
aCurrentTimeInUsec - mCookiePurgeAge, purgeList, removedList, paramsArray);
|
||||
mDBState->hostTable.EnumerateEntries(purgeCookiesCallback, &data);
|
||||
|
||||
uint32_t postExpiryCookieCount = mDBState->cookieCount;
|
||||
|
||||
@ -3774,7 +3834,7 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec)
|
||||
mDBState->cookieCount - mMaxNumberOfCookies : 0;
|
||||
if (purgeList.Length() > excess) {
|
||||
// We're not purging everything in the list, so update our indicator.
|
||||
oldestTime = purgeList[excess].Cookie()->LastAccessed();
|
||||
data.oldestTime = purgeList[excess].Cookie()->LastAccessed();
|
||||
|
||||
purgeList.SetLength(excess);
|
||||
}
|
||||
@ -3783,7 +3843,7 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec)
|
||||
// together, and with ascending index. this allows us to iterate backwards
|
||||
// over the list removing cookies, without having to adjust indexes as we go.
|
||||
purgeList.Sort(CompareCookiesByIndex());
|
||||
for (PurgeList::index_type i = purgeList.Length(); i--; ) {
|
||||
for (nsPurgeData::ArrayType::index_type i = purgeList.Length(); i--; ) {
|
||||
nsCookie *cookie = purgeList[i].Cookie();
|
||||
removedList->AppendElement(cookie, false);
|
||||
COOKIE_LOGEVICTED(cookie, "Cookie too old");
|
||||
@ -3805,7 +3865,7 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec)
|
||||
}
|
||||
|
||||
// reset the oldest time indicator
|
||||
mDBState->cookieOldestTime = oldestTime;
|
||||
mDBState->cookieOldestTime = data.oldestTime;
|
||||
|
||||
COOKIE_LOGSTRING(LogLevel::Debug,
|
||||
("PurgeCookies(): %ld expired; %ld purged; %ld remain; %lld oldest age",
|
||||
@ -3942,6 +4002,47 @@ nsCookieService::GetCookiesFromHost(const nsACString &aHost,
|
||||
return NS_NewArrayEnumerator(aEnumerator, cookieList);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* This structure is used as a in/out parameter when enumerating the cookies
|
||||
* for an app.
|
||||
* It will contain the app id and onlyBrowserElement flag information as input
|
||||
* and will contain the array of matching cookies as output.
|
||||
*/
|
||||
struct GetCookiesForAppStruct {
|
||||
uint32_t appId;
|
||||
bool onlyBrowserElement;
|
||||
nsCOMArray<nsICookie> cookies;
|
||||
|
||||
GetCookiesForAppStruct() = delete;
|
||||
GetCookiesForAppStruct(uint32_t aAppId, bool aOnlyBrowserElement)
|
||||
: appId(aAppId)
|
||||
, onlyBrowserElement(aOnlyBrowserElement)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsCookieService::GetCookiesForApp(nsCookieEntry* entry, void* arg)
|
||||
{
|
||||
GetCookiesForAppStruct* data = static_cast<GetCookiesForAppStruct*>(arg);
|
||||
|
||||
if (entry->mAppId != data->appId ||
|
||||
(data->onlyBrowserElement && !entry->mInBrowserElement)) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
const nsCookieEntry::ArrayType& cookies = entry->GetCookies();
|
||||
|
||||
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
|
||||
data->cookies.AppendObject(cookies[i]);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookiesForApp(uint32_t aAppId, bool aOnlyBrowserElement,
|
||||
nsISimpleEnumerator** aEnumerator)
|
||||
@ -3953,23 +4054,10 @@ nsCookieService::GetCookiesForApp(uint32_t aAppId, bool aOnlyBrowserElement,
|
||||
|
||||
NS_ENSURE_TRUE(aAppId != NECKO_UNKNOWN_APP_ID, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsCOMArray<nsICookie> cookies;
|
||||
for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCookieEntry* entry = iter.Get();
|
||||
GetCookiesForAppStruct data(aAppId, aOnlyBrowserElement);
|
||||
mDBState->hostTable.EnumerateEntries(GetCookiesForApp, &data);
|
||||
|
||||
if (entry->mAppId != aAppId ||
|
||||
(aOnlyBrowserElement && !entry->mInBrowserElement)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const nsCookieEntry::ArrayType& entryCookies = entry->GetCookies();
|
||||
|
||||
for (nsCookieEntry::IndexType i = 0; i < entryCookies.Length(); ++i) {
|
||||
cookies.AppendObject(entryCookies[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_NewArrayEnumerator(aEnumerator, cookies);
|
||||
return NS_NewArrayEnumerator(aEnumerator, data.cookies);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -316,6 +316,12 @@ class nsCookieService final : public nsICookieService
|
||||
already_AddRefed<nsIArray> CreatePurgeList(nsICookie2* aCookie);
|
||||
void UpdateCookieOldestTime(DBState* aDBState, nsCookie* aCookie);
|
||||
|
||||
/**
|
||||
* This method is used to iterate the cookie hash table and select the ones
|
||||
* that are part of a specific app.
|
||||
*/
|
||||
static PLDHashOperator GetCookiesForApp(nsCookieEntry* entry, void* arg);
|
||||
|
||||
/**
|
||||
* This method is a helper that allows calling nsICookieManager::Remove()
|
||||
* with appId/inBrowserElement parameters.
|
||||
@ -350,6 +356,7 @@ class nsCookieService final : public nsICookieService
|
||||
int64_t mCookiePurgeAge;
|
||||
|
||||
// friends!
|
||||
friend PLDHashOperator purgeCookiesCallback(nsCookieEntry *aEntry, void *aArg);
|
||||
friend class DBListenerErrorHandler;
|
||||
friend class ReadCookieDBListener;
|
||||
friend class CloseCookieDBListener;
|
||||
|
Loading…
Reference in New Issue
Block a user