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

Side by Side Diff: src/data_plan.cc

Issue 6250171: cashew: reset local counter on plan transition (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/cashew.git@master
Patch Set: ers review comments Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/data_plan.h ('k') | src/data_plan_unittest.cc » ('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 (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS 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 "src/data_plan.h" 5 #include "src/data_plan.h"
6 6
7 #include <time.h> 7 #include <time.h>
8 8
9 #include <glog/logging.h> 9 #include <glog/logging.h>
10 10
11 #include "src/device.h"
11 #include "src/policy.h" 12 #include "src/policy.h"
13 #include "src/service_manager.h"
12 14
13 namespace cashew { 15 namespace cashew {
14 16
15 // libcros CellularDataPlan property names 17 // libcros CellularDataPlan property names
16 // (what we send to libcros) 18 // (what we send to libcros)
17 static const char *kCellularDataPlanName = "CellularPlanName"; 19 static const char *kCellularDataPlanName = "CellularPlanName";
18 static const char *kCellularDataPlanType = "CellularPlanType"; 20 static const char *kCellularDataPlanType = "CellularPlanType";
19 static const char *kCellularDataPlanUpdateTime = "CellularPlanUpdateTime"; 21 static const char *kCellularDataPlanUpdateTime = "CellularPlanUpdateTime";
20 static const char *kCellularDataPlanStartTime = "CellularPlanStart"; 22 static const char *kCellularDataPlanStartTime = "CellularPlanStart";
21 static const char *kCellularDataPlanEndTime = "CellularPlanEnd"; 23 static const char *kCellularDataPlanEndTime = "CellularPlanEnd";
(...skipping 15 matching lines...) Expand all
37 static const char *kCrosUsageDataPlanEndTimeProperty = "expirationTime"; 39 static const char *kCrosUsageDataPlanEndTimeProperty = "expirationTime";
38 static const char *kCrosUsageDataPlanStartTimeProperty = "startTime"; 40 static const char *kCrosUsageDataPlanStartTimeProperty = "startTime";
39 41
40 // Chromium OS Usage API Data Plan type values 42 // Chromium OS Usage API Data Plan type values
41 static const char *kCrosUsageDataPlanTypeUnlimited = "UNLIMITED"; 43 static const char *kCrosUsageDataPlanTypeUnlimited = "UNLIMITED";
42 static const char *kCrosUsageDataPlanTypeMeteredFree = "METERED_FREE"; 44 static const char *kCrosUsageDataPlanTypeMeteredFree = "METERED_FREE";
43 static const char *kCrosUsageDataPlanTypeMeteredPaid = "METERED_PAID"; 45 static const char *kCrosUsageDataPlanTypeMeteredPaid = "METERED_PAID";
44 46
45 DataPlan::DataPlan(const std::string& name, DataPlan::Type type, 47 DataPlan::DataPlan(const std::string& name, DataPlan::Type type,
46 base::Time update_time, base::Time start_time, 48 base::Time update_time, base::Time start_time,
47 base::Time end_time, Bytes data_bytes_max, 49 base::Time end_time, ByteCount data_bytes_max,
48 Bytes data_bytes_used) 50 ByteCount data_bytes_used)
49 : name_(name), type_(type), update_time_(update_time), 51 : name_(name), type_(type), update_time_(update_time),
50 start_time_(start_time), end_time_(end_time), 52 start_time_(start_time), end_time_(end_time),
51 data_bytes_max_(data_bytes_max), data_bytes_used_(data_bytes_used), 53 data_bytes_max_(data_bytes_max), data_bytes_used_(data_bytes_used),
52 local_bytes_used_(0), total_bytes_used_(data_bytes_used) { 54 local_bytes_used_(0), total_bytes_used_(data_bytes_used) {
53 CHECK_GE(data_bytes_max_, 0); 55 CHECK_GE(data_bytes_max_, 0);
54 CHECK_GE(data_bytes_used_, 0); 56 CHECK_GE(data_bytes_used_, 0);
55 } 57 }
56 58
57 DataPlan::~DataPlan() { 59 DataPlan::~DataPlan() {
58 } 60 }
(...skipping 11 matching lines...) Expand all
70 } 72 }
71 73
72 base::Time DataPlan::GetStartTime() const { 74 base::Time DataPlan::GetStartTime() const {
73 return start_time_; 75 return start_time_;
74 } 76 }
75 77
76 base::Time DataPlan::GetEndTime() const { 78 base::Time DataPlan::GetEndTime() const {
77 return end_time_; 79 return end_time_;
78 } 80 }
79 81
80 Bytes DataPlan::GetDataBytesMax() const { 82 ByteCount DataPlan::GetDataBytesMax() const {
81 return data_bytes_max_; 83 return data_bytes_max_;
82 } 84 }
83 85
84 Bytes DataPlan::GetDataBytesUsed() const { 86 ByteCount DataPlan::GetDataBytesUsed() const {
85 return data_bytes_used_; 87 return data_bytes_used_;
86 } 88 }
87 89
88 Bytes DataPlan::GetLocalBytesUsed() const { 90 ByteCount DataPlan::GetLocalBytesUsed() const {
89 return local_bytes_used_; 91 return local_bytes_used_;
90 } 92 }
91 93
92 Bytes DataPlan::GetTotalBytesUsed() const { 94 ByteCount DataPlan::GetTotalBytesUsed() const {
93 return total_bytes_used_; 95 return total_bytes_used_;
94 } 96 }
95 97
96 void DataPlan::SetLocalBytesUsed(Bytes local_bytes_used) { 98 // TODO(vlaviano): ensure that this method stops the plan's expiration timer
99 // (when it is implemented in a future CL) if the plan is fully consumed
100 void DataPlan::SetLocalBytesUsed(ByteCount local_bytes_used) {
97 CHECK_GE(local_bytes_used, 0); 101 CHECK_GE(local_bytes_used, 0);
98 local_bytes_used_ = local_bytes_used; 102 local_bytes_used_ = local_bytes_used;
99 total_bytes_used_ = data_bytes_used_ + local_bytes_used_; 103 total_bytes_used_ = data_bytes_used_ + local_bytes_used_;
100 if (total_bytes_used_ < 0) { 104 if (total_bytes_used_ < 0) {
101 LOG(WARNING) << "SetLocalBytesUsed: overflow detected"; 105 LOG(WARNING) << "SetLocalBytesUsed: overflow detected";
102 total_bytes_used_ = kint64max; 106 total_bytes_used_ = kint64max;
103 } 107 }
104 } 108 }
105 109
106 bool DataPlan::IsActive() const { 110 bool DataPlan::IsActive() const {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 for (it = data_plans.begin(); it != data_plans.end(); ++it) { 313 for (it = data_plans.begin(); it != data_plans.end(); ++it) {
310 DataPlan *plan = *it; 314 DataPlan *plan = *it;
311 DCHECK(plan != NULL); 315 DCHECK(plan != NULL);
312 if (plan->IsActive()) { 316 if (plan->IsActive()) {
313 return plan; 317 return plan;
314 } 318 }
315 } 319 }
316 return NULL; 320 return NULL;
317 } 321 }
318 322
323 // static
324 bool DataPlan::OnByteCounterUpdate(DataPlanList *data_plans, Service *service,
325 ServiceManager *service_manager,
326 Device *device, uint64 rx_bytes,
327 uint64 tx_bytes) {
328 DCHECK(data_plans != NULL);
329 DCHECK(service != NULL);
330 DCHECK(service_manager != NULL);
331 DCHECK(device != NULL);
332 DCHECK(device->ByteCounterRunning());
333 DLOG(INFO) << "OnByteCounterUpdate: rx_bytes = " << rx_bytes
334 << ", tx_bytes = " << tx_bytes;
335 DataPlan *active_plan = DataPlan::GetActivePlan(*data_plans);
336 if (active_plan == NULL) {
337 DLOG(WARNING) << "OnByteCounterUpdate: no active plan";
338 device->StopByteCounter();
339 return false;
340 }
341 ByteCount local_bytes_used = rx_bytes + tx_bytes;
342 DLOG(INFO) << "OnByteCounterUpdate: local_bytes_used = " << local_bytes_used;
343 // try to detect two error conditions:
344 // (1) overflow of the unsigned addition above prior to the assignment
345 // (2) no overflow, but result has high order bit set and so is interpreted as
346 // a negative number when assigned to |local_bytes_used|
347 if (local_bytes_used < 0 ||
348 static_cast<uint64>(local_bytes_used) < rx_bytes ||
349 static_cast<uint64>(local_bytes_used) < tx_bytes) {
350 LOG(WARNING) << "OnByteCounterUpdate: overflow detected";
351 return false;
352 }
353 // compute delta since last sample
354 // this delta represents the data usage that we need to assign to active plans
355 // this computation relies on the local counter being based on the currently
356 // active plan
357 // TODO(vlaviano): Currently, this is not always true. It's possible for the
358 // local byte counter to be associated with a plan that was active at the
359 // beginning of the sample interval but has now expired. A future CL will
360 // add expiration timers to plan objects to handle this case.
361 ByteCount previous_local_bytes_used = active_plan->GetLocalBytesUsed();
362 DLOG(INFO) << "OnByteCounterUpdate: previous_local_bytes_used = "
363 << previous_local_bytes_used;
364 DCHECK_LE(previous_local_bytes_used, local_bytes_used);
365 ByteCount used_bytes_to_assign = local_bytes_used - previous_local_bytes_used;
366 DLOG(INFO) << "OnByteCounterUpdate: used_bytes_to_assign = "
367 << used_bytes_to_assign;
368 // iterate through active plans, assigning as much data as possible to each
369 // plan and expiring it if its data quota is fully consumed
370 ByteCount assigned_bytes = 0;
371 bool any_plan_updated = false;
372 while (used_bytes_to_assign > 0 && active_plan != NULL) {
373 ByteCount active_plan_data_remaining = 0; // relevant for metered plans
374 if (active_plan->GetType() != DataPlan::kTypeUnlimited) {
375 active_plan_data_remaining = active_plan->GetDataBytesMax() -
376 active_plan->GetTotalBytesUsed();
377 DCHECK_GE(active_plan_data_remaining, 0);
378 }
379 if (active_plan->GetType() == DataPlan::kTypeUnlimited ||
380 used_bytes_to_assign < active_plan_data_remaining) {
381 // can assign all data from this sample and plan not fully consumed
382 assigned_bytes = used_bytes_to_assign;
383 used_bytes_to_assign = 0;
384 } else {
385 // plan fully consumed, and there might be an overage remaining to be
386 // assigned to the next active plan
387 assigned_bytes = active_plan_data_remaining;
388 used_bytes_to_assign -= assigned_bytes;
389 }
390 DCHECK_GE(assigned_bytes, 0);
391 active_plan->SetLocalBytesUsed(previous_local_bytes_used + assigned_bytes);
392 any_plan_updated = true;
393 DLOG(INFO) << "OnByteCounterUpdate: " << active_plan->GetName()
394 << ": updated plan state: data bytes used = "
395 << active_plan->GetDataBytesUsed() << ", local bytes used = "
396 << active_plan->GetLocalBytesUsed() << ", total bytes used = "
397 << active_plan->GetTotalBytesUsed();
398
399 if (!active_plan->IsActive()) {
400 // notify service manager that plan has become inactive
401 service_manager->OnDataPlanInactive(*service, *active_plan);
402
403 // we've consumed a plan, so reset byte counter to only reflect overage
404 // TODO(vlaviano): byte counter api shouldn't expose rx/tx split.
405 device->ResetByteCounter(used_bytes_to_assign, 0);
406 active_plan = DataPlan::GetActivePlan(*data_plans);
407 }
408 }
409
410 // if we have no more active plans, stop our local counter
411 if (active_plan == NULL) {
412 device->StopByteCounter();
413 // warn if we've measured usage beyond what should have been available
414 if (used_bytes_to_assign > 0) {
415 DLOG(WARNING) << "OnByteCounterUpdate: used_bytes_to_assign = "
416 << used_bytes_to_assign << ", but no active plan";
417 }
418 }
419 return any_plan_updated;
420 }
421
319 // private methods 422 // private methods
320 423
321 const char* DataPlan::TypeToLibcrosString(DataPlan::Type type) const { 424 const char* DataPlan::TypeToLibcrosString(DataPlan::Type type) const {
322 switch (type) { 425 switch (type) {
323 case kTypeUnlimited: 426 case kTypeUnlimited:
324 return kCellularDataPlanTypeUnlimited; 427 return kCellularDataPlanTypeUnlimited;
325 case kTypeMeteredFree: 428 case kTypeMeteredFree:
326 return kCellularDataPlanTypeMeteredFree; 429 return kCellularDataPlanTypeMeteredFree;
327 case kTypeMeteredPaid: 430 case kTypeMeteredPaid:
328 return kCellularDataPlanTypeMeteredPaid; 431 return kCellularDataPlanTypeMeteredPaid;
(...skipping 28 matching lines...) Expand all
357 *out_value = generic_int_out; 460 *out_value = generic_int_out;
358 return true; 461 return true;
359 } 462 }
360 if (dict.GetInteger64(key, out_value)) { 463 if (dict.GetInteger64(key, out_value)) {
361 return true; 464 return true;
362 } 465 }
363 return false; 466 return false;
364 } 467 }
365 468
366 } // namespace cashew 469 } // namespace cashew
OLDNEW
« no previous file with comments | « src/data_plan.h ('k') | src/data_plan_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698