Chromium Code Reviews| Index: base/debug/crash_logging.cc |
| diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc |
| index 1e20677ec4a32f94408811f773e17f75eaf018ce..cbc17c8380dd6867fa8645535ecc94b5a930f582 100644 |
| --- a/base/debug/crash_logging.cc |
| +++ b/base/debug/crash_logging.cc |
| @@ -4,6 +4,8 @@ |
| #include "base/debug/crash_logging.h" |
| +#include <map> |
| + |
| #include "base/debug/stack_trace.h" |
| #include "base/logging.h" |
| #include "base/string_util.h" |
| @@ -12,18 +14,62 @@ |
| namespace base { |
| namespace debug { |
| -static SetCrashKeyValueFuncT g_set_key_func_ = NULL; |
| -static ClearCrashKeyValueFuncT g_clear_key_func_ = NULL; |
| +namespace { |
| + |
| +std::map<base::StringPiece, CrashKey>* g_crash_keys_ = NULL; |
| + |
| +const char kChunkFormatString[] = "%s-%zu"; |
| + |
| +SetCrashKeyValueFuncT g_set_key_func_ = NULL; |
| +ClearCrashKeyValueFuncT g_clear_key_func_ = NULL; |
| + |
| +} // namespace |
| void SetCrashKeyValue(const base::StringPiece& key, |
| const base::StringPiece& value) { |
| - if (g_set_key_func_) |
| + if (!g_set_key_func_) |
| + return; |
| + |
| + const CrashKey* crash_key = LookupCrashKey(key); |
| + |
| + // TODO(rsesek): Do this: |
| + //DCHECK(crash_key) << "All crash keys must be registered before use " |
| + // << "(key = " << key << ")"; |
| + |
| + // Handle the un-chunked case. |
| + if (!crash_key || crash_key->num_chunks == 1) { |
| g_set_key_func_(key, value); |
| + return; |
| + } |
| + |
| + // Unset the unused chunks. |
| + std::vector<std::string> chunks = ChunkCrashKeyValue(*crash_key, value); |
| + for (size_t i = chunks.size(); i < crash_key->num_chunks; ++i) { |
| + g_clear_key_func_(base::StringPrintf(kChunkFormatString, key.data(), i+1)); |
| + } |
| + |
| + // Set the chunked keys. |
| + for (size_t i = 0; i < chunks.size(); ++i) { |
| + g_set_key_func_(base::StringPrintf(kChunkFormatString, key.data(), i+1), |
| + chunks[i]); |
| + } |
| } |
| void ClearCrashKey(const base::StringPiece& key) { |
| - if (g_clear_key_func_) |
| + if (!g_clear_key_func_) |
| + return; |
| + |
| + const CrashKey* crash_key = LookupCrashKey(key); |
| + |
| + // Handle the un-chunked case. |
| + if (!crash_key || crash_key->num_chunks == 1) { |
| g_clear_key_func_(key); |
| + return; |
| + } |
| + |
| + for (size_t i = 0; i < crash_key->num_chunks; ++i) { |
| + g_clear_key_func_(base::StringPrintf(kChunkFormatString, key.data(), i+1)); |
| + } |
| } |
| void SetCrashKeyToStackTrace(const base::StringPiece& key, |
| @@ -70,6 +116,33 @@ ScopedCrashKey::~ScopedCrashKey() { |
| ClearCrashKey(key_); |
| } |
| +size_t InitCrashKeys(const CrashKey* const keys, size_t count) { |
| + DCHECK(!g_crash_keys_) << "Crash logging may only be initialized once"; |
| + if (!keys) { |
| + delete g_crash_keys_; |
| + g_crash_keys_ = NULL; |
| + return 0; |
| + } |
| + |
| + g_crash_keys_ = new std::map<base::StringPiece, CrashKey>; |
| + |
| + size_t total_keys = 0; |
| + for (size_t i = 0; i < count; ++i) { |
| + g_crash_keys_->insert(std::make_pair(keys[i].key_name, keys[i])); |
| + total_keys += keys[i].num_chunks; |
| + } |
|
Scott Hess - ex-Googler
2013/01/09 23:40:19
Doing DCHECK_EQ(count, g_crash_keys_->size()) woul
Robert Sesek
2013/01/10 16:52:50
Good idea. Done.
|
| + |
| + return total_keys; |
| +} |
| + |
| +const CrashKey* LookupCrashKey(const base::StringPiece& key) { |
| + std::map<base::StringPiece, CrashKey>::const_iterator it = |
| + g_crash_keys_->find(key.as_string()); |
| + if (it == g_crash_keys_->end()) |
| + return NULL; |
| + return &(it->second); |
| +} |
| + |
| void SetCrashKeyReportingFunctions( |
| SetCrashKeyValueFuncT set_key_func, |
| ClearCrashKeyValueFuncT clear_key_func) { |
| @@ -77,5 +150,26 @@ void SetCrashKeyReportingFunctions( |
| g_clear_key_func_ = clear_key_func; |
| } |
| +std::vector<std::string> ChunkCrashKeyValue(const CrashKey& crash_key, |
| + const base::StringPiece& value) { |
| + std::string value_string = value.as_string(); |
| + std::vector<std::string> chunks; |
| + for (size_t i = 0, offset = 0; |
| + i < crash_key.num_chunks && offset < value_string.length(); |
| + ++i) { |
| + std::string chunk = value_string.substr(offset, crash_key.max_length); |
| + chunks.push_back(chunk); |
| + offset += chunk.length(); |
| + } |
| + return chunks; |
| +} |
| + |
| +void ResetCrashLoggingForTesting() { |
| + delete g_crash_keys_; |
| + g_crash_keys_ = NULL; |
| + g_set_key_func_ = NULL; |
| + g_clear_key_func_ = NULL; |
| +} |
| + |
| } // namespace debug |
| } // namespace base |