| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "chromecast/crash/linux/synchronized_minidump_manager.h" | 5 #include "chromecast/crash/linux/synchronized_minidump_manager.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 DCHECK_GE(period_dumps, 0); | 115 DCHECK_GE(period_dumps, 0); |
| 116 | 116 |
| 117 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); | 117 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); |
| 118 RCHECK(ratelimit_params, -1); | 118 RCHECK(ratelimit_params, -1); |
| 119 | 119 |
| 120 ratelimit_params->SetInteger(kLockfileRatelimitPeriodDumpsKey, period_dumps); | 120 ratelimit_params->SetInteger(kLockfileRatelimitPeriodDumpsKey, period_dumps); |
| 121 | 121 |
| 122 return 0; | 122 return 0; |
| 123 } | 123 } |
| 124 | 124 |
| 125 // Increment the number of dumps in the current ratelimit period in deserialized | |
| 126 // |metadata| by |increment|. Returns 0 on success, < 0 on error. | |
| 127 int IncrementCurrentPeriodDumps(base::Value* metadata, int increment) { | |
| 128 DCHECK_GE(increment, 0); | |
| 129 int last_dumps = GetRatelimitPeriodDumps(metadata); | |
| 130 RCHECK(last_dumps >= 0, -1); | |
| 131 | |
| 132 return SetRatelimitPeriodDumps(metadata, last_dumps + increment); | |
| 133 } | |
| 134 | |
| 135 // Returns true if |metadata| contains valid metadata, false otherwise. | 125 // Returns true if |metadata| contains valid metadata, false otherwise. |
| 136 bool ValidateMetadata(base::Value* metadata) { | 126 bool ValidateMetadata(base::Value* metadata) { |
| 137 RCHECK(metadata, false); | 127 RCHECK(metadata, false); |
| 138 | 128 |
| 139 // Validate ratelimit params | 129 // Validate ratelimit params |
| 140 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); | 130 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); |
| 141 | 131 |
| 142 return ratelimit_params && | 132 return ratelimit_params && |
| 143 ratelimit_params->size() == kLockfileNumRatelimitParams && | 133 ratelimit_params->size() == kLockfileNumRatelimitParams && |
| 144 GetRatelimitPeriodStart(metadata) >= 0 && | 134 GetRatelimitPeriodStart(metadata) >= 0 && |
| 145 GetRatelimitPeriodDumps(metadata) >= 0; | 135 GetRatelimitPeriodDumps(metadata) >= 0; |
| 146 } | 136 } |
| 147 | 137 |
| 148 } // namespace | 138 } // namespace |
| 149 | 139 |
| 150 const int SynchronizedMinidumpManager::kMaxLockfileDumps = 5; | |
| 151 | |
| 152 // One day | 140 // One day |
| 153 const int SynchronizedMinidumpManager::kRatelimitPeriodSeconds = 24 * 3600; | 141 const int SynchronizedMinidumpManager::kRatelimitPeriodSeconds = 24 * 3600; |
| 154 const int SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps = 100; | 142 const int SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps = 100; |
| 155 | 143 |
| 156 SynchronizedMinidumpManager::SynchronizedMinidumpManager() | 144 SynchronizedMinidumpManager::SynchronizedMinidumpManager() |
| 157 : non_blocking_(false), | 145 : non_blocking_(false), |
| 158 dump_path_(GetHomePathASCII(kMinidumpsDir)), | 146 dump_path_(GetHomePathASCII(kMinidumpsDir)), |
| 159 lockfile_path_(dump_path_.Append(kLockfileName).value()), | 147 lockfile_path_(dump_path_.Append(kLockfileName).value()), |
| 160 metadata_path_(dump_path_.Append(kMetadataName).value()), | 148 metadata_path_(dump_path_.Append(kMetadataName).value()), |
| 161 lockfile_fd_(-1) { | 149 lockfile_fd_(-1) { |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 int SynchronizedMinidumpManager::AddEntryToLockFile(const DumpInfo& dump_info) { | 319 int SynchronizedMinidumpManager::AddEntryToLockFile(const DumpInfo& dump_info) { |
| 332 DCHECK_LE(0, lockfile_fd_); | 320 DCHECK_LE(0, lockfile_fd_); |
| 333 DCHECK(dumps_); | 321 DCHECK(dumps_); |
| 334 | 322 |
| 335 // Make sure dump_info is valid. | 323 // Make sure dump_info is valid. |
| 336 if (!dump_info.valid()) { | 324 if (!dump_info.valid()) { |
| 337 LOG(ERROR) << "Entry to be added is invalid"; | 325 LOG(ERROR) << "Entry to be added is invalid"; |
| 338 return -1; | 326 return -1; |
| 339 } | 327 } |
| 340 | 328 |
| 341 if (!CanWriteDumps(1)) { | |
| 342 LOG(ERROR) << "Can't Add Dump: Ratelimited"; | |
| 343 return -1; | |
| 344 } | |
| 345 | |
| 346 IncrementCurrentPeriodDumps(metadata_.get(), 1); | |
| 347 dumps_->Append(dump_info.GetAsValue()); | 329 dumps_->Append(dump_info.GetAsValue()); |
| 348 | 330 |
| 349 return 0; | 331 return 0; |
| 350 } | 332 } |
| 351 | 333 |
| 352 int SynchronizedMinidumpManager::RemoveEntryFromLockFile(int index) { | 334 int SynchronizedMinidumpManager::RemoveEntryFromLockFile(int index) { |
| 353 return dumps_->Remove(static_cast<size_t>(index), nullptr) ? 0 : -1; | 335 return dumps_->Remove(static_cast<size_t>(index), nullptr) ? 0 : -1; |
| 354 } | 336 } |
| 355 | 337 |
| 356 void SynchronizedMinidumpManager::ReleaseLockFile() { | 338 void SynchronizedMinidumpManager::ReleaseLockFile() { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 384 int SynchronizedMinidumpManager::SetCurrentDumps( | 366 int SynchronizedMinidumpManager::SetCurrentDumps( |
| 385 const ScopedVector<DumpInfo>& dumps) { | 367 const ScopedVector<DumpInfo>& dumps) { |
| 386 dumps_->Clear(); | 368 dumps_->Clear(); |
| 387 | 369 |
| 388 for (DumpInfo* dump : dumps) | 370 for (DumpInfo* dump : dumps) |
| 389 dumps_->Append(dump->GetAsValue()); | 371 dumps_->Append(dump->GetAsValue()); |
| 390 | 372 |
| 391 return 0; | 373 return 0; |
| 392 } | 374 } |
| 393 | 375 |
| 394 bool SynchronizedMinidumpManager::CanWriteDumps(int num_dumps) { | 376 int SynchronizedMinidumpManager::IncrementRatelimitPeriodDumps() { |
| 395 const auto dumps(GetDumps()); | 377 DCHECK(metadata_); |
| 378 int last_dumps = GetRatelimitPeriodDumps(metadata_.get()); |
| 379 RCHECK(last_dumps >= 0, -1); |
| 396 | 380 |
| 397 // If no more dumps can be written, return false. | 381 return SetRatelimitPeriodDumps(metadata_.get(), last_dumps + 1); |
| 398 if (static_cast<int>(dumps.size()) + num_dumps > kMaxLockfileDumps) | 382 } |
| 399 return false; | |
| 400 | 383 |
| 401 // If too many dumps have been written recently, return false. | 384 bool SynchronizedMinidumpManager::CanUploadDump() { |
| 402 time_t cur_time = time(nullptr); | 385 time_t cur_time = time(nullptr); |
| 403 time_t period_start = GetRatelimitPeriodStart(metadata_.get()); | 386 time_t period_start = GetRatelimitPeriodStart(metadata_.get()); |
| 404 int period_dumps_count = GetRatelimitPeriodDumps(metadata_.get()); | 387 int period_dumps_count = GetRatelimitPeriodDumps(metadata_.get()); |
| 405 | 388 |
| 406 // If we're in invalid state, or we passed the period, reset the ratelimit. | 389 // If we're in invalid state, or we passed the period, reset the ratelimit. |
| 407 // When the device reboots, |cur_time| may be incorrectly reported to be a | 390 // When the device reboots, |cur_time| may be incorrectly reported to be a |
| 408 // very small number for a short period of time. So only consider | 391 // very small number for a short period of time. So only consider |
| 409 // |period_start| invalid when |cur_time| is less if |cur_time| is not very | 392 // |period_start| invalid when |cur_time| is less if |cur_time| is not very |
| 410 // close to 0. | 393 // close to 0. |
| 411 if (period_dumps_count < 0 || | 394 if (period_dumps_count < 0 || |
| 412 (cur_time < period_start && cur_time > kRatelimitPeriodSeconds) || | 395 (cur_time < period_start && cur_time > kRatelimitPeriodSeconds) || |
| 413 difftime(cur_time, period_start) >= kRatelimitPeriodSeconds) { | 396 difftime(cur_time, period_start) >= kRatelimitPeriodSeconds) { |
| 414 period_start = cur_time; | 397 period_start = cur_time; |
| 415 period_dumps_count = 0; | 398 period_dumps_count = 0; |
| 416 SetRatelimitPeriodStart(metadata_.get(), period_start); | 399 SetRatelimitPeriodStart(metadata_.get(), period_start); |
| 417 SetRatelimitPeriodDumps(metadata_.get(), period_dumps_count); | 400 SetRatelimitPeriodDumps(metadata_.get(), period_dumps_count); |
| 418 } | 401 } |
| 419 | 402 |
| 420 return period_dumps_count + num_dumps <= kRatelimitPeriodMaxDumps; | 403 return period_dumps_count < kRatelimitPeriodMaxDumps; |
| 421 } | 404 } |
| 422 | 405 |
| 423 } // namespace chromecast | 406 } // namespace chromecast |
| OLD | NEW |