Home | History | Annotate | Download | only in net
      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