OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This is a simple application that stress-tests the crash recovery of the disk | 5 // This is a simple application that stress-tests the crash recovery of the disk |
6 // cache. The main application starts a copy of itself on a loop, checking the | 6 // cache. The main application starts a copy of itself on a loop, checking the |
7 // exit code of the child process. When the child dies in an unexpected way, | 7 // exit code of the child process. When the child dies in an unexpected way, |
8 // the main application quits. | 8 // the main application quits. |
9 | 9 |
10 // The child application has two threads: one to exercise the cache in an | 10 // The child application has two threads: one to exercise the cache in an |
11 // infinite loop, and another one to asynchronously kill the process. | 11 // infinite loop, and another one to asynchronously kill the process. |
12 | 12 |
13 #include <string> | 13 #include <string> |
14 #include <vector> | 14 #include <vector> |
15 | 15 |
16 #include "base/at_exit.h" | 16 #include "base/at_exit.h" |
17 #include "base/command_line.h" | 17 #include "base/command_line.h" |
18 #include "base/debug_util.h" | 18 #include "base/debug_util.h" |
19 #include "base/file_path.h" | 19 #include "base/file_path.h" |
20 #include "base/logging.h" | 20 #include "base/logging.h" |
21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
23 #include "base/platform_thread.h" | 23 #include "base/platform_thread.h" |
24 #include "base/process_util.h" | 24 #include "base/process_util.h" |
25 #include "base/string_util.h" | 25 #include "base/string_util.h" |
26 #include "base/thread.h" | 26 #include "base/thread.h" |
| 27 #include "net/base/net_errors.h" |
| 28 #include "net/base/test_completion_callback.h" |
27 #include "net/base/io_buffer.h" | 29 #include "net/base/io_buffer.h" |
28 #include "net/disk_cache/backend_impl.h" | 30 #include "net/disk_cache/backend_impl.h" |
29 #include "net/disk_cache/disk_cache.h" | 31 #include "net/disk_cache/disk_cache.h" |
30 #include "net/disk_cache/disk_cache_test_util.h" | 32 #include "net/disk_cache/disk_cache_test_util.h" |
31 | 33 |
32 using base::Time; | 34 using base::Time; |
33 | 35 |
34 const int kError = -1; | 36 const int kError = -1; |
35 const int kExpectedCrash = 100; | 37 const int kExpectedCrash = 100; |
36 | 38 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 } | 72 } |
71 | 73 |
72 // ----------------------------------------------------------------------- | 74 // ----------------------------------------------------------------------- |
73 | 75 |
74 // This thread will loop forever, adding and removing entries from the cache. | 76 // This thread will loop forever, adding and removing entries from the cache. |
75 // iteration is the current crash cycle, so the entries on the cache are marked | 77 // iteration is the current crash cycle, so the entries on the cache are marked |
76 // to know which instance of the application wrote them. | 78 // to know which instance of the application wrote them. |
77 void StressTheCache(int iteration) { | 79 void StressTheCache(int iteration) { |
78 int cache_size = 0x800000; // 8MB | 80 int cache_size = 0x800000; // 8MB |
79 FilePath path = GetCacheFilePath().AppendASCII("_stress"); | 81 FilePath path = GetCacheFilePath().AppendASCII("_stress"); |
80 disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(path); | 82 |
81 cache->SetFlags(disk_cache::kNoLoadProtection | disk_cache::kNoRandom); | 83 base::Thread cache_thread("CacheThread"); |
82 cache->SetMaxSize(cache_size); | 84 if (!cache_thread.StartWithOptions( |
83 cache->SetType(net::DISK_CACHE); | 85 base::Thread::Options(MessageLoop::TYPE_IO, 0))) |
84 if (!cache->Init()) { | 86 return; |
| 87 |
| 88 TestCompletionCallback cb; |
| 89 disk_cache::Backend* cache; |
| 90 int rv = disk_cache::BackendImpl::CreateBackend( |
| 91 path, false, cache_size, net::DISK_CACHE, |
| 92 disk_cache::kNoLoadProtection | disk_cache::kNoRandom, |
| 93 cache_thread.message_loop_proxy(), &cache, &cb); |
| 94 |
| 95 if (cb.GetResult(rv) != net::OK) { |
85 printf("Unable to initialize cache.\n"); | 96 printf("Unable to initialize cache.\n"); |
86 return; | 97 return; |
87 } | 98 } |
88 printf("Iteration %d, initial entries: %d\n", iteration, | 99 printf("Iteration %d, initial entries: %d\n", iteration, |
89 cache->GetEntryCount()); | 100 cache->GetEntryCount()); |
90 | 101 |
91 int seed = static_cast<int>(Time::Now().ToInternalValue()); | 102 int seed = static_cast<int>(Time::Now().ToInternalValue()); |
92 srand(seed); | 103 srand(seed); |
93 | 104 |
94 const int kNumKeys = 5000; | 105 const int kNumKeys = 5000; |
95 const int kNumEntries = 30; | 106 const int kNumEntries = 30; |
96 std::string keys[kNumKeys]; | 107 std::string keys[kNumKeys]; |
97 disk_cache::Entry* entries[kNumEntries] = {0}; | 108 disk_cache::Entry* entries[kNumEntries] = {0}; |
98 | 109 |
99 for (int i = 0; i < kNumKeys; i++) { | 110 for (int i = 0; i < kNumKeys; i++) { |
100 keys[i] = GenerateKey(true); | 111 keys[i] = GenerateKey(true); |
101 } | 112 } |
102 | 113 |
103 const int kSize = 4000; | 114 const int kSize = 4000; |
104 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); | 115 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); |
105 memset(buffer->data(), 'k', kSize); | 116 memset(buffer->data(), 'k', kSize); |
106 | 117 |
107 for (int i = 0;; i++) { | 118 for (int i = 0;; i++) { |
108 int slot = rand() % kNumEntries; | 119 int slot = rand() % kNumEntries; |
109 int key = rand() % kNumKeys; | 120 int key = rand() % kNumKeys; |
110 | 121 |
111 if (entries[slot]) | 122 if (entries[slot]) |
112 entries[slot]->Close(); | 123 entries[slot]->Close(); |
113 | 124 |
114 if (!cache->OpenEntry(keys[key], &entries[slot])) | 125 rv = cache->OpenEntry(keys[key], &entries[slot], &cb); |
115 CHECK(cache->CreateEntry(keys[key], &entries[slot])); | 126 if (cb.GetResult(rv) != net::OK) { |
| 127 rv = cache->CreateEntry(keys[key], &entries[slot], &cb); |
| 128 CHECK_EQ(net::OK, cb.GetResult(rv)); |
| 129 } |
116 | 130 |
117 base::snprintf(buffer->data(), kSize, "%d %d", iteration, i); | 131 base::snprintf(buffer->data(), kSize, "%d %d", iteration, i); |
118 CHECK_EQ(kSize, | 132 rv = entries[slot]->WriteData(0, 0, buffer, kSize, &cb, false); |
119 entries[slot]->WriteData(0, 0, buffer, kSize, NULL, false)); | 133 CHECK_EQ(kSize, cb.GetResult(rv)); |
120 | 134 |
121 if (rand() % 100 > 80) { | 135 if (rand() % 100 > 80) { |
122 key = rand() % kNumKeys; | 136 key = rand() % kNumKeys; |
123 cache->DoomEntry(keys[key]); | 137 cache->DoomEntry(keys[key]); |
124 } | 138 } |
125 | 139 |
126 if (!(i % 100)) | 140 if (!(i % 100)) |
127 printf("Entries: %d \r", i); | 141 printf("Entries: %d \r", i); |
128 MessageLoop::current()->RunAllPending(); | 142 MessageLoop::current()->RunAllPending(); |
129 } | 143 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 long int iteration = strtol(argv[1], &end, 0); | 213 long int iteration = strtol(argv[1], &end, 0); |
200 | 214 |
201 if (!StartCrashThread()) { | 215 if (!StartCrashThread()) { |
202 printf("failed to start thread\n"); | 216 printf("failed to start thread\n"); |
203 return kError; | 217 return kError; |
204 } | 218 } |
205 | 219 |
206 StressTheCache(iteration); | 220 StressTheCache(iteration); |
207 return 0; | 221 return 0; |
208 } | 222 } |
OLD | NEW |