Backed out changeset 18d79e1e15f9 (bug 958317)

This commit is contained in:
Ed Morley 2014-03-05 17:24:52 +00:00
Родитель 24bad37290
Коммит 6fee27b115
5 изменённых файлов: 104 добавлений и 106 удалений

Просмотреть файл

@ -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)) {