1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
/*
This test exercises the CacheFileContextEvictor::WasEvicted API and code using it.
- We store 10+10 (pinned and non-pinned) entries to the cache, wait for them being written.
- Then we purge the memory pools.
- Now the IO thread is suspended on the EVICT (7) level to prevent actual deletion of the files.
- Index is disabled.
- We do clear() of the cache, this creates the "ce_*" file and posts to the EVICT level
the eviction loop mechanics.
- We open again those 10+10 entries previously stored.
- IO is resumed
- We expect to get all the pinned and
loose all the non-pinned (common) entries.
*/
const kENTRYCOUNT = 10;
function log_(msg) { if (true) dump(">>>>>>>>>>>>> " + msg + "\n"); }
function run_test()
{
do_get_profile();
if (!newCacheBackEndUsed()) {
do_check_true(true, "This test checks only cache2 specific behavior.");
return;
}
var lci = LoadContextInfo.default;
var testingInterface = get_cache_service().QueryInterface(Ci.nsICacheTesting);
do_check_true(testingInterface);
var mc = new MultipleCallbacks(1, function() {
// (2)
mc = new MultipleCallbacks(1, finish_cache2_test);
// Release all references to cache entries so that they can be purged
// Calling gc() four times is needed to force it to actually release
// entries that are obviously unreferenced. Yeah, I know, this is wacky...
gc();
gc();
do_execute_soon(() => {
gc();
gc();
log_("purging");
// Invokes cacheservice:purge-memory-pools when done.
get_cache_service().purgeFromMemory(Ci.nsICacheStorageService.PURGE_EVERYTHING); // goes to (3)
});
}, true);
// (1), here we start
log_("first set of opens");
var i;
for (i = 0; i < kENTRYCOUNT; ++i) {
// Callbacks 1-20
mc.add();
asyncOpenCacheEntry("http://pinned" + i + "/", "pin", Ci.nsICacheStorage.OPEN_TRUNCATE, lci,
new OpenCallback(NEW|WAITFORWRITE, "m" + i, "p" + i, function(entry) { mc.fired(); }));
mc.add();
asyncOpenCacheEntry("http://common" + i + "/", "disk", Ci.nsICacheStorage.OPEN_TRUNCATE, lci,
new OpenCallback(NEW|WAITFORWRITE, "m" + i, "d" + i, function(entry) { mc.fired(); }));
}
mc.fired(); // Goes to (2)
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver({
observe: function(subject, topic, data)
{
// (3)
log_("after purge");
// Prevent the I/O thread from evicting physically the data. We first want to re-open the entries.
// This deterministically emulates a slow hard drive.
testingInterface.suspendCacheIOThread(7);
log_("clearing");
// Now clear everything except pinned. Stores the "ce_*" file and schedules background eviction.
get_cache_service().clear();
log_("cleared");
log_("second set of opens");
// Now open again. Pinned entries should be there, disk entries should be the renewed entries.
// Callbacks 21-40
for (i = 0; i < kENTRYCOUNT; ++i) {
mc.add();
asyncOpenCacheEntry("http://pinned" + i + "/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, lci,
new OpenCallback(NORMAL, "m" + i, "p" + i, function(entry) { mc.fired(); }));
mc.add();
asyncOpenCacheEntry("http://common" + i + "/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, lci,
new OpenCallback(NEW, "m2" + i, "d2" + i, function(entry) { mc.fired(); }));
}
// Resume IO, this will just pop-off the CacheFileContextEvictor::EvictEntries() because of
// an early check on CacheIOThread::YieldAndRerun() in that method.
// CacheFileIOManager::OpenFileInternal should now run and CacheFileContextEvictor::WasEvicted
// should be checked on.
log_("resuming");
testingInterface.resumeCacheIOThread();
log_("resumed");
mc.fired(); // Finishes this test
}
}, "cacheservice:purge-memory-pools", false);
do_test_pending();
}
|