зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 18d79e1e15f9 (bug 958317)
This commit is contained in:
Родитель
24bad37290
Коммит
6fee27b115
|
@ -42,7 +42,9 @@ namespace net {
|
|||
|
||||
#define kOpenHandlesLimit 64
|
||||
#define kMetadataWriteDelay 5000
|
||||
#define kEvictionLoopLimit 40 // in milliseconds
|
||||
#define kRemoveTrashStartDelay 60000 // in milliseconds
|
||||
#define kRemoveTrashLoopLimit 40 // in milliseconds
|
||||
|
||||
bool
|
||||
CacheFileHandle::DispatchRelease()
|
||||
|
@ -2351,7 +2353,7 @@ CacheFileIOManager::OverLimitEvictionInternal()
|
|||
MOZ_ASSERT(mIOThread->IsCurrentThread());
|
||||
|
||||
// mOverLimitEvicting is accessed only on IO thread, so we can set it to false
|
||||
// here and set it to true again once we dispatch another event that will
|
||||
// here and set ti to true again once we dispatch another event that will
|
||||
// continue with the eviction. The reason why we do so is that we can fail
|
||||
// early anywhere in this method and the variable will contain a correct
|
||||
// value. Otherwise we would need to set it to false on every failing place.
|
||||
|
@ -2361,6 +2363,8 @@ CacheFileIOManager::OverLimitEvictionInternal()
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
TimeStamp start;
|
||||
|
||||
while (true) {
|
||||
uint32_t cacheUsage;
|
||||
rv = CacheIndex::GetCacheSize(&cacheUsage);
|
||||
|
@ -2376,11 +2380,15 @@ CacheFileIOManager::OverLimitEvictionInternal()
|
|||
LOG(("CacheFileIOManager::OverLimitEvictionInternal() - Cache size over "
|
||||
"limit. [cacheSize=%u, limit=%u]", cacheUsage, cacheLimit));
|
||||
|
||||
if (CacheIOThread::YieldAndRerun()) {
|
||||
LOG(("CacheFileIOManager::OverLimitEvictionInternal() - Breaking loop "
|
||||
"for higher level events."));
|
||||
mOverLimitEvicting = true;
|
||||
return NS_OK;
|
||||
if (start.IsNull()) {
|
||||
start = TimeStamp::NowLoRes();
|
||||
} else {
|
||||
TimeDuration elapsed = TimeStamp::NowLoRes() - start;
|
||||
if (elapsed.ToMilliseconds() >= kEvictionLoopLimit) {
|
||||
LOG(("CacheFileIOManager::OverLimitEvictionInternal() - Breaking loop "
|
||||
"after %u ms.", static_cast<uint32_t>(elapsed.ToMilliseconds())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SHA1Sum::Hash hash;
|
||||
|
@ -2435,7 +2443,14 @@ CacheFileIOManager::OverLimitEvictionInternal()
|
|||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("We should never get here");
|
||||
nsCOMPtr<nsIRunnable> ev;
|
||||
ev = NS_NewRunnableMethod(this,
|
||||
&CacheFileIOManager::OverLimitEvictionInternal);
|
||||
|
||||
rv = mIOThread->Dispatch(ev, CacheIOThread::EVICT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mOverLimitEvicting = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2613,12 +2628,20 @@ CacheFileIOManager::RemoveTrashInternal()
|
|||
// we don't have to drop the flag on any possible early return.
|
||||
mRemovingTrashDirs = false;
|
||||
|
||||
TimeStamp start;
|
||||
|
||||
while (true) {
|
||||
if (CacheIOThread::YieldAndRerun()) {
|
||||
LOG(("CacheFileIOManager::RemoveTrashInternal() - Breaking loop for "
|
||||
"higher level events."));
|
||||
mRemovingTrashDirs = true;
|
||||
return NS_OK;
|
||||
if (start.IsNull()) {
|
||||
start = TimeStamp::NowLoRes();
|
||||
} else {
|
||||
static TimeDuration const kLimit = TimeDuration::FromMilliseconds(
|
||||
kRemoveTrashLoopLimit);
|
||||
TimeDuration elapsed = TimeStamp::NowLoRes() - start;
|
||||
if (elapsed >= kLimit) {
|
||||
LOG(("CacheFileIOManager::RemoveTrashInternal() - Breaking loop after "
|
||||
"%u ms.", static_cast<uint32_t>(elapsed.ToMilliseconds())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find some trash directory
|
||||
|
@ -2686,7 +2709,14 @@ CacheFileIOManager::RemoveTrashInternal()
|
|||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("We should never get here");
|
||||
nsCOMPtr<nsIRunnable> ev;
|
||||
ev = NS_NewRunnableMethod(this,
|
||||
&CacheFileIOManager::RemoveTrashInternal);
|
||||
|
||||
rv = mIOThread->Dispatch(ev, CacheIOThread::EVICT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mRemovingTrashDirs = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,25 +14,19 @@
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
CacheIOThread* CacheIOThread::sSelf = nullptr;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CacheIOThread, nsIThreadObserver)
|
||||
|
||||
CacheIOThread::CacheIOThread()
|
||||
: mMonitor("CacheIOThread")
|
||||
, mThread(nullptr)
|
||||
, mLowestLevelWaiting(LAST_LEVEL)
|
||||
, mCurrentlyExecutingLevel(0)
|
||||
, mHasXPCOMEvents(false)
|
||||
, mRerunCurrentEvent(false)
|
||||
, mShutdown(false)
|
||||
{
|
||||
sSelf = this;
|
||||
}
|
||||
|
||||
CacheIOThread::~CacheIOThread()
|
||||
{
|
||||
sSelf = nullptr;
|
||||
#ifdef DEBUG
|
||||
for (uint32_t level = 0; level < LAST_LEVEL; ++level) {
|
||||
MOZ_ASSERT(!mEventQueue[level].Length());
|
||||
|
@ -74,27 +68,6 @@ bool CacheIOThread::IsCurrentThread()
|
|||
return mThread == PR_GetCurrentThread();
|
||||
}
|
||||
|
||||
bool CacheIOThread::YieldInternal()
|
||||
{
|
||||
if (!IsCurrentThread()) {
|
||||
NS_WARNING("Trying to yield to priority events on non-cache2 I/O thread? "
|
||||
"You probably do something wrong.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mCurrentlyExecutingLevel == XPCOM_LEVEL) {
|
||||
// Doesn't make any sense, since this handler is the one
|
||||
// that would be executed as the next one.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EventsPending(mCurrentlyExecutingLevel))
|
||||
return false;
|
||||
|
||||
mRerunCurrentEvent = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult CacheIOThread::Shutdown()
|
||||
{
|
||||
{
|
||||
|
@ -164,8 +137,6 @@ loopStart:
|
|||
"net::cache::io::level(xpcom)");
|
||||
|
||||
mHasXPCOMEvents = false;
|
||||
mCurrentlyExecutingLevel = XPCOM_LEVEL;
|
||||
|
||||
MonitorAutoUnlock unlock(mMonitor);
|
||||
|
||||
bool processedEvent;
|
||||
|
@ -233,8 +204,6 @@ void CacheIOThread::LoopOneLevel(uint32_t aLevel)
|
|||
events.SwapElements(mEventQueue[aLevel]);
|
||||
uint32_t length = events.Length();
|
||||
|
||||
mCurrentlyExecutingLevel = aLevel;
|
||||
|
||||
bool returnEvents = false;
|
||||
uint32_t index;
|
||||
{
|
||||
|
@ -248,19 +217,7 @@ void CacheIOThread::LoopOneLevel(uint32_t aLevel)
|
|||
break;
|
||||
}
|
||||
|
||||
// Drop any previous flagging, only an event on the current level may set
|
||||
// this flag.
|
||||
mRerunCurrentEvent = false;
|
||||
|
||||
events[index]->Run();
|
||||
|
||||
if (mRerunCurrentEvent) {
|
||||
// The event handler yields to higher priority events and wants to rerun.
|
||||
returnEvents = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Release outside the lock.
|
||||
events[index] = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,32 +36,12 @@ public:
|
|||
CLOSE,
|
||||
BUILD_OR_UPDATE_INDEX,
|
||||
EVICT,
|
||||
LAST_LEVEL,
|
||||
|
||||
// This is actually executed as the first level, but we want this enum
|
||||
// value merely as an indicator while other values are used as indexes
|
||||
// to the queue array. Hence put at end and not as the first.
|
||||
XPCOM_LEVEL
|
||||
LAST_LEVEL
|
||||
};
|
||||
|
||||
nsresult Init();
|
||||
nsresult Dispatch(nsIRunnable* aRunnable, uint32_t aLevel);
|
||||
bool IsCurrentThread();
|
||||
|
||||
/**
|
||||
* Callable only on this thread, checks if there is an event waiting in
|
||||
* the event queue with a higher execution priority. If so, the result
|
||||
* is true and the current event handler should break it's work and return
|
||||
* from Run() method immediately. The event handler will be rerun again
|
||||
* when all more priority events are processed. Events pending after this
|
||||
* handler (i.e. the one that called YieldAndRerun()) will not execute sooner
|
||||
* then this handler is executed w/o a call to YieldAndRerun().
|
||||
*/
|
||||
static bool YieldAndRerun()
|
||||
{
|
||||
return sSelf ? sSelf->YieldInternal() : false;
|
||||
}
|
||||
|
||||
nsresult Shutdown();
|
||||
already_AddRefed<nsIEventTarget> Target();
|
||||
|
||||
|
@ -74,19 +54,14 @@ private:
|
|||
void ThreadFunc();
|
||||
void LoopOneLevel(uint32_t aLevel);
|
||||
bool EventsPending(uint32_t aLastLevel = LAST_LEVEL);
|
||||
bool YieldInternal();
|
||||
|
||||
static CacheIOThread* sSelf;
|
||||
|
||||
mozilla::Monitor mMonitor;
|
||||
PRThread* mThread;
|
||||
nsCOMPtr<nsIThread> mXPCOMThread;
|
||||
uint32_t mLowestLevelWaiting;
|
||||
uint32_t mCurrentlyExecutingLevel;
|
||||
nsTArray<nsRefPtr<nsIRunnable> > mEventQueue[LAST_LEVEL];
|
||||
|
||||
bool mHasXPCOMEvents;
|
||||
bool mRerunCurrentEvent;
|
||||
bool mShutdown;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define kIndexVersion 0x00000001
|
||||
#define kBuildIndexStartDelay 10000 // in milliseconds
|
||||
#define kUpdateIndexStartDelay 10000 // in milliseconds
|
||||
#define kBuildIndexLoopLimit 40 // in milliseconds
|
||||
#define kUpdateIndexLoopLimit 40 // in milliseconds
|
||||
|
||||
const char kIndexName[] = "index";
|
||||
const char kTempIndexName[] = "index.tmp";
|
||||
|
@ -2367,10 +2369,20 @@ CacheIndex::BuildIndex()
|
|||
}
|
||||
}
|
||||
|
||||
TimeStamp start;
|
||||
|
||||
while (true) {
|
||||
if (CacheIOThread::YieldAndRerun()) {
|
||||
LOG(("CacheIndex::BuildIndex() - Breaking loop for higher level events."));
|
||||
return;
|
||||
if (start.IsNull()) {
|
||||
start = TimeStamp::NowLoRes();
|
||||
} else {
|
||||
static TimeDuration const kLimit = TimeDuration::FromMilliseconds(
|
||||
kBuildIndexLoopLimit);
|
||||
TimeDuration elapsed = TimeStamp::NowLoRes() - start;
|
||||
if (elapsed >= kLimit) {
|
||||
LOG(("CacheIndex::BuildIndex() - Breaking loop after %u ms.",
|
||||
static_cast<uint32_t>(elapsed.ToMilliseconds())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
@ -2472,7 +2484,16 @@ CacheIndex::BuildIndex()
|
|||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("We should never get here");
|
||||
nsRefPtr<CacheIOThread> ioThread = CacheFileIOManager::IOThread();
|
||||
MOZ_ASSERT(ioThread);
|
||||
|
||||
rv = ioThread->Dispatch(this, CacheIOThread::BUILD_OR_UPDATE_INDEX);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("CacheIndex::BuildIndex() - Can't dispatch event");
|
||||
LOG(("CacheIndex::BuildIndex() - Can't dispatch event" ));
|
||||
FinishBuild(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2599,11 +2620,20 @@ CacheIndex::UpdateIndex()
|
|||
}
|
||||
}
|
||||
|
||||
TimeStamp start;
|
||||
|
||||
while (true) {
|
||||
if (CacheIOThread::YieldAndRerun()) {
|
||||
LOG(("CacheIndex::UpdateIndex() - Breaking loop for higher level "
|
||||
"events."));
|
||||
return;
|
||||
if (start.IsNull()) {
|
||||
start = TimeStamp::NowLoRes();
|
||||
} else {
|
||||
static TimeDuration const kLimit = TimeDuration::FromMilliseconds(
|
||||
kUpdateIndexLoopLimit);
|
||||
TimeDuration elapsed = TimeStamp::NowLoRes() - start;
|
||||
if (elapsed >= kLimit) {
|
||||
LOG(("CacheIndex::UpdateIndex() - Breaking loop after %u ms.",
|
||||
static_cast<uint32_t>(elapsed.ToMilliseconds())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
@ -2739,7 +2769,16 @@ CacheIndex::UpdateIndex()
|
|||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("We should never get here");
|
||||
nsRefPtr<CacheIOThread> ioThread = CacheFileIOManager::IOThread();
|
||||
MOZ_ASSERT(ioThread);
|
||||
|
||||
rv = ioThread->Dispatch(this, CacheIOThread::BUILD_OR_UPDATE_INDEX);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("CacheIndex::UpdateIndex() - Can't dispatch event");
|
||||
LOG(("CacheIndex::UpdateIndex() - Can't dispatch event" ));
|
||||
FinishUpdate(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -638,11 +638,13 @@ nsresult CacheFilesDeletor::Execute()
|
|||
}
|
||||
|
||||
nsresult rv;
|
||||
TimeStamp start;
|
||||
|
||||
switch (mMode) {
|
||||
case ALL:
|
||||
case DOOMED:
|
||||
// Simply delete all files, don't doom then though the backend
|
||||
start = TimeStamp::NowLoRes();
|
||||
|
||||
while (mEnumerator->HasMore()) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
@ -663,9 +665,15 @@ nsresult CacheFilesDeletor::Execute()
|
|||
|
||||
++mRunning;
|
||||
|
||||
if (CacheIOThread::YieldAndRerun()) {
|
||||
LOG((" deleted %u files, breaking loop for higher level events."));
|
||||
return NS_OK;
|
||||
if (!(mRunning % (1 << 5)) && mEnumerator->HasMore()) {
|
||||
TimeStamp now(TimeStamp::NowLoRes());
|
||||
#define DELETOR_LOOP_LIMIT_MS 200
|
||||
static TimeDuration const kLimitms = TimeDuration::FromMilliseconds(DELETOR_LOOP_LIMIT_MS);
|
||||
if ((now - start) > kLimitms) {
|
||||
LOG((" deleted %u files, breaking %dms loop", mRunning, DELETOR_LOOP_LIMIT_MS));
|
||||
rv = mIOThread->Dispatch(this, CacheIOThread::EVICT);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1058,9 +1066,7 @@ CacheStorageService::PurgeOverMemoryLimit()
|
|||
|
||||
LOG((" purging took %1.2fms", (TimeStamp::Now() - start).ToMilliseconds()));
|
||||
|
||||
// When we exit because of yield, leave the flag so this event is not reposted
|
||||
// from OnMemoryConsumptionChange unnecessarily until we are dequeued again.
|
||||
mPurging = CacheIOThread::YieldAndRerun();
|
||||
mPurging = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1074,9 +1080,6 @@ CacheStorageService::PurgeExpired()
|
|||
uint32_t const memoryLimit = CacheObserver::MemoryLimit();
|
||||
|
||||
for (uint32_t i = 0; mMemorySize > memoryLimit && i < mExpirationArray.Length();) {
|
||||
if (CacheIOThread::YieldAndRerun())
|
||||
return;
|
||||
|
||||
nsRefPtr<CacheEntry> entry = mExpirationArray[i];
|
||||
|
||||
uint32_t expirationTime = entry->GetExpirationTime();
|
||||
|
@ -1106,9 +1109,6 @@ CacheStorageService::PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat)
|
|||
uint32_t const memoryLimit = CacheObserver::MemoryLimit();
|
||||
|
||||
for (uint32_t i = 0; mMemorySize > memoryLimit && i < mFrecencyArray.Length();) {
|
||||
if (CacheIOThread::YieldAndRerun())
|
||||
return;
|
||||
|
||||
nsRefPtr<CacheEntry> entry = mFrecencyArray[i];
|
||||
|
||||
if (entry->Purge(aWhat)) {
|
||||
|
@ -1129,9 +1129,6 @@ CacheStorageService::PurgeAll(uint32_t aWhat)
|
|||
MOZ_ASSERT(IsOnManagementThread());
|
||||
|
||||
for (uint32_t i = 0; i < mFrecencyArray.Length();) {
|
||||
if (CacheIOThread::YieldAndRerun())
|
||||
return;
|
||||
|
||||
nsRefPtr<CacheEntry> entry = mFrecencyArray[i];
|
||||
|
||||
if (entry->Purge(aWhat)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче