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