1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file. 4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <cstdlib> 6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <fstream> 7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <iostream> 8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <string> 9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <vector> 10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/at_exit.h" 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/bind.h" 13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/callback.h" 14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/command_line.h" 15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/files/file_path.h" 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h" 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/memory/scoped_vector.h" 19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/message_loop/message_loop.h" 20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/run_loop.h" 22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_piece.h" 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_split.h" 25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/stringprintf.h" 26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/cache_type.h" 27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/net_errors.h" 28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/disk_cache/disk_cache.h" 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/disk_cache/simple/simple_backend_impl.h" 30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/disk_cache/simple/simple_index.h" 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace disk_cache { 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace { 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kBlockFileBackendType[] = "block_file"; 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kSimpleBackendType[] = "simple"; 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kDiskCacheType[] = "disk_cache"; 39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kAppCacheType[] = "app_cache"; 40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kPrivateDirty[] = "Private_Dirty:"; 42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kReadWrite[] = "rw-"; 43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kHeap[] = "[heap]"; 44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kKb[] = "kB"; 45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)struct CacheSpec { 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public: 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) static scoped_ptr<CacheSpec> Parse(const std::string& spec_string) { 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<std::string> tokens; 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::SplitString(spec_string, ':', &tokens); 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (tokens.size() != 3) 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<CacheSpec>(); 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (tokens[0] != kBlockFileBackendType && tokens[0] != kSimpleBackendType) 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<CacheSpec>(); 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (tokens[1] != kDiskCacheType && tokens[1] != kAppCacheType) 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<CacheSpec>(); 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<CacheSpec>(new CacheSpec( 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tokens[0] == kBlockFileBackendType ? net::CACHE_BACKEND_BLOCKFILE 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : net::CACHE_BACKEND_SIMPLE, 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) tokens[1] == kDiskCacheType ? net::DISK_CACHE : net::APP_CACHE, 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::FilePath(tokens[2]))); 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const net::BackendType backend_type; 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const net::CacheType cache_type; 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const base::FilePath path; 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private: 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CacheSpec(net::BackendType backend_type, 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) net::CacheType cache_type, 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const base::FilePath& path) 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : backend_type(backend_type), 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) cache_type(cache_type), 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) path(path) { 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}; 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SetSuccessCodeOnCompletion(base::RunLoop* run_loop, 79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool* succeeded, 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int net_error) { 81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (net_error == net::OK) { 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *succeeded = true; 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *succeeded = false; 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) run_loop->Quit(); 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<Backend> CreateAndInitBackend(const CacheSpec& spec) { 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) scoped_ptr<Backend> result; 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) scoped_ptr<Backend> backend; 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool succeeded = false; 93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::RunLoop run_loop; 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const net::CompletionCallback callback = base::Bind( 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) &SetSuccessCodeOnCompletion, 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Unretained(&run_loop), 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Unretained(&succeeded)); 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const int net_error = CreateCacheBackend( 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) spec.cache_type, spec.backend_type, spec.path, 0, false, 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::MessageLoopProxy::current(), NULL, &backend, callback); 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (net_error == net::OK) 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) callback.Run(net::OK); 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) run_loop.Run(); 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!succeeded) { 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "Could not initialize backend in " 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << spec.path.LossyDisplayName(); 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return result.Pass(); 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // For the simple cache, the index may not be initialized yet. 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (spec.backend_type == net::CACHE_BACKEND_SIMPLE) { 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::RunLoop index_run_loop; 113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const net::CompletionCallback index_callback = base::Bind( 114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) &SetSuccessCodeOnCompletion, 115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Unretained(&index_run_loop), 116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Unretained(&succeeded)); 117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SimpleBackendImpl* simple_backend = 118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) static_cast<SimpleBackendImpl*>(backend.get()); 119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const int index_net_error = 120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) simple_backend->index()->ExecuteWhenReady(index_callback); 121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (index_net_error == net::OK) 122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) index_callback.Run(net::OK); 123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) index_run_loop.Run(); 125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!succeeded) { 126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "Could not initialize Simple Cache in " 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << spec.path.LossyDisplayName(); 128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return result.Pass(); 129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(backend); 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) result.swap(backend); 133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return result.Pass(); 134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Parses range lines from /proc/<PID>/smaps, e.g. (anonymous read write): 137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// 7f819d88b000-7f819d890000 rw-p 00000000 00:00 0 138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool ParseRangeLine(const std::string& line, 139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::vector<std::string>* tokens, 140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool* is_anonymous_read_write) { 141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) tokens->clear(); 142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::SplitStringAlongWhitespace(line, tokens); 143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (tokens->size() == 5) { 144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string& mode = (*tokens)[1]; 145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *is_anonymous_read_write = !mode.compare(0, 3, kReadWrite); 146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 148424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // On Android, most of the memory is allocated in the heap, instead of being 149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // mapped. 150424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (tokens->size() == 6) { 151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string& type = (*tokens)[5]; 152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *is_anonymous_read_write = (type == kHeap); 153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Parses range property lines from /proc/<PID>/smaps, e.g.: 159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Private_Dirty: 16 kB 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Returns |false| iff it recognizes a new range line. Outputs non-zero |size| 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// only if parsing succeeded. 163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool ParseRangeProperty(const std::string& line, 164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::vector<std::string>* tokens, 165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint64* size, 166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool* is_private_dirty) { 167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) tokens->clear(); 168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::SplitStringAlongWhitespace(line, tokens); 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If the line is long, attempt to parse new range outside of this scope. 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (tokens->size() > 3) 172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Skip the line on other parsing error occasions. 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (tokens->size() < 3) 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string& type = (*tokens)[0]; 178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (type != kPrivateDirty) 179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string& unit = (*tokens)[2]; 181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (unit != kKb) { 182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(WARNING) << "Discarding value not in kB: " << line; 183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string& size_str = (*tokens)[1]; 186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint64 map_size = 0; 187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!base::StringToUint64(size_str, &map_size)) 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *is_private_dirty = true; 190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *size = map_size; 191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)uint64 GetMemoryConsumption() { 195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::ifstream maps_file( 196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::StringPrintf("/proc/%d/smaps", getpid()).c_str()); 197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!maps_file.good()) { 198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "Could not open smaps file."; 199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string line; 202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::vector<std::string> tokens; 203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint64 total_size = 0; 204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!std::getline(maps_file, line) || line.empty()) 205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return total_size; 206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) while (true) { 207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_anonymous_read_write = false; 208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!ParseRangeLine(line, &tokens, &is_anonymous_read_write)) { 209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(WARNING) << "Parsing smaps - did not expect line: " << line; 210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!std::getline(maps_file, line) || line.empty()) 212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return total_size; 213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool is_private_dirty = false; 214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint64 size = 0; 215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) while (ParseRangeProperty(line, &tokens, &size, &is_private_dirty)) { 216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (is_anonymous_read_write && is_private_dirty) { 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) total_size += size; 218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) is_private_dirty = false; 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!std::getline(maps_file, line) || line.empty()) 221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return total_size; 222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return total_size; 225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool CacheMemTest(const ScopedVector<CacheSpec>& specs) { 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedVector<Backend> backends; 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedVector<CacheSpec>::const_iterator it; 23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (it = specs.begin(); it != specs.end(); ++it) { 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<Backend> backend = CreateAndInitBackend(**it); 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!backend) 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::cout << "Number of entries in " << (*it)->path.LossyDisplayName() 23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << " : " << backend->GetEntryCount() << std::endl; 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) backends.push_back(backend.release()); 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const uint64 memory_consumption = GetMemoryConsumption(); 239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::cout << "Private dirty memory: " << memory_consumption << " kB" 240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << std::endl; 241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PrintUsage(std::ostream* stream) { 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *stream << "Usage: disk_cache_mem_test " 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "--spec-1=<spec> " 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "[--spec-2=<spec>]" 248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << std::endl 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << " with <cache_spec>=<backend_type>:<cache_type>:<cache_path>" 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << std::endl 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << " <backend_type>='block_file'|'simple'" << std::endl 252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << " <cache_type>='disk_cache'|'app_cache'" << std::endl 253424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << " <cache_path>=file system path" << std::endl; 254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 255424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ParseAndStoreSpec(const std::string& spec_str, 25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedVector<CacheSpec>* specs) { 25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<CacheSpec> spec = CacheSpec::Parse(spec_str); 25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!spec) { 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PrintUsage(&std::cerr); 26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) specs->push_back(spec.release()); 26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool Main(int argc, char** argv) { 268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::AtExitManager at_exit_manager; 269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::MessageLoopForIO message_loop; 27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::CommandLine::Init(argc, argv); 27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::CommandLine& command_line = 27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *base::CommandLine::ForCurrentProcess(); 273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (command_line.HasSwitch("help")) { 274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) PrintUsage(&std::cout); 275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if ((command_line.GetSwitches().size() != 1 && 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) command_line.GetSwitches().size() != 2) || 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !command_line.HasSwitch("spec-1") || 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (command_line.GetSwitches().size() == 2 && 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !command_line.HasSwitch("spec-2"))) { 282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) PrintUsage(&std::cerr); 283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ScopedVector<CacheSpec> specs; 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string spec_str_1 = command_line.GetSwitchValueASCII("spec-1"); 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ParseAndStoreSpec(spec_str_1, &specs)) 288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (command_line.HasSwitch("spec-2")) { 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string spec_str_2 = command_line.GetSwitchValueASCII("spec-2"); 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!ParseAndStoreSpec(spec_str_2, &specs)) 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return CacheMemTest(specs); 295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace 298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace disk_cache 299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int main(int argc, char** argv) { 301424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return !disk_cache::Main(argc, argv); 302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 303