1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/net/event_history.h" 18 19 #include <time.h> 20 21 #include <deque> 22 23 #include "shill/net/shill_time.h" 24 25 using std::deque; 26 27 namespace shill { 28 29 void EventHistory::RecordEvent() { 30 RecordEventInternal(time_->GetNow()); 31 } 32 33 void EventHistory::ExpireEventsBefore(int seconds_ago, ClockType clock_type) { 34 ExpireEventsBeforeInternal(seconds_ago, time_->GetNow(), clock_type); 35 } 36 37 void EventHistory::RecordEventAndExpireEventsBefore(int seconds_ago, 38 ClockType clock_type) { 39 Timestamp now = time_->GetNow(); 40 RecordEventInternal(now); 41 ExpireEventsBeforeInternal(seconds_ago, now, clock_type); 42 } 43 44 std::vector<std::string> EventHistory::ExtractWallClockToStrings() const { 45 std::vector<std::string> strings; 46 for (deque<Timestamp>::const_iterator it = events_.begin(); 47 it != events_.end(); ++it) { 48 strings.push_back(it->wall_clock); 49 } 50 return strings; 51 } 52 53 void EventHistory::RecordEventInternal(Timestamp now) { 54 events_.push_back(now); 55 while (!events_.empty() && max_events_specified_ && 56 (events_.size() > static_cast<size_t>(max_events_saved_))) { 57 events_.pop_front(); 58 } 59 } 60 61 void EventHistory::ExpireEventsBeforeInternal(int seconds_ago, Timestamp now, 62 ClockType clock_type) { 63 struct timeval interval = (const struct timeval){seconds_ago}; 64 while (!events_.empty()) { 65 struct timeval elapsed = {0, 0}; 66 switch (clock_type) { 67 case kClockTypeBoottime: 68 timersub(&now.boottime, &events_.front().boottime, &elapsed); 69 break; 70 case kClockTypeMonotonic: 71 timersub(&now.monotonic, &events_.front().monotonic, &elapsed); 72 break; 73 default: { 74 NOTIMPLEMENTED() 75 << __func__ << ": " 76 << "Invalid clock type specified - defaulting to boottime clock"; 77 timersub(&now.boottime, &events_.front().boottime, &elapsed); 78 } 79 } 80 if (timercmp(&elapsed, &interval, < )) { 81 break; 82 } 83 events_.pop_front(); 84 } 85 } 86 87 int EventHistory::CountEventsWithinInterval(int seconds_ago, 88 ClockType clock_type) { 89 int num_events_in_interval = 0; 90 Timestamp now = time_->GetNow(); 91 struct timeval interval = (const struct timeval){seconds_ago}; 92 int i = 0; 93 for (const auto& event : events_) { 94 struct timeval elapsed = {0, 0}; 95 switch (clock_type) { 96 case kClockTypeBoottime: 97 timersub(&now.boottime, &event.boottime, &elapsed); 98 break; 99 case kClockTypeMonotonic: 100 timersub(&now.monotonic, &event.monotonic, &elapsed); 101 break; 102 default: { 103 NOTIMPLEMENTED() 104 << __func__ << ": " 105 << "Invalid clock type specified - defaulting to boottime clock"; 106 timersub(&now.boottime, &event.boottime, &elapsed); 107 } 108 } 109 if (timercmp(&elapsed, &interval, <= )) { 110 num_events_in_interval = events_.size() - i; 111 break; 112 } 113 ++i; 114 } 115 return num_events_in_interval; 116 } 117 118 } // namespace shill 119