| 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 |