Chromium Code Reviews| Index: client/prune_crash_reports.cc |
| diff --git a/client/prune_crash_reports.cc b/client/prune_crash_reports.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..dd6a194f4699dd8126558022888aae015eddc616 |
| --- /dev/null |
| +++ b/client/prune_crash_reports.cc |
| @@ -0,0 +1,127 @@ |
| +// Copyright 2015 The Crashpad Authors. All rights reserved. |
| +// |
| +// Licensed under the Apache License, Version 2.0 (the "License"); |
| +// you may not use this file except in compliance with the License. |
| +// You may obtain a copy of the License at |
| +// |
| +// http://www.apache.org/licenses/LICENSE-2.0 |
| +// |
| +// Unless required by applicable law or agreed to in writing, software |
| +// distributed under the License is distributed on an "AS IS" BASIS, |
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| +// See the License for the specific language governing permissions and |
| +// limitations under the License. |
| + |
| +#include "client/prune_crash_reports.h" |
| + |
| +#include <sys/stat.h> |
| + |
| +#include <algorithm> |
| +#include <vector> |
| + |
| +#include "base/logging.h" |
| + |
| +namespace crashpad { |
| + |
| +void PruneCrashReportDatabase(CrashReportDatabase* database, |
| + PruneCondition* condition) { |
| + std::vector<CrashReportDatabase::Report> all_reports; |
| + CrashReportDatabase::OperationStatus status; |
| + |
| + status = database->GetPendingReports(&all_reports); |
| + if (status != CrashReportDatabase::kNoError) { |
| + LOG(ERROR) << "PruneCrashReportDatabase: Failed to get pending reports"; |
| + return; |
| + } |
| + |
| + std::vector<CrashReportDatabase::Report> completed_reports; |
| + status = database->GetCompletedReports(&completed_reports); |
| + if (status != CrashReportDatabase::kNoError) { |
| + LOG(ERROR) << "PruneCrashReportDatabase: Failed to get completed reports"; |
| + return; |
| + } |
| + all_reports.insert(all_reports.end(), completed_reports.begin(), |
| + completed_reports.end()); |
| + |
| + std::sort(all_reports.begin(), all_reports.end(), |
| + [](const CrashReportDatabase::Report& lhs, |
| + const CrashReportDatabase::Report& rhs) { |
| + return lhs.creation_time > rhs.creation_time; |
| + }); |
| + |
| + for (const auto& report : all_reports) { |
| + if (condition->ShouldPruneReport(report)) { |
| + status = database->DeleteReport(report.uuid); |
| + if (status != CrashReportDatabase::kNoError) { |
| + LOG(ERROR) << "Database Pruning: Failed to remove report " |
| + << report.uuid.ToString(); |
| + } |
| + } |
| + } |
| +} |
|
Mark Mentovai
2015/10/07 20:58:23
Lose a TODO, gain a TODO. Can you leave behind a b
Robert Sesek
2015/10/07 21:01:34
Done.
|
| + |
| +// static |
| +scoped_ptr<PruneCondition> PruneCondition::GetDefault() { |
| + // DatabaseSizePruneCondition must be the LHS so that it is always evaluated, |
| + // due to the short-circuting behavior of BinaryPruneCondition. |
| + return make_scoped_ptr(new BinaryPruneCondition(BinaryPruneCondition::OR, |
| + new DatabaseSizePruneCondition(1024 * 128), new AgePruneCondition(365))); |
| +} |
| + |
| +static const time_t kSecondsInDay = 60 * 60 * 24; |
| + |
| +AgePruneCondition::AgePruneCondition(int max_age_in_days) |
| + : oldest_report_time_( |
| + ((time(nullptr) - (max_age_in_days * kSecondsInDay)) |
| + / kSecondsInDay) * kSecondsInDay) {} |
| + |
| +AgePruneCondition::~AgePruneCondition() {} |
| + |
| +bool AgePruneCondition::ShouldPruneReport( |
| + const CrashReportDatabase::Report& report) { |
| + return report.creation_time < oldest_report_time_; |
| +} |
| + |
| +DatabaseSizePruneCondition::DatabaseSizePruneCondition(size_t max_size_in_kb) |
| + : max_size_in_kb_(max_size_in_kb), measured_size_in_kb_(0) {} |
| + |
| +DatabaseSizePruneCondition::~DatabaseSizePruneCondition() {} |
| + |
| +bool DatabaseSizePruneCondition::ShouldPruneReport( |
| + const CrashReportDatabase::Report& report) { |
| +#if defined(OS_POSIX) |
| + struct stat statbuf; |
| + if (stat(report.file_path.value().c_str(), &statbuf) == 0) { |
| +#elif defined(OS_WIN) |
| + struct _stati64 statbuf; |
| + if (_wstat64(report.file_path.value().c_str(), &statbuf) == 0) { |
| +#else |
| +#error "Not implemented" |
| +#endif |
| + // Round up fractional KB to the next 1-KB boundary. |
| + measured_size_in_kb_ += |
| + (static_cast<size_t>(statbuf.st_size) + 1023) / 1024; |
|
Mark Mentovai
2015/10/07 20:58:23
size_t may be narrower than decltype(statbuf.st_si
Robert Sesek
2015/10/07 21:01:34
Done.
|
| + } |
| + return measured_size_in_kb_ > max_size_in_kb_; |
| +} |
| + |
| +BinaryPruneCondition::BinaryPruneCondition( |
| + Operator op, PruneCondition* lhs, PruneCondition* rhs) |
| + : op_(op), lhs_(lhs), rhs_(rhs) {} |
| + |
| +BinaryPruneCondition::~BinaryPruneCondition() {} |
| + |
| +bool BinaryPruneCondition::ShouldPruneReport( |
| + const CrashReportDatabase::Report& report) { |
| + switch (op_) { |
| + case AND: |
| + return lhs_->ShouldPruneReport(report) && rhs_->ShouldPruneReport(report); |
| + case OR: |
| + return lhs_->ShouldPruneReport(report) || rhs_->ShouldPruneReport(report); |
| + default: |
| + NOTREACHED(); |
| + return false; |
| + } |
| +} |
| + |
| +} // namespace crashpad |