18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file. 48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/domain_reliability/context.h" 68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm> 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/bind.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/json/json_writer.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/logging.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/metrics/histogram.h" 138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/metrics/sparse_histogram.h" 14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/values.h" 158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "components/domain_reliability/dispatcher.h" 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/domain_reliability/uploader.h" 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "components/domain_reliability/util.h" 188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "net/base/net_errors.h" 198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using base::DictionaryValue; 228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)using base::ListValue; 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using base::Value; 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace domain_reliability { 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)namespace { 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef std::deque<DomainReliabilityBeacon> BeaconDeque; 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef BeaconDeque::iterator BeaconIterator; 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)typedef BeaconDeque::const_iterator BeaconConstIterator; 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class DomainReliabilityContext::ResourceState { 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) public: 358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ResourceState(DomainReliabilityContext* context, 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const DomainReliabilityConfig::Resource* config) 378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : context(context), 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) config(config), 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) successful_requests(0), 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failed_requests(0), 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploading_successful_requests(0), 42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch uploading_failed_requests(0) {} 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~ResourceState() {} 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Serializes the resource state into a Value to be included in an upload. 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // If there is nothing to report (no beacons and all request counters are 0), 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // returns a scoped_ptr to NULL instead so the resource can be omitted. 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> ToValue(base::TimeTicks upload_time) const { 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (successful_requests == 0 && failed_requests == 0) 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return scoped_ptr<base::Value>(); 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DictionaryValue* resource_value = new DictionaryValue(); 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource_value->SetString("name", config->name); 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) resource_value->SetInteger("successful_requests", successful_requests); 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) resource_value->SetInteger("failed_requests", failed_requests); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return scoped_ptr<Value>(resource_value); 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Remembers the current state of the resource data when an upload starts. 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void MarkUpload() { 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(0u, uploading_successful_requests); 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(0u, uploading_failed_requests); 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploading_successful_requests = successful_requests; 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploading_failed_requests = failed_requests; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Uses the state remembered by |MarkUpload| to remove successfully uploaded 69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // data but keep beacons and request counts added after the upload started. 70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void CommitUpload() { 71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch successful_requests -= uploading_successful_requests; 72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch failed_requests -= uploading_failed_requests; 73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch uploading_successful_requests = 0; 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uploading_failed_requests = 0; 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RollbackUpload() { 78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch uploading_successful_requests = 0; 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch uploading_failed_requests = 0; 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DomainReliabilityContext* context; 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const DomainReliabilityConfig::Resource* config; 84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 successful_requests; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 failed_requests; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // State saved during uploads; if an upload succeeds, these are used to 898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // remove uploaded data from the beacon list and request counters. 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32 uploading_successful_requests; 918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint32 uploading_failed_requests; 928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private: 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ResourceState); 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const size_t DomainReliabilityContext::kMaxQueuedBeacons = 150; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DomainReliabilityContext::DomainReliabilityContext( 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockableTime* time, 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DomainReliabilityScheduler::Params& scheduler_params, 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& upload_reporter_string, 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DomainReliabilityDispatcher* dispatcher, 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DomainReliabilityUploader* uploader, 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<const DomainReliabilityConfig> config) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : config_(config.Pass()), 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) time_(time), 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) upload_reporter_string_(upload_reporter_string), 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scheduler_(time, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) config_->collectors.size(), 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scheduler_params, 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&DomainReliabilityContext::ScheduleUpload, 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this))), 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dispatcher_(dispatcher), 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploader_(uploader), 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uploading_beacons_size_(0), 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) weak_factory_(this) { 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InitializeResourceStates(); 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DomainReliabilityContext::~DomainReliabilityContext() {} 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DomainReliabilityContext::OnBeacon(const GURL& url, 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const DomainReliabilityBeacon& beacon) { 1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) size_t index = config_->GetResourceIndexForUrl(url); 1276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (index == DomainReliabilityConfig::kInvalidResourceIndex) 1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK_GT(states_.size(), index); 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool success = (beacon.status == "ok"); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ResourceState* state = states_[index]; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (success) 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ++state->successful_requests; 1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) else 1376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ++state->failed_requests; 1386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) bool reported = false; 1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) bool evicted = false; 1416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (state->config->DecideIfShouldReportRequest(success)) { 1426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) beacons_.push_back(beacon); 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) beacons_.back().resource = state->config->name; 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (beacons_.size() > kMaxQueuedBeacons) { 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) RemoveOldestBeacon(); 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) evicted = true; 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scheduler_.OnBeaconAdded(); 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reported = true; 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.ReportedBeaconError", 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) -beacon.chrome_error); 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(ttuttle): Histogram HTTP response code? 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("DomainReliability.BeaconReported", reported); 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("DomainReliability.OnBeaconDidEvict", evicted); 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DomainReliabilityContext::ClearBeacons() { 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceStateVector::iterator it; 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (it = states_.begin(); it != states_.end(); ++it) { 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceState* state = *it; 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state->successful_requests = 0; 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state->failed_requests = 0; 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state->uploading_successful_requests = 0; 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) state->uploading_failed_requests = 0; 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) beacons_.clear(); 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uploading_beacons_size_ = 0; 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<base::Value> DomainReliabilityContext::GetWebUIData() const { 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* context_value = new base::DictionaryValue(); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) context_value->SetString("domain", config().domain); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) context_value->SetInteger("beacon_count", static_cast<int>(beacons_.size())); 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) context_value->SetInteger("uploading_beacon_count", 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static_cast<int>(uploading_beacons_size_)); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) context_value->Set("scheduler", scheduler_.GetWebUIData()); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<base::Value>(context_value); 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::GetQueuedBeaconsForTesting( 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<DomainReliabilityBeacon>* beacons_out) const { 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) beacons_out->assign(beacons_.begin(), beacons_.end()); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::GetRequestCountsForTesting( 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t resource_index, 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t* successful_requests_out, 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t* failed_requests_out) const { 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(DomainReliabilityConfig::kInvalidResourceIndex, resource_index); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GT(states_.size(), resource_index); 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const ResourceState& state = *states_[resource_index]; 1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *successful_requests_out = state.successful_requests; 1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *failed_requests_out = state.failed_requests; 1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid DomainReliabilityContext::InitializeResourceStates() { 2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ScopedVector<DomainReliabilityConfig::Resource>::const_iterator it; 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (it = config_->resources.begin(); it != config_->resources.end(); ++it) 2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) states_.push_back(new ResourceState(this, *it)); 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DomainReliabilityContext::ScheduleUpload( 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::TimeDelta min_delay, 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::TimeDelta max_delay) { 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dispatcher_->ScheduleTask( 2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind( 2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &DomainReliabilityContext::StartUpload, 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_.GetWeakPtr()), 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) min_delay, 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) max_delay); 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::StartUpload() { 2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MarkUpload(); 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(upload_time_.is_null()); 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch upload_time_ = time_->NowTicks(); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string report_json; 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<const Value> report_value(CreateReport(upload_time_)); 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::JSONWriter::Write(report_value.get(), &report_json); 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) report_value.reset(); 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t collector_index = scheduler_.OnUploadStart(); 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploader_->UploadReport( 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) report_json, 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) config_->collectors[collector_index]->upload_url, 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind( 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &DomainReliabilityContext::OnUploadComplete, 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_.GetWeakPtr())); 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("DomainReliability.UploadFailover", 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) collector_index > 0); 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!last_upload_time_.is_null()) { 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_LONG_TIMES("DomainReliability.UploadInterval", 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) upload_time_ - last_upload_time_); 2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DomainReliabilityContext::OnUploadComplete(bool success) { 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (success) 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CommitUpload(); 2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else 2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RollbackUpload(); 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scheduler_.OnUploadComplete(success); 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("DomainReliability.UploadSuccess", success); 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!upload_time_.is_null()); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UMA_HISTOGRAM_MEDIUM_TIMES("DomainReliability.UploadDuration", 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) time_->NowTicks() - upload_time_); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_upload_time_ = upload_time_; 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) upload_time_ = base::TimeTicks(); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<const Value> DomainReliabilityContext::CreateReport( 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks upload_time) const { 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ListValue> beacons_value(new ListValue()); 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (BeaconConstIterator it = beacons_.begin(); it != beacons_.end(); ++it) 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) beacons_value->Append(it->ToValue(upload_time)); 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ListValue> resources_value(new ListValue()); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) { 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<Value> resource_report = (*it)->ToValue(upload_time); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (resource_report) 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resources_value->Append(resource_report.release()); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DictionaryValue* report_value = new DictionaryValue(); 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!config().version.empty()) 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) report_value->SetString("config_version", config().version); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) report_value->SetString("reporter", upload_reporter_string_); 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) report_value->Set("entries", beacons_value.release()); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!resources_value->empty()) 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) report_value->Set("resources", resources_value.release()); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return scoped_ptr<const Value>(report_value); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::MarkUpload() { 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->MarkUpload(); 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(0u, uploading_beacons_size_); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploading_beacons_size_ = beacons_.size(); 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(0u, uploading_beacons_size_); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::CommitUpload() { 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->CommitUpload(); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BeaconIterator begin = beacons_.begin(); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BeaconIterator end = begin + uploading_beacons_size_; 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) beacons_.erase(begin, end); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(0u, uploading_beacons_size_); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uploading_beacons_size_ = 0; 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::RollbackUpload() { 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*it)->RollbackUpload(); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_NE(0u, uploading_beacons_size_); 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uploading_beacons_size_ = 0; 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DomainReliabilityContext::RemoveOldestBeacon() { 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!beacons_.empty()); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(1) << "Beacon queue for " << config().domain << " full; " 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "removing oldest beacon"; 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) beacons_.pop_front(); 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If that just removed a beacon counted in uploading_beacons_size_, decrement 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // that. 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (uploading_beacons_size_ > 0) 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) --uploading_beacons_size_; 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace domain_reliability 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)