-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathseries.c
132 lines (111 loc) · 4.37 KB
/
series.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <stdlib.h>
#include "common.h"
#include "series.h"
#include "pinger.h"
#include "stat.h"
t_series_list stat_series[MAXTTL];
const int series_count = MAXTTL;
int series_datamax = PP_RTT0;
static t_series_list stat_series_kept[MAXTTL];
#define KEPT_SERIES(i) stat_series_kept[i].list
#define KEPT_SERIES_LEN(i) stat_series_kept[i].len
#define CURR_SERIES(i) series[i].list
#define CURR_SERIES_LEN(i) series[i].len
#define CURR_SERIES_LAST_SEQ(i) ((CURR_SERIES_LEN(i) && CURR_SERIES(i) && CURR_SERIES(i)->data) ? \
((t_rseq*)CURR_SERIES(i)->data)->seq : 0)
static gboolean grm_lock;
static int series_no = MIN_SERIES_RANGE + 1;
GSList *on_scale_list;
//
static void series_scale(int max) {
series_datamax = max * GRAPH_DATA_GAP;
for (GSList *item = on_scale_list; item; item = item->next) {
GtkWidget *widget = item->data;
if (!GTK_IS_WIDGET(widget)) continue;
gtk_widget_queue_draw(widget);
if (!gtk_widget_get_visible(widget)) gtk_widget_set_visible(widget, true);
}
}
static int max_in_series(GSList* list) {
int max = PP_RTT0;
for (int i = 0; i < series_count; i++)
for (GSList *item = list; item; item = item->next) {
if (!item->data) continue;
int rtt = ((t_rseq*)item->data)->rtt;
if (rtt > max) max = rtt;
}
return max;
}
static void series_save_rseq(int nth, t_rseq *data) {
if (grm_lock || !data) return;
t_rseq *dup = g_memdup2(data, sizeof(*data));
if (!dup) return; // highly unlikely
t_series_list* series = pinger_state.pause ? stat_series_kept : stat_series;
CURR_SERIES(nth) = g_slist_prepend(CURR_SERIES(nth), dup); CURR_SERIES_LEN(nth)++;
if (data->rtt > series_datamax) series_scale(data->rtt); // up-scale
while (CURR_SERIES(nth) && (CURR_SERIES_LEN(nth) > series_no)) {
GSList *last = g_slist_last(CURR_SERIES(nth));
if (!last) break;
int rtt = last->data ? ((t_rseq*)last->data)->rtt : -1;
if (last->data) { g_free(last->data); last->data = NULL; }
CURR_SERIES(nth) = g_slist_delete_link(CURR_SERIES(nth), last); CURR_SERIES_LEN(nth)--;
if ((rtt * GRAPH_DATA_GAP) >= series_datamax) {
int max = max_in_series(CURR_SERIES(nth));
if (((max * GRAPH_DATA_GAP) < series_datamax) && (max > PP_RTT0)) series_scale(max); // down-scale
}
}
}
static gpointer series_on_copy(gconstpointer src, gpointer data G_GNUC_UNUSED) {
return g_memdup2(src, sizeof(t_rseq));
}
// pub
void series_update(void) {
if (grm_lock) return;
t_series_list* series = pinger_state.pause ? stat_series_kept : stat_series;
t_rseq skip = { .rtt = -1, .seq = 0 };
for (int i = 0; i < series_count; i++) {
if ((opts.range.min <= i) && (i < tgtat)) {
int seq = CURR_SERIES_LAST_SEQ(i) + 1;
t_rseq data = { .seq = seq };
stat_rseq(i, &data);
if (data.seq > 0) series_save_rseq(i, &data);
else /* sync seq */ if (data.seq < 0) { // rarely
data.seq = -data.seq;
if (data.seq < seq) DEBUG("%s: #%d -> #%d", SYNC_BACK_HDR, seq, data.seq);
else { // unlikely, just in case
series_save_rseq(i, &data);
DEBUG("%s: #%d -> #%d", SYNC_FRWD_HDR, seq, data.seq);
}
}
} else series_save_rseq(i, &skip);
}
}
void series_free(gboolean unreg) {
series_datamax = PP_RTT0;
for (int i = 0; i < series_count; i++) {
SERIES_LEN(i) = 0; if (SERIES(i)) { g_slist_free_full(SERIES(i), g_free); SERIES(i) = NULL; }
KEPT_SERIES_LEN(i) = 0; if (KEPT_SERIES(i)) { g_slist_free_full(KEPT_SERIES(i), g_free); KEPT_SERIES(i) = NULL; }
}
if (unreg && on_scale_list) { g_slist_free(on_scale_list); on_scale_list = NULL; }
}
void series_lock(void) {
grm_lock = true;
for (int i = 0; i < series_count; i++) { // keep current data
KEPT_SERIES(i) = SERIES(i) ? g_slist_copy_deep(SERIES(i), series_on_copy, NULL) : NULL;
KEPT_SERIES_LEN(i) = g_slist_length(KEPT_SERIES(i));
}
grm_lock = false;
}
void series_unlock(void) {
grm_lock = true;
for (int i = 0; i < series_count; i++) { // clean current data, copy kept references
if (SERIES(i)) g_slist_free_full(SERIES(i), g_free);
SERIES(i) = KEPT_SERIES(i); SERIES_LEN(i) = KEPT_SERIES_LEN(i);
KEPT_SERIES_LEN(i) = 0; KEPT_SERIES(i) = NULL;
}
grm_lock = false;
}
inline void series_min_no(int number) { if (number > series_no) series_no = number; }
void series_reg_on_scale(GtkWidget *widget) {
if (GTK_IS_WIDGET(widget)) on_scale_list = g_slist_append(on_scale_list, widget);
}