#include <Clock.h>
Public Member Functions | |
Clock (void) | |
create a clock | |
Clock (const Timeval &delta) | |
create a clock that ticks at the given interval | |
Clock (const Clock &toCopy) | |
Clock * | clone (const Clock &toCopy) |
Clock & | operator= (const Clock &rhs) |
Alarm & | addAlarm (AlarmListener &l, const Timeval &s, const Timeval &i) |
Add a repeating alarm initiated at a given time, occurring at a given interval. | |
void | addAlarmEvent (Alarm &alarm, const Timeval &when) |
Method for Alarm objects to add AlarmEvents. | |
void | updateClock (const Timeval &time) |
global clock update, called before a packet is processed | |
const Timeval & | getTime (void) const |
get the current time | |
int | getPhase (void) const |
get the current phase of the timeval | |
Static Public Member Functions | |
static Clock & | getClock (void) |
Static Public Attributes | |
static const int | PHASE_PRETIME = 0 |
static const int | PHASE_INTIME = 1 |
static const int | PHASE_POSTTIME = 2 |
Protected Attributes | |
std::vector< Alarm * > | alarms |
std::priority_queue< AlarmEvent, std::vector< AlarmEvent >, std::greater< AlarmEvent > > | q |
Timeval | currTime |
int | phase |
bool | started |
Static Protected Attributes | |
static Clock | theClock |
Time is a major issue for this toolkit, in more ways than one. We wish to be able to support two types of time-driven attributes; those with a time-based window, and alarm-driven attributes. The former need to be able to update their windows appropriately, and the latter need to receive alarms at a pre-set interval in order to update. An example of windowed attributes is a buffer that maintains the packet length of every packet for a flow in the past 30 seconds; an example of an alarm-driven attribute is one that maintains a list of data volumes over discrete 30-second windows, and another example is one that computes the minimum 30-second data volume (over non-discrete intervals). This documentation discusses the motivation behind the time handling for the toolkit, as there are a number of very significant design decisions taken here based on many interacting factors - put simply, I think these things are VERY hazardous to muck with, so I'm trying to flag all the landmines.
Windowed attributes must be able to update their windows so that they contain all packets in a certain time window, without double-counting (unless it's a sliding window). That is, for a 30s window, the window starting at time 0s and the one starting at time 30s should not share any packets. They must also be able to ensure that their window is up-to-date at any given time.
Alarm-driven attributes must be able to tell the toolkit to poll them at a set frequency from a given start time, and the toolkit must ensure that these alarms are triggered. An alarm being triggered means a handler function being called in the attribute which set the alarm. It also must be able to ensure that an alarm set for the current time has gone off, due to the possibility of simultaneous alarms for multiple attributes with some interdependency (i.e. if A and B both have an alarm set for time t, and B depends on A, but B's alarm goes off first, then when A is queried by B, it has to be able to trigger its own alarm if appropriate).
To deal with the boundary problems that arise, we imagine three phases to each timeval: pretime, intime, and posttime. Pretime is an imaginary time before the timeval, and posttime an imaginary time after the timeval, wheras intime is the period of real time represented by the timeval. Pretime and posttime give us time to evalutate alarms when windows are in a consistent state. By this, we mean that in pretime for a timeval t, a window of time length w will include all packets in the interval [t-w,t), and in posttime for that timeval, it will include all packets in the interval (t-w,t]. During intime, no guarantees can be made, as we could be between processing two packets, both with a timestamp of t. Alarms for a specific timeval are handled in pretime for that timeval; the posttime is for a (to-be-implemented) `anytime' alarm functionality. That latter type of alarm is for min/max attributes that need to run computations before and after each timeval is handled. These phases spare us the metaphysical and pragmatic distresses inherent in `incrementing' a real valued timeval. :p
These mechanisms have consequences for purging flows with alarm-driven attributes; if a flow has a pending alarm, it should not be purged. For example, if a flow has a 30s data rate attribute, purging it while the alarm is still active would result in the packets between the end of the last full 30s segment and the end of the flow not being counted. Currently this is handled by leaving a flow in a `garbage bin' state and setting its alarms to go inactive after the next time they fire, then once all of the flow's alarms have gone inactive, it can be purged. >> On second thought, what we'll do for now is not leave the alarms on, but force alarm-driven attributes to have a `finalCalc' method that does whatever it has to to munge up the last value when the attribute is being deallocated.
Several design choices were made to accomodate all this messiness:
make certain that all attributes update when their values are accessed, otherwise bad things _will_ happen. This would be best to do by changing the getAttrib handling so that the superclass was more involved, possibly by replacing the per-attribute function with an initialization that populates a member which could be accessed by Attribute::getAttrib.
|
create a clock Defaults to a 1s interval |
|
Add a repeating alarm initiated at a given time, occurring at a given interval.
|
|
Method for Alarm objects to add AlarmEvents.
|
|
global clock update, called before a packet is processed
|