make the stats collection thread-safe

remotes/origin/2.0
Richard Fuchs 13 years ago
parent c19b99903c
commit 95d9de7bc4

@ -50,8 +50,10 @@ struct callmaster {
u_int16_t lastport;
BIT_ARRAY_DECLARE(ports_used, 0x10000);
struct stats statsps;
struct stats stats;
mutex_t statspslock;
struct stats statsps; /* per second stats, running timer */
mutex_t statslock;
struct stats stats; /* copied from statsps once a second */
struct poller *poller;
pcre *info_re;
@ -213,7 +215,9 @@ static int stream_packet(struct streamrelay *r, char *b, int l, struct sockaddr_
LOG_PARAMS_C(c), r->localport, addr, ntohs(fsin->sin6_port));
r->stats.errors++;
mutex_unlock(&cs->lock);
mutex_lock(&m->statspslock);
m->statsps.errors++;
mutex_unlock(&m->statspslock);
return 0;
}
@ -318,7 +322,9 @@ forward:
if (ret == -1) {
r->stats.errors++;
mutex_unlock(&cs->lock);
mutex_lock(&m->statspslock);
m->statsps.errors++;
mutex_unlock(&m->statspslock);
return -1;
}
@ -327,8 +333,10 @@ drop:
r->stats.bytes += l;
r->last = poller_now;
mutex_unlock(&cs->lock);
mutex_lock(&m->statspslock);
m->statsps.packets++;
m->statsps.bytes += l;
mutex_unlock(&m->statspslock);
return 0;
}
@ -466,6 +474,7 @@ struct iterator_helper {
};
/* called with callmaster->hashlock held */
static void call_timer_iterator(void *key, void *val, void *ptr) {
struct call *c = val;
struct iterator_helper *hlp = ptr;
@ -493,6 +502,7 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
for (j = 0; j < 2; j++) {
sr = &p->rtps[j];
hlp->ports[sr->localport] = sr;
obj_hold(cs);
check = cm->conf.timeout;
if (!sr->peer.port)
@ -575,8 +585,12 @@ next:
d = 0; \
else \
d = ke->stats.x - sr->kstats.x; \
mutex_lock(&cs->lock); \
sr->stats.x += d; \
mutex_unlock(&cs->lock); \
mutex_lock(&m->statspslock); \
m->statsps.x += d; \
mutex_unlock(&m->statspslock); \
} while (0)
static void callmaster_timer(void *ptr) {
struct callmaster *m = ptr;
@ -586,6 +600,8 @@ static void callmaster_timer(void *ptr) {
struct mediaproxy_list_entry *ke;
struct streamrelay *sr;
u_int64_t d;
struct stats tmpstats;
struct callstream *cs;
ZERO(hlp);
@ -593,31 +609,42 @@ static void callmaster_timer(void *ptr) {
g_hash_table_foreach(m->callhash, call_timer_iterator, &hlp);
rwlock_unlock_r(&m->hashlock);
memcpy(&m->stats, &m->statsps, sizeof(m->stats));
mutex_lock(&m->statspslock);
memcpy(&tmpstats, &m->statsps, sizeof(tmpstats));
ZERO(m->statsps);
mutex_unlock(&m->statspslock);
mutex_lock(&m->statslock);
memcpy(&m->stats, &tmpstats, sizeof(m->stats));
mutex_unlock(&m->statslock);
i = (m->conf.kernelid != -1) ? kernel_list(m->conf.kernelid) : NULL;
while (i) {
ke = i->data;
cs = NULL;
sr = hlp.ports[ke->target.target_port];
if (!sr)
goto next;
cs = sr->up->up;
DS(packets);
DS(bytes);
DS(errors);
mutex_lock(&cs->lock);
if (ke->stats.packets != sr->kstats.packets)
sr->last = poller_now;
sr->kstats.packets = ke->stats.packets;
sr->kstats.bytes = ke->stats.bytes;
sr->kstats.errors = ke->stats.errors;
mutex_unlock(&cs->lock);
next:
g_slice_free1(sizeof(*ke), ke);
i = g_list_delete_link(i, i);
if (cs)
obj_put(cs);
}
if (m->conf.b2b_url)
@ -1793,12 +1820,18 @@ next:
}
void calls_status(struct callmaster *m, struct control_stream *s) {
struct stats st;
mutex_lock(&m->statslock);
st = m->stats;
mutex_unlock(&m->statslock);
rwlock_lock_r(&m->hashlock);
control_stream_printf(s, "proxy %u %llu/%llu/%llu\n",
g_hash_table_size(m->callhash),
(long long unsigned int) m->stats.bytes,
(long long unsigned int) m->stats.bytes - m->stats.errors,
(long long unsigned int) m->stats.bytes * 2 - m->stats.errors);
(long long unsigned int) st.bytes,
(long long unsigned int) st.bytes - st.errors,
(long long unsigned int) st.bytes * 2 - st.errors);
g_hash_table_foreach(m->callhash, call_status_iterator, s);
rwlock_unlock_r(&m->hashlock);

Loading…
Cancel
Save