Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: storage/browser/quota/quota_manager.cc

Issue 1403673002: Add Quota.TimeSinceOriginEvicted UMA histogram. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « storage/browser/quota/quota_manager.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "storage/browser/quota/quota_manager.h" 5 #include "storage/browser/quota/quota_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 // Preserve kMinimumPreserveForSystem disk space for system book-keeping 67 // Preserve kMinimumPreserveForSystem disk space for system book-keeping
68 // when returning the quota to unlimited apps/extensions. 68 // when returning the quota to unlimited apps/extensions.
69 // TODO(kinuko): This should be like 10% of the actual disk space. 69 // TODO(kinuko): This should be like 10% of the actual disk space.
70 // For now we simply use a constant as getting the disk size needs 70 // For now we simply use a constant as getting the disk size needs
71 // platform-dependent code. (http://crbug.com/178976) 71 // platform-dependent code. (http://crbug.com/178976)
72 int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes; 72 int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes;
73 73
74 const int QuotaManager::kEvictionIntervalInMilliSeconds = 74 const int QuotaManager::kEvictionIntervalInMilliSeconds =
75 30 * kMinutesInMilliSeconds; 75 30 * kMinutesInMilliSeconds;
76 76
77 const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] =
78 "Quota.TimeBetweenRepeatedOriginEvictions";
79
77 // Heuristics: assuming average cloud server allows a few Gigs storage 80 // Heuristics: assuming average cloud server allows a few Gigs storage
78 // on the server side and the storage needs to be shared for user data 81 // on the server side and the storage needs to be shared for user data
79 // and by multiple apps. 82 // and by multiple apps.
80 int64 QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes; 83 int64 QuotaManager::kSyncableStorageDefaultHostQuota = 500 * kMBytes;
81 84
82 namespace { 85 namespace {
83 86
84 void CountOriginType(const std::set<GURL>& origins, 87 void CountOriginType(const std::set<GURL>& origins,
85 SpecialStoragePolicy* policy, 88 SpecialStoragePolicy* policy,
86 size_t* protected_origins, 89 size_t* protected_origins,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 SpecialStoragePolicy* policy, 149 SpecialStoragePolicy* policy,
147 GURL* url, 150 GURL* url,
148 QuotaDatabase* database) { 151 QuotaDatabase* database) {
149 DCHECK(database); 152 DCHECK(database);
150 database->GetLRUOrigin(type, *exceptions, policy, url); 153 database->GetLRUOrigin(type, *exceptions, policy, url);
151 return true; 154 return true;
152 } 155 }
153 156
154 bool DeleteOriginInfoOnDBThread(const GURL& origin, 157 bool DeleteOriginInfoOnDBThread(const GURL& origin,
155 StorageType type, 158 StorageType type,
159 bool is_eviction,
156 QuotaDatabase* database) { 160 QuotaDatabase* database) {
157 DCHECK(database); 161 DCHECK(database);
158 return database->DeleteOriginInfo(origin, type); 162 if (!database->DeleteOriginInfo(origin, type))
163 return false;
164
165 // If the deletion is not due to an eviction, delete the entry in the eviction
166 // table as well due to privacy concerns.
167 if (!is_eviction)
168 return database->DeleteOriginLastEvictionTime(origin, type);
169
170 base::Time last_eviction_time;
171 if (!database->GetOriginLastEvictionTime(origin, type, &last_eviction_time))
172 return false;
173
174 base::Time now = base::Time::Now();
175 if (last_eviction_time != base::Time()) {
176 UMA_HISTOGRAM_LONG_TIMES(
177 QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram,
178 now - last_eviction_time);
179 }
180
181 return database->SetOriginLastEvictionTime(origin, type, now);
159 } 182 }
160 183
161 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins, 184 bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins,
162 QuotaDatabase* database) { 185 QuotaDatabase* database) {
163 DCHECK(database); 186 DCHECK(database);
164 if (database->IsOriginDatabaseBootstrapped()) 187 if (database->IsOriginDatabaseBootstrapped())
165 return true; 188 return true;
166 189
167 // Register existing origins with 0 last time access. 190 // Register existing origins with 0 last time access.
168 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) { 191 if (database->RegisterInitialOriginInfo(*origins, kStorageTypeTemporary)) {
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 567
545 DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask); 568 DISALLOW_COPY_AND_ASSIGN(GetUsageInfoTask);
546 }; 569 };
547 570
548 class QuotaManager::OriginDataDeleter : public QuotaTask { 571 class QuotaManager::OriginDataDeleter : public QuotaTask {
549 public: 572 public:
550 OriginDataDeleter(QuotaManager* manager, 573 OriginDataDeleter(QuotaManager* manager,
551 const GURL& origin, 574 const GURL& origin,
552 StorageType type, 575 StorageType type,
553 int quota_client_mask, 576 int quota_client_mask,
577 bool is_eviction,
554 const StatusCallback& callback) 578 const StatusCallback& callback)
555 : QuotaTask(manager), 579 : QuotaTask(manager),
556 origin_(origin), 580 origin_(origin),
557 type_(type), 581 type_(type),
558 quota_client_mask_(quota_client_mask), 582 quota_client_mask_(quota_client_mask),
559 error_count_(0), 583 error_count_(0),
560 remaining_clients_(-1), 584 remaining_clients_(-1),
561 skipped_clients_(0), 585 skipped_clients_(0),
586 is_eviction_(is_eviction),
562 callback_(callback), 587 callback_(callback),
563 weak_factory_(this) {} 588 weak_factory_(this) {}
564 589
565 protected: 590 protected:
566 void Run() override { 591 void Run() override {
567 error_count_ = 0; 592 error_count_ = 0;
568 remaining_clients_ = manager()->clients_.size(); 593 remaining_clients_ = manager()->clients_.size();
569 for (QuotaClientList::iterator iter = manager()->clients_.begin(); 594 for (QuotaClientList::iterator iter = manager()->clients_.begin();
570 iter != manager()->clients_.end(); ++iter) { 595 iter != manager()->clients_.end(); ++iter) {
571 if (quota_client_mask_ & (*iter)->id()) { 596 if (quota_client_mask_ & (*iter)->id()) {
572 (*iter)->DeleteOriginData( 597 (*iter)->DeleteOriginData(
573 origin_, type_, 598 origin_, type_,
574 base::Bind(&OriginDataDeleter::DidDeleteOriginData, 599 base::Bind(&OriginDataDeleter::DidDeleteOriginData,
575 weak_factory_.GetWeakPtr())); 600 weak_factory_.GetWeakPtr()));
576 } else { 601 } else {
577 ++skipped_clients_; 602 ++skipped_clients_;
578 if (--remaining_clients_ == 0) 603 if (--remaining_clients_ == 0)
579 CallCompleted(); 604 CallCompleted();
580 } 605 }
581 } 606 }
582 } 607 }
583 608
584 void Completed() override { 609 void Completed() override {
585 if (error_count_ == 0) { 610 if (error_count_ == 0) {
586 // crbug.com/349708 611 // crbug.com/349708
587 TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Ok"); 612 TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Ok");
588 613
589 // Only remove the entire origin if we didn't skip any client types. 614 // Only remove the entire origin if we didn't skip any client types.
590 if (skipped_clients_ == 0) 615 if (skipped_clients_ == 0)
591 manager()->DeleteOriginFromDatabase(origin_, type_); 616 manager()->DeleteOriginFromDatabase(origin_, type_, is_eviction_);
592 callback_.Run(kQuotaStatusOk); 617 callback_.Run(kQuotaStatusOk);
593 } else { 618 } else {
594 // crbug.com/349708 619 // crbug.com/349708
595 TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Error"); 620 TRACE_EVENT0("io", "QuotaManager::OriginDataDeleter::Completed Error");
596 621
597 callback_.Run(kQuotaErrorInvalidModification); 622 callback_.Run(kQuotaErrorInvalidModification);
598 } 623 }
599 DeleteSoon(); 624 DeleteSoon();
600 } 625 }
601 626
(...skipping 16 matching lines...) Expand all
618 QuotaManager* manager() const { 643 QuotaManager* manager() const {
619 return static_cast<QuotaManager*>(observer()); 644 return static_cast<QuotaManager*>(observer());
620 } 645 }
621 646
622 GURL origin_; 647 GURL origin_;
623 StorageType type_; 648 StorageType type_;
624 int quota_client_mask_; 649 int quota_client_mask_;
625 int error_count_; 650 int error_count_;
626 int remaining_clients_; 651 int remaining_clients_;
627 int skipped_clients_; 652 int skipped_clients_;
653 bool is_eviction_;
628 StatusCallback callback_; 654 StatusCallback callback_;
629 655
630 base::WeakPtrFactory<OriginDataDeleter> weak_factory_; 656 base::WeakPtrFactory<OriginDataDeleter> weak_factory_;
631 DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter); 657 DISALLOW_COPY_AND_ASSIGN(OriginDataDeleter);
632 }; 658 };
633 659
634 class QuotaManager::HostDataDeleter : public QuotaTask { 660 class QuotaManager::HostDataDeleter : public QuotaTask {
635 public: 661 public:
636 HostDataDeleter(QuotaManager* manager, 662 HostDataDeleter(QuotaManager* manager,
637 const std::string& host, 663 const std::string& host,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 else 719 else
694 CallCompleted(); 720 CallCompleted();
695 } 721 }
696 } 722 }
697 723
698 void ScheduleOriginsDeletion() { 724 void ScheduleOriginsDeletion() {
699 remaining_deleters_ = origins_.size(); 725 remaining_deleters_ = origins_.size();
700 for (std::set<GURL>::const_iterator p = origins_.begin(); 726 for (std::set<GURL>::const_iterator p = origins_.begin();
701 p != origins_.end(); 727 p != origins_.end();
702 ++p) { 728 ++p) {
703 OriginDataDeleter* deleter = 729 OriginDataDeleter* deleter = new OriginDataDeleter(
704 new OriginDataDeleter( 730 manager(), *p, type_, quota_client_mask_, false,
705 manager(), *p, type_, quota_client_mask_, 731 base::Bind(&HostDataDeleter::DidDeleteOriginData,
706 base::Bind(&HostDataDeleter::DidDeleteOriginData, 732 weak_factory_.GetWeakPtr()));
707 weak_factory_.GetWeakPtr()));
708 deleter->Start(); 733 deleter->Start();
709 } 734 }
710 } 735 }
711 736
712 void DidDeleteOriginData(QuotaStatusCode status) { 737 void DidDeleteOriginData(QuotaStatusCode status) {
713 DCHECK_GT(remaining_deleters_, 0); 738 DCHECK_GT(remaining_deleters_, 0);
714 739
715 if (status != kQuotaStatusOk) 740 if (status != kQuotaStatusOk)
716 ++error_count_; 741 ++error_count_;
717 742
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 LazyInitialize(); 977 LazyInitialize();
953 DCHECK(GetUsageTracker(type)); 978 DCHECK(GetUsageTracker(type));
954 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled); 979 GetUsageTracker(type)->SetUsageCacheEnabled(client_id, origin, enabled);
955 } 980 }
956 981
957 void QuotaManager::SetTemporaryStorageEvictionPolicy( 982 void QuotaManager::SetTemporaryStorageEvictionPolicy(
958 scoped_ptr<QuotaEvictionPolicy> policy) { 983 scoped_ptr<QuotaEvictionPolicy> policy) {
959 temporary_storage_eviction_policy_ = policy.Pass(); 984 temporary_storage_eviction_policy_ = policy.Pass();
960 } 985 }
961 986
962 void QuotaManager::DeleteOriginData( 987 void QuotaManager::DeleteOriginData(const GURL& origin,
963 const GURL& origin, StorageType type, int quota_client_mask, 988 StorageType type,
964 const StatusCallback& callback) { 989 int quota_client_mask,
965 LazyInitialize(); 990 const StatusCallback& callback) {
966 991 DeleteOriginDataInternal(origin, type, quota_client_mask, false, callback);
967 if (origin.is_empty() || clients_.empty()) {
968 callback.Run(kQuotaStatusOk);
969 return;
970 }
971
972 DCHECK(origin == origin.GetOrigin());
973 OriginDataDeleter* deleter =
974 new OriginDataDeleter(this, origin, type, quota_client_mask, callback);
975 deleter->Start();
976 } 992 }
977 993
978 void QuotaManager::DeleteHostData(const std::string& host, 994 void QuotaManager::DeleteHostData(const std::string& host,
979 StorageType type, 995 StorageType type,
980 int quota_client_mask, 996 int quota_client_mask,
981 const StatusCallback& callback) { 997 const StatusCallback& callback) {
982 LazyInitialize(); 998 LazyInitialize();
983 999
984 if (host.empty() || clients_.empty()) { 1000 if (host.empty() || clients_.empty()) {
985 callback.Run(kQuotaStatusOk); 1001 callback.Run(kQuotaStatusOk);
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1383 void QuotaManager::StartEviction() { 1399 void QuotaManager::StartEviction() {
1384 DCHECK(!temporary_storage_evictor_.get()); 1400 DCHECK(!temporary_storage_evictor_.get());
1385 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor( 1401 temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
1386 this, kEvictionIntervalInMilliSeconds)); 1402 this, kEvictionIntervalInMilliSeconds));
1387 if (desired_available_space_ >= 0) 1403 if (desired_available_space_ >= 0)
1388 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction( 1404 temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
1389 desired_available_space_); 1405 desired_available_space_);
1390 temporary_storage_evictor_->Start(); 1406 temporary_storage_evictor_->Start();
1391 } 1407 }
1392 1408
1393 void QuotaManager::DeleteOriginFromDatabase( 1409 void QuotaManager::DeleteOriginFromDatabase(const GURL& origin,
1394 const GURL& origin, StorageType type) { 1410 StorageType type,
1411 bool is_eviction) {
1395 LazyInitialize(); 1412 LazyInitialize();
1396 if (db_disabled_) 1413 if (db_disabled_)
1397 return; 1414 return;
1398 1415
1399 PostTaskAndReplyWithResultForDBThread( 1416 PostTaskAndReplyWithResultForDBThread(
1400 FROM_HERE, 1417 FROM_HERE,
1401 base::Bind(&DeleteOriginInfoOnDBThread, origin, type), 1418 base::Bind(&DeleteOriginInfoOnDBThread, origin, type, is_eviction),
1402 base::Bind(&QuotaManager::DidDatabaseWork, 1419 base::Bind(&QuotaManager::DidDatabaseWork, weak_factory_.GetWeakPtr()));
1403 weak_factory_.GetWeakPtr()));
1404 } 1420 }
1405 1421
1406 void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) { 1422 void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) {
1407 DCHECK(io_thread_->BelongsToCurrentThread()); 1423 DCHECK(io_thread_->BelongsToCurrentThread());
1408 1424
1409 // We only try evict origins that are not in use, so basically 1425 // We only try evict origins that are not in use, so basically
1410 // deletion attempt for eviction should not fail. Let's record 1426 // deletion attempt for eviction should not fail. Let's record
1411 // the origin if we get error and exclude it from future eviction 1427 // the origin if we get error and exclude it from future eviction
1412 // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted). 1428 // if the error happens consistently (> kThresholdOfErrorsToBeBlacklisted).
1413 if (status != kQuotaStatusOk) 1429 if (status != kQuotaStatusOk)
1414 origins_in_error_[eviction_context_.evicted_origin]++; 1430 origins_in_error_[eviction_context_.evicted_origin]++;
1415 1431
1416 eviction_context_.evict_origin_data_callback.Run(status); 1432 eviction_context_.evict_origin_data_callback.Run(status);
1417 eviction_context_.evict_origin_data_callback.Reset(); 1433 eviction_context_.evict_origin_data_callback.Reset();
1418 } 1434 }
1419 1435
1436 void QuotaManager::DeleteOriginDataInternal(const GURL& origin,
1437 StorageType type,
1438 int quota_client_mask,
1439 bool is_eviction,
1440 const StatusCallback& callback) {
1441 LazyInitialize();
1442
1443 if (origin.is_empty() || clients_.empty()) {
1444 callback.Run(kQuotaStatusOk);
1445 return;
1446 }
1447
1448 DCHECK(origin == origin.GetOrigin());
1449 OriginDataDeleter* deleter = new OriginDataDeleter(
1450 this, origin, type, quota_client_mask, is_eviction, callback);
1451 deleter->Start();
1452 }
1453
1420 void QuotaManager::ReportHistogram() { 1454 void QuotaManager::ReportHistogram() {
1421 GetGlobalUsage(kStorageTypeTemporary, 1455 GetGlobalUsage(kStorageTypeTemporary,
1422 base::Bind( 1456 base::Bind(
1423 &QuotaManager::DidGetTemporaryGlobalUsageForHistogram, 1457 &QuotaManager::DidGetTemporaryGlobalUsageForHistogram,
1424 weak_factory_.GetWeakPtr())); 1458 weak_factory_.GetWeakPtr()));
1425 GetGlobalUsage(kStorageTypePersistent, 1459 GetGlobalUsage(kStorageTypePersistent,
1426 base::Bind( 1460 base::Bind(
1427 &QuotaManager::DidGetPersistentGlobalUsageForHistogram, 1461 &QuotaManager::DidGetPersistentGlobalUsageForHistogram,
1428 weak_factory_.GetWeakPtr())); 1462 weak_factory_.GetWeakPtr()));
1429 } 1463 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 void QuotaManager::EvictOriginData(const GURL& origin, 1548 void QuotaManager::EvictOriginData(const GURL& origin,
1515 StorageType type, 1549 StorageType type,
1516 const EvictOriginDataCallback& callback) { 1550 const EvictOriginDataCallback& callback) {
1517 DCHECK(io_thread_->BelongsToCurrentThread()); 1551 DCHECK(io_thread_->BelongsToCurrentThread());
1518 DCHECK_EQ(type, kStorageTypeTemporary); 1552 DCHECK_EQ(type, kStorageTypeTemporary);
1519 1553
1520 eviction_context_.evicted_origin = origin; 1554 eviction_context_.evicted_origin = origin;
1521 eviction_context_.evicted_type = type; 1555 eviction_context_.evicted_type = type;
1522 eviction_context_.evict_origin_data_callback = callback; 1556 eviction_context_.evict_origin_data_callback = callback;
1523 1557
1524 DeleteOriginData(origin, type, QuotaClient::kAllClientsMask, 1558 DeleteOriginDataInternal(origin, type, QuotaClient::kAllClientsMask, true,
1525 base::Bind(&QuotaManager::DidOriginDataEvicted, 1559 base::Bind(&QuotaManager::DidOriginDataEvicted,
1526 weak_factory_.GetWeakPtr())); 1560 weak_factory_.GetWeakPtr()));
1527 } 1561 }
1528 1562
1529 void QuotaManager::GetUsageAndQuotaForEviction( 1563 void QuotaManager::GetUsageAndQuotaForEviction(
1530 const UsageAndQuotaCallback& callback) { 1564 const UsageAndQuotaCallback& callback) {
1531 // crbug.com/349708 1565 // crbug.com/349708
1532 TRACE_EVENT0("io", "QuotaManager::GetUsageAndQuotaForEviction"); 1566 TRACE_EVENT0("io", "QuotaManager::GetUsageAndQuotaForEviction");
1533 1567
1534 DCHECK(io_thread_->BelongsToCurrentThread()); 1568 DCHECK(io_thread_->BelongsToCurrentThread());
1535 LazyInitialize(); 1569 LazyInitialize();
1536 1570
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 // |database_|, therefore we can be sure that database_ is alive when this 1733 // |database_|, therefore we can be sure that database_ is alive when this
1700 // task runs. 1734 // task runs.
1701 base::PostTaskAndReplyWithResult( 1735 base::PostTaskAndReplyWithResult(
1702 db_thread_.get(), 1736 db_thread_.get(),
1703 from_here, 1737 from_here,
1704 base::Bind(task, base::Unretained(database_.get())), 1738 base::Bind(task, base::Unretained(database_.get())),
1705 reply); 1739 reply);
1706 } 1740 }
1707 1741
1708 } // namespace storage 1742 } // namespace storage
OLDNEW
« no previous file with comments | « storage/browser/quota/quota_manager.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698