118 lines
3.6 KiB
C++
118 lines
3.6 KiB
C++
//
|
|
// 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
|