--- AnyEvent-FastPing/FastPing.xs 2011/02/01 04:06:24 1.11 +++ AnyEvent-FastPing/FastPing.xs 2011/02/02 19:26:45 1.12 @@ -112,7 +112,7 @@ typedef struct { tstamp next; - double interval; + tstamp interval; int addrlen; addr_tt lo, hi; /* only if !addrcnt */ @@ -126,8 +126,11 @@ RANGE **ranges; int rangecnt, rangemax; + tstamp next; tstamp interval; + tstamp maxrtt; + uint16_t magic1; uint16_t magic2; uint16_t magic3; @@ -359,31 +362,32 @@ memset (&pkt, 0, sizeof (pkt)); - tstamp now = NOW (); - tstamp next = now; + tstamp now = NOW (); + + pkt.code = 0; + pkt.id = self->magic1; + pkt.seq = self->magic2; + pkt.magic = self->magic3; + pkt.pinger = self->id; - pkt.code = 0; - pkt.id = self->magic1; - pkt.seq = self->magic2; - pkt.magic = self->magic3; - pkt.pinger = self->id; + if (self->next < now) + self->next = now; while (self->rangecnt) { RANGE *range = self->ranges [0]; - int n, k; // ranges [0] is always the next range to ping tstamp wait = range->next - now; // compare with the global frequency limit { - tstamp diff = next - now; + tstamp diff = self->next - now; if (wait < diff) - wait = diff; - else if (range) - next = range->next; + wait = diff; // global rate limit overrides + else + self->next = range->next; // fast forward } if (wait > 0.) @@ -399,14 +403,12 @@ range_free (range); } else - { - range->next = next; - range->next += range->interval; - } + range->next = self->next + range->interval; downheap (self); - next += self->interval; + self->next += self->interval; + now = NOW (); } ssleep (self->maxrtt); @@ -484,6 +486,7 @@ pingers [self->id] = self; self->recvcb = &PL_sv_undef; + self->next = 0.; self->interval = MIN_INTERVAL; self->maxrtt = 0.5; self->rangemax = 16; @@ -645,6 +648,10 @@ sv_setiv (get_sv ("AnyEvent::FastPing::ICMP6_FD", 1), icmp6_fd); } +#define NOT_RUNNING \ + if (self->running) \ + croak ("AnyEvent::FastPing object has been started - you have to sotp t first before calling this method, caught"); + MODULE = AnyEvent::FastPing PACKAGE = AnyEvent::FastPing PREFIX = pinger_ BOOT: @@ -750,6 +757,7 @@ { SV *pv = NEWSV (0, sizeof (PINGER)); PINGER *self = (PINGER *)SvPVX (pv); + SvPOK_only (pv); XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), gv_stashpv (SvPVutf8_nolen (klass), 1)))); pinger_init (self); @@ -783,21 +791,30 @@ void interval (PINGER *self, NV interval) CODE: + NOT_RUNNING; self->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL; void max_rtt (PINGER *self, NV maxrtt) CODE: + NOT_RUNNING; self->maxrtt = maxrtt; void -add_range (PINGER *self, SV *lo_, SV *hi_, NV interval) +on_recv (PINGER *self, SV *cb) + CODE: + SvREFCNT_dec (self->recvcb); + self->recvcb = newSVsv (cb); + +void +add_range (PINGER *self, SV *lo_, SV *hi_, NV interval = 0) CODE: { STRLEN lo_len, hi_len; char *lo = SvPVbyte (lo_, lo_len); char *hi = SvPVbyte (hi_, hi_len); RANGE *range; + NOT_RUNNING; if (lo_len != hi_len || (lo_len != 4 && lo_len != 16)) croak ("AnyEvent::FastPing::add_range address range must be specified as two binary IPv4 or IPv6 addresses"); @@ -821,17 +838,18 @@ } void -add_hosts (PINGER *self, SV *addrs, NV interval) +add_hosts (PINGER *self, SV *addrs, NV interval = 0, UV interleave = 1) CODE: { AV *av; - int i; + int i, j, k; int cnt; int addrlen; RANGE *range; + NOT_RUNNING; if (!SvROK (addrs) || SvTYPE (SvRV (addrs)) != SVt_PVAV) - croak ("AnyEvent::FastPing::add_hosst expects an arrayref with binary IPv4 or IPv6 addresses"); + croak ("AnyEvent::FastPing::add_hosts expects an arrayref with binary IPv4 or IPv6 addresses"); av = (AV *)SvRV (addrs); cnt = av_len (av) + 1; @@ -859,17 +877,16 @@ range->addrlen = addrlen; range->addrcnt = cnt; - for (i = cnt; i--; ) - memcpy ((uint8_t *)(range + 1) + (cnt - 1 - i) * addrlen, - SvPVbyte_nolen (*av_fetch (av, i, 1)), - addrlen); + if (interleave == 0) + interleave = cnt <= 256 * 256 ? 256 : (int)sqrtf (cnt); + + k = cnt; + for (j = 0; j < interleave; ++j) + for (i = j; i < cnt; i += interleave) + memcpy ((uint8_t *)(range + 1) + --k * addrlen, + SvPVbyte_nolen (*av_fetch (av, i, 1)), + addrlen); pinger_add_range (self, range); } -void -on_recv (PINGER *self, SV *cb) - CODE: - SvREFCNT_dec (self->recvcb); - self->recvcb = newSVsv (cb); -