Chromium Code Reviews| Index: base/process/process_metrics_linux.cc |
| diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc |
| index c472d73782c0d3c40c4da8affefff83039377e3b..be166e33e322959bb7d10111e0746dbe5680c27f 100644 |
| --- a/base/process/process_metrics_linux.cc |
| +++ b/base/process/process_metrics_linux.cc |
| @@ -25,69 +25,51 @@ namespace base { |
| namespace { |
| -enum ParsingState { |
| - KEY_NAME, |
| - KEY_VALUE |
| -}; |
| - |
| -#ifdef OS_CHROMEOS |
| +#if defined(OS_CHROMEOS) |
| // Read a file with a single number string and return the number as a uint64. |
| -static uint64 ReadFileToUint64(const base::FilePath file) { |
| +static uint64 ReadFileToUint64(const FilePath file) { |
| std::string file_as_string; |
| if (!ReadFileToString(file, &file_as_string)) |
| return 0; |
| - base::TrimWhitespaceASCII(file_as_string, base::TRIM_ALL, &file_as_string); |
| + TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string); |
| uint64 file_as_uint64 = 0; |
| - if (!base::StringToUint64(file_as_string, &file_as_uint64)) |
| + if (!StringToUint64(file_as_string, &file_as_uint64)) |
| return 0; |
| return file_as_uint64; |
| } |
| #endif |
| -// Read /proc/<pid>/status and returns the value for |field|, or 0 on failure. |
| +// Read /proc/<pid>/status and return the value for |field|, or 0 on failure. |
| // Only works for fields in the form of "Field: value kB". |
| size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) { |
| - FilePath stat_file = internal::GetProcPidDir(pid).Append("status"); |
| std::string status; |
| { |
| // Synchronously reading files in /proc is safe. |
| ThreadRestrictions::ScopedAllowIO allow_io; |
| + FilePath stat_file = internal::GetProcPidDir(pid).Append("status"); |
| if (!ReadFileToString(stat_file, &status)) |
| return 0; |
| } |
| - StringTokenizer tokenizer(status, ":\n"); |
| - ParsingState state = KEY_NAME; |
| - StringPiece last_key_name; |
| - while (tokenizer.GetNext()) { |
| - switch (state) { |
| - case KEY_NAME: |
| - last_key_name = tokenizer.token_piece(); |
| - state = KEY_VALUE; |
| - break; |
| - case KEY_VALUE: |
| - DCHECK(!last_key_name.empty()); |
| - if (last_key_name == field) { |
| - std::string value_str; |
| - tokenizer.token_piece().CopyToString(&value_str); |
| - std::string value_str_trimmed; |
| - base::TrimWhitespaceASCII(value_str, base::TRIM_ALL, |
| - &value_str_trimmed); |
| - std::vector<std::string> split_value_str; |
| - SplitString(value_str_trimmed, ' ', &split_value_str); |
| - if (split_value_str.size() != 2 || split_value_str[1] != "kB") { |
| - NOTREACHED(); |
| - return 0; |
| - } |
| - size_t value; |
| - if (!StringToSizeT(split_value_str[0], &value)) { |
| - NOTREACHED(); |
| - return 0; |
| - } |
| - return value; |
| - } |
| - state = KEY_NAME; |
| - break; |
| + std::vector<std::pair<std::string, std::string> > pairs; |
| + SplitStringIntoKeyValuePairs(status, ':', '\n', &pairs); |
| + for (size_t i = 0; i < pairs.size(); ++i) { |
| + std::string key, value_str; |
| + TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key); |
| + TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value_str); |
| + if (key == field) { |
| + std::vector<std::string> split_value_str; |
| + SplitString(value_str, ' ', &split_value_str); |
| + if (split_value_str.size() != 2 || split_value_str[1] != "kB") { |
| + NOTREACHED(); |
| + return 0; |
| + } |
| + size_t value; |
| + if (!StringToSizeT(split_value_str[0], &value)) { |
| + NOTREACHED(); |
| + return 0; |
| + } |
| + return value; |
| } |
| } |
| NOTREACHED(); |
| @@ -223,36 +205,28 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { |
| if (!ReadFileToString(io_file, &proc_io_contents)) |
| return false; |
| - (*io_counters).OtherOperationCount = 0; |
| - (*io_counters).OtherTransferCount = 0; |
| - |
| - StringTokenizer tokenizer(proc_io_contents, ": \n"); |
| - ParsingState state = KEY_NAME; |
| - StringPiece last_key_name; |
| - while (tokenizer.GetNext()) { |
| - switch (state) { |
| - case KEY_NAME: |
| - last_key_name = tokenizer.token_piece(); |
| - state = KEY_VALUE; |
| - break; |
| - case KEY_VALUE: |
| - DCHECK(!last_key_name.empty()); |
| - if (last_key_name == "syscr") { |
| - StringToInt64(tokenizer.token_piece(), |
| - reinterpret_cast<int64*>(&(*io_counters).ReadOperationCount)); |
| - } else if (last_key_name == "syscw") { |
| - StringToInt64(tokenizer.token_piece(), |
| - reinterpret_cast<int64*>(&(*io_counters).WriteOperationCount)); |
| - } else if (last_key_name == "rchar") { |
| - StringToInt64(tokenizer.token_piece(), |
| - reinterpret_cast<int64*>(&(*io_counters).ReadTransferCount)); |
| - } else if (last_key_name == "wchar") { |
| - StringToInt64(tokenizer.token_piece(), |
| - reinterpret_cast<int64*>(&(*io_counters).WriteTransferCount)); |
| - } |
| - state = KEY_NAME; |
| - break; |
| - } |
| + io_counters->OtherOperationCount = 0; |
| + io_counters->OtherTransferCount = 0; |
| + |
| + std::vector<std::pair<std::string, std::string> > pairs; |
| + SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs); |
| + for (size_t i = 0; i < pairs.size(); ++i) { |
| + std::string key, value_str; |
| + TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key); |
| + TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value_str); |
| + uint64* target_counter = NULL; |
| + if (key == "syscr") |
| + target_counter = &io_counters->ReadOperationCount; |
| + else if (key == "syscw") |
| + target_counter = &io_counters->WriteOperationCount; |
| + else if (key == "rchar") |
| + target_counter = &io_counters->ReadTransferCount; |
| + else if (key == "wchar") |
| + target_counter = &io_counters->WriteTransferCount; |
| + if (!target_counter) |
| + continue; |
| + bool converted = StringToUint64(value_str, target_counter); |
| + DCHECK(converted); |
| } |
| return true; |
| } |
| @@ -261,7 +235,7 @@ ProcessMetrics::ProcessMetrics(ProcessHandle process) |
| : process_(process), |
| last_system_time_(0), |
| last_cpu_(0) { |
| - processor_count_ = base::SysInfo::NumberOfProcessors(); |
| + processor_count_ = SysInfo::NumberOfProcessors(); |
| } |
| #if defined(OS_CHROMEOS) |
| @@ -480,7 +454,7 @@ SystemMemoryInfoKB::SystemMemoryInfoKB() { |
| } |
| scoped_ptr<Value> SystemMemoryInfoKB::ToValue() const { |
| - scoped_ptr<DictionaryValue> res(new base::DictionaryValue()); |
| + scoped_ptr<DictionaryValue> res(new DictionaryValue()); |
| res->SetInteger("total", total); |
| res->SetInteger("free", free); |
| @@ -532,61 +506,49 @@ bool ParseProcMeminfo(const std::string& meminfo_data, |
| SplitStringAlongWhitespace(*it, &tokens); |
| // HugePages_* only has a number and no suffix so we can't rely on |
| // there being exactly 3 tokens. |
| - if (tokens.size() > 1) { |
| - if (tokens[0] == "MemTotal:") { |
| - StringToInt(tokens[1], &meminfo->total); |
| - continue; |
| - } if (tokens[0] == "MemFree:") { |
| - StringToInt(tokens[1], &meminfo->free); |
| - continue; |
| - } if (tokens[0] == "Buffers:") { |
| - StringToInt(tokens[1], &meminfo->buffers); |
| - continue; |
| - } if (tokens[0] == "Cached:") { |
| - StringToInt(tokens[1], &meminfo->cached); |
| - continue; |
| - } if (tokens[0] == "Active(anon):") { |
| - StringToInt(tokens[1], &meminfo->active_anon); |
| - continue; |
| - } if (tokens[0] == "Inactive(anon):") { |
| - StringToInt(tokens[1], &meminfo->inactive_anon); |
| - continue; |
| - } if (tokens[0] == "Active(file):") { |
| - StringToInt(tokens[1], &meminfo->active_file); |
| - continue; |
| - } if (tokens[0] == "Inactive(file):") { |
| - StringToInt(tokens[1], &meminfo->inactive_file); |
| - continue; |
| - } if (tokens[0] == "SwapTotal:") { |
| - StringToInt(tokens[1], &meminfo->swap_total); |
| - continue; |
| - } if (tokens[0] == "SwapFree:") { |
| - StringToInt(tokens[1], &meminfo->swap_free); |
| - continue; |
| - } if (tokens[0] == "Dirty:") { |
| - StringToInt(tokens[1], &meminfo->dirty); |
| - continue; |
| -#if defined(OS_CHROMEOS) |
| - // Chrome OS has a tweaked kernel that allows us to query Shmem, which is |
| - // usually video memory otherwise invisible to the OS. |
| - } if (tokens[0] == "Shmem:") { |
| - StringToInt(tokens[1], &meminfo->shmem); |
| - continue; |
| - } if (tokens[0] == "Slab:") { |
| - StringToInt(tokens[1], &meminfo->slab); |
| - continue; |
| -#endif |
| - } |
| - } else |
| + if (tokens.size() <= 1) { |
| DLOG(WARNING) << "meminfo: tokens: " << tokens.size() |
| << " malformed line: " << *it; |
| + continue; |
| + } |
| + |
| + int* target = NULL; |
| + if (tokens[0] == "MemTotal:") |
| + target = &meminfo->total; |
| + else if (tokens[0] == "MemFree:") |
| + target = &meminfo->free; |
| + else if (tokens[0] == "Buffers:") |
| + target = &meminfo->buffers; |
| + else if (tokens[0] == "Cached:") |
| + target = &meminfo->cached; |
| + else if (tokens[0] == "Active(anon):") |
| + target = &meminfo->active_anon; |
| + else if (tokens[0] == "Inactive(anon):") |
| + target = &meminfo->inactive_anon; |
| + else if (tokens[0] == "Active(file):") |
| + target = &meminfo->active_file; |
| + else if (tokens[0] == "Inactive(file):") |
| + target = &meminfo->inactive_file; |
| + else if (tokens[0] == "SwapTotal:") |
| + target = &meminfo->swap_total; |
| + else if (tokens[0] == "SwapFree:") |
| + target = &meminfo->swap_free; |
| + else if (tokens[0] == "Dirty:") |
| + target = &meminfo->dirty; |
| +#if defined(OS_CHROMEOS) |
| + // Chrome OS has a tweaked kernel that allows us to query Shmem, which is |
| + // usually video memory otherwise invisible to the OS. |
| + else if (tokens[0] == "Shmem:") |
| + target = &meminfo->shmem; |
| + else if (tokens[0] == "Slab:") |
| + target = &meminfo->slab; |
| +#endif |
| + if (target) |
| + StringToInt(tokens[1], target); |
| } |
| // Make sure we got a valid MemTotal. |
| - if (!meminfo->total) |
| - return false; |
| - |
| - return true; |
| + return meminfo->total > 0; |
| } |
| // exposed for testing |
| @@ -609,15 +571,15 @@ bool ParseProcVmstat(const std::string& vmstat_data, |
| it != vmstat_lines.end(); ++it) { |
| std::vector<std::string> tokens; |
| SplitString(*it, ' ', &tokens); |
| - if (tokens.size() == 2) { |
| - if (tokens[0] == "pswpin") { |
| - StringToInt(tokens[1], &meminfo->pswpin); |
| - continue; |
| - } if (tokens[0] == "pswpout") { |
| - StringToInt(tokens[1], &meminfo->pswpout); |
| - continue; |
| - } if (tokens[0] == "pgmajfault") |
| - StringToInt(tokens[1], &meminfo->pgmajfault); |
| + if (tokens.size() != 2) |
| + continue; |
| + |
| + if (tokens[0] == "pswpin") { |
| + StringToInt(tokens[1], &meminfo->pswpin); |
| + } else if (tokens[0] == "pswpout") { |
| + StringToInt(tokens[1], &meminfo->pswpout); |
| + } else if (tokens[0] == "pgmajfault") { |
| + StringToInt(tokens[1], &meminfo->pgmajfault); |
| } |
| } |
| @@ -625,7 +587,7 @@ bool ParseProcVmstat(const std::string& vmstat_data, |
| } |
| bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { |
| - // Synchronously reading files in /proc is safe. |
| + // Synchronously reading files in /proc and /sys are safe. |
| ThreadRestrictions::ScopedAllowIO allow_io; |
| // Used memory is: total - free - buffers - caches |
| @@ -707,7 +669,7 @@ SystemDiskInfo::SystemDiskInfo() { |
| } |
| scoped_ptr<Value> SystemDiskInfo::ToValue() const { |
| - scoped_ptr<DictionaryValue> res(new base::DictionaryValue()); |
| + scoped_ptr<DictionaryValue> res(new DictionaryValue()); |
| // Write out uint64 variables as doubles. |
| // Note: this may discard some precision, but for JS there's no other option. |
| @@ -729,27 +691,28 @@ scoped_ptr<Value> SystemDiskInfo::ToValue() const { |
| bool IsValidDiskName(const std::string& candidate) { |
| if (candidate.length() < 3) |
| return false; |
| - if (candidate.substr(0,2) == "sd" || candidate.substr(0,2) == "hd") { |
| - // [sh]d[a-z]+ case |
| - for (size_t i = 2; i < candidate.length(); i++) { |
| + if (candidate[1] == 'd' && |
| + (candidate[0] == 'h' || candidate[0] == 's' || candidate[0] == 'v')) { |
| + // [hsv]d[a-z]+ case |
|
Lei Zhang
2014/09/06 09:31:58
vd* are virtual disks
|
| + for (size_t i = 2; i < candidate.length(); ++i) { |
| if (!islower(candidate[i])) |
| return false; |
| } |
| - } else { |
| - if (candidate.length() < 7) { |
| - return false; |
| - } |
| - if (candidate.substr(0,6) == "mmcblk") { |
| - // mmcblk[0-9]+ case |
| - for (size_t i = 6; i < candidate.length(); i++) { |
| - if (!isdigit(candidate[i])) |
| - return false; |
| - } |
| - } else { |
| - return false; |
| - } |
| + return true; |
| } |
| + const char kMMCName[] = "mmcblk"; |
| + const size_t kMMCNameLen = strlen(kMMCName); |
| + if (candidate.length() < kMMCNameLen + 1) |
| + return false; |
| + if (candidate.compare(0, kMMCNameLen, kMMCName) != 0) |
| + return false; |
| + |
| + // mmcblk[0-9]+ case |
| + for (size_t i = kMMCNameLen; i < candidate.length(); ++i) { |
| + if (!isdigit(candidate[i])) |
| + return false; |
| + } |
| return true; |
| } |
| @@ -854,7 +817,7 @@ void GetSwapInfo(SwapInfo* swap_info) { |
| // Synchronously reading files in /sys/block/zram0 is safe. |
| ThreadRestrictions::ScopedAllowIO allow_io; |
| - base::FilePath zram_path("/sys/block/zram0"); |
| + FilePath zram_path("/sys/block/zram0"); |
| uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size")); |
| if (orig_data_size <= 4096) { |
| // A single page is compressed at startup, and has a high compression |