/* * same as hist_check() in ratelimit.c but this one * only counts, no updates on the window ==> faster */ static inline int ALLOW_UNUSED hist_count(rl_pipe_t *pipe) { /* Window ELement*/ #define U2MILI(__usec__) (__usec__/1000) #define S2MILI(__sec__) (__sec__ *1000) int i; int first_good_index; int rl_win_ms = rl_window_size * 1000; int count=0; unsigned long long now_total, start_total; struct timeval tv; gettimeofday(&tv, NULL); if (pipe->rwin.start_time.tv_sec == 0) { return 0; } else { start_total = S2MILI(pipe->rwin.start_time.tv_sec) + U2MILI(pipe->rwin.start_time.tv_usec); now_total = S2MILI(tv.tv_sec) + U2MILI(tv.tv_usec); if (now_total - start_total >= 2*rl_win_ms) { /* nothing here; window is expired */ } else if (now_total - start_total >= rl_win_ms) { first_good_index = ((((now_total - rl_win_ms) - start_total) /rl_slot_period + 1) + pipe->rwin.start_index) % pipe->rwin.window_size; count = 0; for (i=first_good_index; i != pipe->rwin.start_index; i=(i+1)%pipe->rwin.window_size) count += pipe->rwin.window[i]; } else { /* count all of them; valid window */ for (i=0; i < pipe->rwin.window_size; i++) count += pipe->rwin.window[i]; } } return count; #undef U2MILI #undef S2MILI }
/** * the algorithm keeps a circular window of requests in a fixed size buffer * * @param pipe containing the window * @param update whether or not to inc call number * @return number of calls in the window */ static inline int hist_check(rl_pipe_t *pipe, int update) { #define U2MILI(__usec__) (__usec__/1000) #define S2MILI(__sec__) (__sec__ *1000) int i; int first_good_index; int rl_win_ms = rl_window_size * 1000; unsigned long long now_total, start_total; struct timeval tv; /* first get values from our beloved replicated friends * current pipe counter will be calculated after this * iteration; no need for the old one */ pipe->counter = 0; pipe->counter = rl_get_all_counters(pipe); gettimeofday(&tv, NULL); if (pipe->rwin.start_time.tv_sec == 0) { /* the lucky one to come first here */ pipe->rwin.start_time = tv; pipe->rwin.start_index = 0; /* we know it starts from 0 because we did memset when created*/ pipe->rwin.window[pipe->rwin.start_index] += update; } else { start_total = S2MILI(pipe->rwin.start_time.tv_sec) + U2MILI(pipe->rwin.start_time.tv_usec); now_total = S2MILI(tv.tv_sec) + U2MILI(tv.tv_usec); /* didn't do any update to the window for "2*window_size" secs * we can't use any elements from the vector * the window is invalidated; very unlikely to happen*/ if (now_total - start_total >= 2*rl_win_ms) { memset(pipe->rwin.window, 0, pipe->rwin.window_size * sizeof(long int)); pipe->rwin.start_index = 0; pipe->rwin.start_time = tv; pipe->rwin.window[pipe->rwin.start_index] += update; } else if (now_total - start_total >= rl_win_ms) { /* current time in interval [window_size; 2*window_size) * all the elements in [start_time; (ctime-window_size+1) are * invalidated(set to 0) * */ /* the first window index not to be set to 0 * number of slots from the start_index*/ first_good_index = ((((now_total - rl_win_ms) - start_total) /rl_slot_period + 1) + pipe->rwin.start_index) % pipe->rwin.window_size; /* the new start time will be the start time of the first slot */ start_total = (now_total - rl_win_ms) - (now_total - rl_win_ms)%rl_slot_period+ rl_slot_period; pipe->rwin.start_time.tv_sec = start_total/1000; pipe->rwin.start_time.tv_usec = (start_total%1000)*1000; for (i=pipe->rwin.start_index; i != first_good_index; i=(i+1)%pipe->rwin.window_size) pipe->rwin.window[i] = 0; pipe->rwin.start_index = first_good_index; /* count current call; it will be the last element in the window */ pipe->rwin.window[((pipe->rwin.start_index) + (pipe->rwin.window_size-1)) % pipe->rwin.window_size] += update; } else { /* now_total - start_total < rl_win_ms */ /* no need to modify the window, the value is inside it; * we just need to increment the number of calls for * the current slot*/ pipe->rwin.window[(now_total-start_total)/rl_slot_period] += update; } } /* count the total number of calls in the window */ for (i=0; i < pipe->rwin.window_size; i++) pipe->counter += pipe->rwin.window[i]; return pipe->counter > pipe->limit ? -1 : 1; #undef U2MILI #undef S2MILI }