3 #include "config_portability.h"
12 #include "diagnostic.h"
13 #include "forecast_api.h"
16 /* the default MAX timeout */
17 #define DEFAULT_MAX_TIMEOUT (120.0)
18 #define DEFAULT_MIN_TIMEOUT (5.0)
20 /* we have this number of entries */
21 #define HOW_MANY_ENTRIES (1024)
23 /* keep track of the measurements we got */
26 FORECASTAPI_ForecastState *state[TIMEOUT_TYPES_NUMBER];
29 static void *lock = NULL; /* local mutex */
31 /* we have few types to keep track of */
32 static timeOutStruct timeOuts[HOW_MANY_ENTRIES];
34 /* keep track of the current limits on the timeouts */
35 static double to_limits[TIMEOUT_TYPES_NUMBER*2];
37 /* helper to work with modulo HOW_MANY_ENTRIES */
38 #define MODPLUS(a,b,m) (((a) + (b)) % (m))
39 #define MODMINUS(a,b,m) (((a) - (b) + (m)) % (m))
42 * Initialize the Hash structure
47 static int initialized = 0;
49 /* let's do it only once */
50 if (initialized != 0) {
57 for (i=0; i < HOW_MANY_ENTRIES; i++) {
59 for (j=0; j < TIMEOUT_TYPES_NUMBER; j++) {
60 timeOuts[i].state[j] = NULL;
63 ReleaseNWSLock(&lock);
65 for (j=0; j < TIMEOUT_TYPES_NUMBER; j++) {
66 /* set defaults to sane state */
67 SetDefaultTimeout(j, DEFAULT_MIN_TIMEOUT, DEFAULT_MAX_TIMEOUT);
71 /* we use a simple hash table structure to speed up the access to the
72 * timeout structures. If #addr# is not in the table it is added and if
73 * the table is full, space is made for the addr.
74 * Returns # the index at which addr is been found
77 HashIndex(IPAddress addr) {
80 /* initialize the structure */
83 i = addr % HOW_MANY_ENTRIES;
84 end = MODMINUS(i, 1, HOW_MANY_ENTRIES);
87 for (; i != end; i = MODPLUS(i, 1, HOW_MANY_ENTRIES)) {
88 if ((timeOuts[i].addr == addr) || (timeOuts[i].addr == 0)) {
89 /* either we found it, or emtpy slot: is good */
95 /* table is full: emtpying one slot */
96 i = addr % HOW_MANY_ENTRIES;
100 /* if this is the first time we have the item, get it to a sane
102 if (timeOuts[i].addr == 0) {
103 timeOuts[i].addr = addr;
104 for (end=0; end < TIMEOUT_TYPES_NUMBER; end++) {
105 /* Initialize the forecaster state */
106 if (timeOuts[i].state[end] != NULL) {
107 FORECASTAPI_FreeForecastState(&timeOuts[i].state[end]);
109 timeOuts[i].state[end] = FORECASTAPI_NewForecastState();
113 ReleaseNWSLock(&lock);
119 SetDefaultTimeout(timeoutTypes type, double min, double max) {
121 if (type < RECV || type > USER3) {
122 WARN("SetDefaultTimeout: unknown type\n");
133 to_limits[type*2] = min;
134 to_limits[type*2 + 1] = max;
135 ReleaseNWSLock(&lock);
139 GetDefaultTimeout(timeoutTypes type, double *min, double *max) {
141 if (type < RECV || type > USER3) {
142 WARN("SetDefaultTimeout: unknown type\n");
146 *min = to_limits[type*2];
147 *max = to_limits[type*2 + 1];
148 ReleaseNWSLock(&lock);
153 GetTimeOut(timeoutTypes type, IPAddress addr, long size) {
156 FORECASTAPI_ForecastCollection forecast;
159 if (type < 0 || type > USER3) {
160 WARN("GetTimeOut: type out of range\n");
164 /* if addr is 0 (for example if it's a pipe) we pick the minimums
167 return to_limits[type*2];
172 /* let's get a forecast */
174 if (FORECASTAPI_ComputeForecast(timeOuts[i].state[type], &forecast) != 0) {
175 forecast.forecasts[type].forecast = to_limits[type*2 + 1];
177 ReleaseNWSLock(&lock);
179 /* let's get 3 standard deviations (if we have sqrt) */
181 ret = forecast.forecasts[0].forecast + 3 * sqrt(forecast.forecasts[FORECASTAPI_MSE_FORECAST].error);
183 ret = forecast.forecasts[0].forecast + 2 * forecast.forecasts[FORECASTAPI_MAE_FORECAST].error;
186 /* adjust for the size of the packet */
191 if (ret > to_limits[type*2 + 1]) {
192 ret = to_limits[type*2 + 1];
193 } else if (ret < to_limits[type*2]) {
194 ret = to_limits[type*2];
201 SetTimeOut(timeoutTypes type, IPAddress addr, double duration, long size, int timedOut) {
203 FORECASTAPI_Measurement m;
206 if (type < 0 || type > USER3) {
207 WARN("SetTimeOut: type out of range\n");
211 WARN("SetTimeOut: duration negative?\n");
215 /* if addr is 0 (for example if it's a pipe) we return */
222 m.timeStamp = CurrentTime();
223 /* adjust for the size of the packet */
225 m.measurement = duration / size;
227 m.measurement = duration;
230 /* adjustments if we timed out before */
235 FORECASTAPI_UpdateForecast(timeOuts[i].state[type], &m, 1);
236 ReleaseNWSLock(&lock);