| // |
| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // 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 "shill/net/event_history.h" |
| |
| #include <time.h> |
| |
| #include <deque> |
| |
| #include "shill/net/shill_time.h" |
| |
| using std::deque; |
| |
| namespace shill { |
| |
| void EventHistory::RecordEvent() { |
| RecordEventInternal(time_->GetNow()); |
| } |
| |
| void EventHistory::ExpireEventsBefore(int seconds_ago, ClockType clock_type) { |
| ExpireEventsBeforeInternal(seconds_ago, time_->GetNow(), clock_type); |
| } |
| |
| void EventHistory::RecordEventAndExpireEventsBefore(int seconds_ago, |
| ClockType clock_type) { |
| Timestamp now = time_->GetNow(); |
| RecordEventInternal(now); |
| ExpireEventsBeforeInternal(seconds_ago, now, clock_type); |
| } |
| |
| std::vector<std::string> EventHistory::ExtractWallClockToStrings() const { |
| std::vector<std::string> strings; |
| for (deque<Timestamp>::const_iterator it = events_.begin(); |
| it != events_.end(); ++it) { |
| strings.push_back(it->wall_clock); |
| } |
| return strings; |
| } |
| |
| void EventHistory::RecordEventInternal(Timestamp now) { |
| events_.push_back(now); |
| while (!events_.empty() && max_events_specified_ && |
| (events_.size() > static_cast<size_t>(max_events_saved_))) { |
| events_.pop_front(); |
| } |
| } |
| |
| void EventHistory::ExpireEventsBeforeInternal(int seconds_ago, Timestamp now, |
| ClockType clock_type) { |
| struct timeval interval = (const struct timeval){seconds_ago}; |
| while (!events_.empty()) { |
| struct timeval elapsed = {0, 0}; |
| switch (clock_type) { |
| case kClockTypeBoottime: |
| timersub(&now.boottime, &events_.front().boottime, &elapsed); |
| break; |
| case kClockTypeMonotonic: |
| timersub(&now.monotonic, &events_.front().monotonic, &elapsed); |
| break; |
| default: { |
| NOTIMPLEMENTED() |
| << __func__ << ": " |
| << "Invalid clock type specified - defaulting to boottime clock"; |
| timersub(&now.boottime, &events_.front().boottime, &elapsed); |
| } |
| } |
| if (timercmp(&elapsed, &interval, < )) { |
| break; |
| } |
| events_.pop_front(); |
| } |
| } |
| |
| int EventHistory::CountEventsWithinInterval(int seconds_ago, |
| ClockType clock_type) { |
| int num_events_in_interval = 0; |
| Timestamp now = time_->GetNow(); |
| struct timeval interval = (const struct timeval){seconds_ago}; |
| int i = 0; |
| for (const auto& event : events_) { |
| struct timeval elapsed = {0, 0}; |
| switch (clock_type) { |
| case kClockTypeBoottime: |
| timersub(&now.boottime, &event.boottime, &elapsed); |
| break; |
| case kClockTypeMonotonic: |
| timersub(&now.monotonic, &event.monotonic, &elapsed); |
| break; |
| default: { |
| NOTIMPLEMENTED() |
| << __func__ << ": " |
| << "Invalid clock type specified - defaulting to boottime clock"; |
| timersub(&now.boottime, &event.boottime, &elapsed); |
| } |
| } |
| if (timercmp(&elapsed, &interval, <= )) { |
| num_events_in_interval = events_.size() - i; |
| break; |
| } |
| ++i; |
| } |
| return num_events_in_interval; |
| } |
| |
| } // namespace shill |