Willy Tarreau | 7f062c4 | 2009-03-05 18:43:00 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Event rate calculation functions. |
| 3 | * |
Willy Tarreau | 2970b0b | 2010-06-20 07:15:43 +0200 | [diff] [blame] | 4 | * Copyright 2000-2010 Willy Tarreau <w@1wt.eu> |
Willy Tarreau | 7f062c4 | 2009-03-05 18:43:00 +0100 | [diff] [blame] | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License |
| 8 | * as published by the Free Software Foundation; either version |
| 9 | * 2 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | */ |
| 12 | |
Willy Tarreau | 4c7e4b7 | 2020-05-27 12:58:42 +0200 | [diff] [blame] | 13 | #include <haproxy/api.h> |
Willy Tarreau | 6634794 | 2020-06-01 12:18:08 +0200 | [diff] [blame] | 14 | #include <haproxy/freq_ctr.h> |
Willy Tarreau | b255105 | 2020-06-09 09:07:15 +0200 | [diff] [blame] | 15 | #include <haproxy/time.h> |
| 16 | #include <haproxy/tools.h> |
Willy Tarreau | 7f062c4 | 2009-03-05 18:43:00 +0100 | [diff] [blame] | 17 | |
Willy Tarreau | f3a9f8d | 2021-04-11 00:38:06 +0200 | [diff] [blame] | 18 | /* Returns the total number of events over the current + last period, including |
| 19 | * a number of already pending events <pend>. The average frequency will be |
| 20 | * obtained by dividing the output by <period>. This is essentially made to |
| 21 | * ease implementation of higher-level read functions. |
| 22 | * |
| 23 | * As a special case, if pend < 0, it's assumed there are no pending |
| 24 | * events and a flapping correction must be applied at the end. This is used by |
| 25 | * read_freq_ctr_period() to avoid reporting ups and downs on low-frequency |
| 26 | * events when the past value is <= 1. |
| 27 | */ |
Willy Tarreau | fa1258f | 2021-04-10 23:00:53 +0200 | [diff] [blame] | 28 | ullong freq_ctr_total(struct freq_ctr *ctr, uint period, int pend) |
Willy Tarreau | f3a9f8d | 2021-04-11 00:38:06 +0200 | [diff] [blame] | 29 | { |
| 30 | ullong curr, past; |
| 31 | uint curr_tick; |
| 32 | int remain; |
| 33 | |
| 34 | for (;; __ha_cpu_relax()) { |
| 35 | curr = ctr->curr_ctr; |
| 36 | past = ctr->prev_ctr; |
| 37 | curr_tick = ctr->curr_tick; |
| 38 | |
| 39 | /* now let's make sure the second loads retrieve the most |
| 40 | * up-to-date values. If no value changed after a load barrier, |
| 41 | * we're certain the values we got were stable. |
| 42 | */ |
| 43 | __ha_barrier_load(); |
| 44 | |
| 45 | if (curr_tick & 0x1) |
| 46 | continue; |
| 47 | |
| 48 | if (curr != ctr->curr_ctr) |
| 49 | continue; |
| 50 | |
| 51 | if (past != ctr->prev_ctr) |
| 52 | continue; |
| 53 | |
| 54 | if (curr_tick != ctr->curr_tick) |
| 55 | continue; |
| 56 | break; |
| 57 | }; |
| 58 | |
| 59 | remain = curr_tick + period - global_now_ms; |
| 60 | if (unlikely(remain < 0)) { |
| 61 | /* We're past the first period, check if we can still report a |
| 62 | * part of last period or if we're too far away. |
| 63 | */ |
| 64 | remain += period; |
| 65 | past = (remain >= 0) ? curr : 0; |
| 66 | curr = 0; |
| 67 | } |
| 68 | |
| 69 | if (pend < 0) { |
| 70 | /* enable flapping correction at very low rates */ |
| 71 | pend = 0; |
| 72 | if (!curr && past <= 1) |
| 73 | return past * period; |
| 74 | } |
| 75 | |
| 76 | /* compute the total number of confirmed events over the period */ |
| 77 | return past * remain + (curr + pend) * period; |
| 78 | } |
Willy Tarreau | 7f062c4 | 2009-03-05 18:43:00 +0100 | [diff] [blame] | 79 | |
| 80 | /* |
| 81 | * Local variables: |
| 82 | * c-indent-level: 8 |
| 83 | * c-basic-offset: 8 |
| 84 | * End: |
| 85 | */ |