Bug 1009500 - HTTP cache v2: respect OPEN_BYPASS_IF_BUSY, r=michal

This commit is contained in:
Honza Bambas 2014-05-14 23:12:38 +02:00
parent 16830192eb
commit 4f3dee8ee7
5 changed files with 57 additions and 5 deletions

View File

@ -264,6 +264,7 @@ void CacheEntry::AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags
this, StateString(mState), aFlags, aCallback));
bool readonly = aFlags & nsICacheStorage::OPEN_READONLY;
bool bypassIfBusy = aFlags & nsICacheStorage::OPEN_BYPASS_IF_BUSY;
bool truncate = aFlags & nsICacheStorage::OPEN_TRUNCATE;
bool priority = aFlags & nsICacheStorage::OPEN_PRIORITY;
bool multithread = aFlags & nsICacheStorage::CHECK_MULTITHREADED;
@ -275,7 +276,7 @@ void CacheEntry::AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags
mozilla::MutexAutoLock lock(mLock);
RememberCallback(callback);
RememberCallback(callback, bypassIfBusy);
// Load() opens the lock
if (Load(truncate, priority)) {
@ -491,12 +492,20 @@ void CacheEntry::TransferCallbacks(CacheEntry & aFromEntry)
}
}
void CacheEntry::RememberCallback(Callback const& aCallback)
void CacheEntry::RememberCallback(Callback & aCallback, bool aBypassIfBusy)
{
LOG(("CacheEntry::RememberCallback [this=%p, cb=%p]", this, aCallback.mCallback.get()));
mLock.AssertCurrentThreadOwns();
LOG(("CacheEntry::RememberCallback [this=%p, cb=%p, state=%s]",
this, aCallback.mCallback.get(), StateString(mState)));
if (aBypassIfBusy && (mState == WRITING || mState == REVALIDATING)) {
LOG((" writing or revalidating, callback wants to bypass cache"));
aCallback.mNotWanted = true;
InvokeAvailableCallback(aCallback);
return;
}
mCallbacks.AppendElement(aCallback);
}

View File

@ -210,7 +210,7 @@ private:
bool Load(bool aTruncate, bool aPriority);
void OnLoaded();
void RememberCallback(Callback const & aCallback);
void RememberCallback(Callback & aCallback, bool aBypassIfBusy);
void InvokeCallbacksLock();
void InvokeCallbacks();
bool InvokeCallbacks(bool aReadOnly);

View File

@ -43,6 +43,8 @@ const RECREATE = 1 << 10;
const NOTWANTED = 1 << 11;
// Tell the cache to wait for the entry to be completely written first
const COMPLETE = 1 << 12;
// Don't write meta/data and don't set valid in the callback, consumer will do it manually
const DONTFILL = 1 << 13;
var log_c2 = true;
function LOG_C2(o, m)
@ -179,6 +181,11 @@ OpenCallback.prototype =
catch (ex) {}
}
if (this.behavior & DONTFILL) {
do_check_false(this.behavior & WAITFORWRITE);
return;
}
var self = this;
do_execute_soon(function() { // emulate network latency
entry.setMetaDataElement("meto", self.workingMetadata);

View File

@ -0,0 +1,35 @@
function run_test()
{
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test doesn't run when the old cache back end is used since the behavior is different");
return;
}
// Open for write, delay the actual write
asyncOpenCacheEntry("http://a/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
new OpenCallback(NEW|DONTFILL, "a1m", "a1d", function(entry) {
var bypassed = false;
// Open and bypass
asyncOpenCacheEntry("http://a/", "disk", Ci.nsICacheStorage.OPEN_BYPASS_IF_BUSY, null,
new OpenCallback(NOTFOUND, "", "", function(entry) {
do_check_false(bypassed);
bypassed = true;
})
);
// do_execute_soon for two reasons:
// 1. we want finish_cache2_test call for sure after do_test_pending, but all the callbacks here
// may invoke synchronously
// 2. precaution when the OPEN_BYPASS_IF_BUSY invocation become a post one day
do_execute_soon(function() {
do_check_true(bypassed);
finish_cache2_test();
});
})
);
do_test_pending();
}

View File

@ -24,6 +24,7 @@ support-files =
[test_cache2-01b-basic-datasize.js]
[test_cache2-01c-basic-hasmeta-only.js]
[test_cache2-01d-basic-not-wanted.js]
[test_cache2-01e-basic-bypass-if-busy.js]
[test_cache2-02-open-non-existing.js]
[test_cache2-03-oncacheentryavail-throws.js]
[test_cache2-04-oncacheentryavail-throws2x.js]