ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FastPing.xs
(Generate patch)

Comparing AnyEvent-FastPing/FastPing.xs (file contents):
Revision 1.11 by root, Tue Feb 1 04:06:24 2011 UTC vs.
Revision 1.12 by root, Wed Feb 2 19:26:45 2011 UTC

110typedef uint8_t addr_tt[16]; 110typedef uint8_t addr_tt[16];
111 111
112typedef struct 112typedef struct
113{ 113{
114 tstamp next; 114 tstamp next;
115 double interval; 115 tstamp interval;
116 int addrlen; 116 int addrlen;
117 117
118 addr_tt lo, hi; /* only if !addrcnt */ 118 addr_tt lo, hi; /* only if !addrcnt */
119 119
120 int addrcnt; 120 int addrcnt;
124typedef struct 124typedef struct
125{ 125{
126 RANGE **ranges; 126 RANGE **ranges;
127 int rangecnt, rangemax; 127 int rangecnt, rangemax;
128 128
129 tstamp next;
129 tstamp interval; 130 tstamp interval;
131
130 tstamp maxrtt; 132 tstamp maxrtt;
133
131 uint16_t magic1; 134 uint16_t magic1;
132 uint16_t magic2; 135 uint16_t magic2;
133 uint16_t magic3; 136 uint16_t magic3;
134 137
135 int id; 138 int id;
357 PINGER *self = (PINGER *)self_; 360 PINGER *self = (PINGER *)self_;
358 PKT pkt; 361 PKT pkt;
359 362
360 memset (&pkt, 0, sizeof (pkt)); 363 memset (&pkt, 0, sizeof (pkt));
361 364
362 tstamp now = NOW (); 365 tstamp now = NOW ();
363 tstamp next = now;
364 366
365 pkt.code = 0; 367 pkt.code = 0;
366 pkt.id = self->magic1; 368 pkt.id = self->magic1;
367 pkt.seq = self->magic2; 369 pkt.seq = self->magic2;
368 pkt.magic = self->magic3; 370 pkt.magic = self->magic3;
369 pkt.pinger = self->id; 371 pkt.pinger = self->id;
372
373 if (self->next < now)
374 self->next = now;
370 375
371 while (self->rangecnt) 376 while (self->rangecnt)
372 { 377 {
373 RANGE *range = self->ranges [0]; 378 RANGE *range = self->ranges [0];
374 int n, k;
375 379
376 // ranges [0] is always the next range to ping 380 // ranges [0] is always the next range to ping
377 tstamp wait = range->next - now; 381 tstamp wait = range->next - now;
378 382
379 // compare with the global frequency limit 383 // compare with the global frequency limit
380 { 384 {
381 tstamp diff = next - now; 385 tstamp diff = self->next - now;
382 386
383 if (wait < diff) 387 if (wait < diff)
384 wait = diff; 388 wait = diff; // global rate limit overrides
385 else if (range) 389 else
386 next = range->next; 390 self->next = range->next; // fast forward
387 } 391 }
388 392
389 if (wait > 0.) 393 if (wait > 0.)
390 ssleep (wait); 394 ssleep (wait);
391 395
397 { 401 {
398 self->ranges [0] = self->ranges [--self->rangecnt]; 402 self->ranges [0] = self->ranges [--self->rangecnt];
399 range_free (range); 403 range_free (range);
400 } 404 }
401 else 405 else
402 {
403 range->next = next;
404 range->next += range->interval; 406 range->next = self->next + range->interval;
405 }
406 407
407 downheap (self); 408 downheap (self);
408 409
409 next += self->interval; 410 self->next += self->interval;
411 now = NOW ();
410 } 412 }
411 413
412 ssleep (self->maxrtt); 414 ssleep (self->maxrtt);
413 415
414 { 416 {
482 } 484 }
483 485
484 pingers [self->id] = self; 486 pingers [self->id] = self;
485 487
486 self->recvcb = &PL_sv_undef; 488 self->recvcb = &PL_sv_undef;
489 self->next = 0.;
487 self->interval = MIN_INTERVAL; 490 self->interval = MIN_INTERVAL;
488 self->maxrtt = 0.5; 491 self->maxrtt = 0.5;
489 self->rangemax = 16; 492 self->rangemax = 16;
490 self->ranges = malloc (sizeof (self->ranges [0]) * self->rangemax); 493 self->ranges = malloc (sizeof (self->ranges [0]) * self->rangemax);
491} 494}
643 646
644 sv_setiv (get_sv ("AnyEvent::FastPing::ICMP4_FD", 1), icmp4_fd); 647 sv_setiv (get_sv ("AnyEvent::FastPing::ICMP4_FD", 1), icmp4_fd);
645 sv_setiv (get_sv ("AnyEvent::FastPing::ICMP6_FD", 1), icmp6_fd); 648 sv_setiv (get_sv ("AnyEvent::FastPing::ICMP6_FD", 1), icmp6_fd);
646} 649}
647 650
651#define NOT_RUNNING \
652 if (self->running) \
653 croak ("AnyEvent::FastPing object has been started - you have to sotp t first before calling this method, caught");
654
648MODULE = AnyEvent::FastPing PACKAGE = AnyEvent::FastPing PREFIX = pinger_ 655MODULE = AnyEvent::FastPing PACKAGE = AnyEvent::FastPing PREFIX = pinger_
649 656
650BOOT: 657BOOT:
651{ 658{
652 HV *stash = gv_stashpv ("AnyEvent::FastPing", 1); 659 HV *stash = gv_stashpv ("AnyEvent::FastPing", 1);
748_new (SV *klass, UV magic1, UV magic2, UV magic3) 755_new (SV *klass, UV magic1, UV magic2, UV magic3)
749 PPCODE: 756 PPCODE:
750{ 757{
751 SV *pv = NEWSV (0, sizeof (PINGER)); 758 SV *pv = NEWSV (0, sizeof (PINGER));
752 PINGER *self = (PINGER *)SvPVX (pv); 759 PINGER *self = (PINGER *)SvPVX (pv);
760
753 SvPOK_only (pv); 761 SvPOK_only (pv);
754 XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), gv_stashpv (SvPVutf8_nolen (klass), 1)))); 762 XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), gv_stashpv (SvPVutf8_nolen (klass), 1))));
755 pinger_init (self); 763 pinger_init (self);
756 self->magic1 = magic1; 764 self->magic1 = magic1;
757 self->magic2 = magic2; 765 self->magic2 = magic2;
781 pinger_stop (pingers [id]); 789 pinger_stop (pingers [id]);
782 790
783void 791void
784interval (PINGER *self, NV interval) 792interval (PINGER *self, NV interval)
785 CODE: 793 CODE:
794 NOT_RUNNING;
786 self->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL; 795 self->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL;
787 796
788void 797void
789max_rtt (PINGER *self, NV maxrtt) 798max_rtt (PINGER *self, NV maxrtt)
790 CODE: 799 CODE:
800 NOT_RUNNING;
791 self->maxrtt = maxrtt; 801 self->maxrtt = maxrtt;
792 802
793void 803void
804on_recv (PINGER *self, SV *cb)
805 CODE:
806 SvREFCNT_dec (self->recvcb);
807 self->recvcb = newSVsv (cb);
808
809void
794add_range (PINGER *self, SV *lo_, SV *hi_, NV interval) 810add_range (PINGER *self, SV *lo_, SV *hi_, NV interval = 0)
795 CODE: 811 CODE:
796{ 812{
797 STRLEN lo_len, hi_len; 813 STRLEN lo_len, hi_len;
798 char *lo = SvPVbyte (lo_, lo_len); 814 char *lo = SvPVbyte (lo_, lo_len);
799 char *hi = SvPVbyte (hi_, hi_len); 815 char *hi = SvPVbyte (hi_, hi_len);
800 RANGE *range; 816 RANGE *range;
817 NOT_RUNNING;
801 818
802 if (lo_len != hi_len || (lo_len != 4 && lo_len != 16)) 819 if (lo_len != hi_len || (lo_len != 4 && lo_len != 16))
803 croak ("AnyEvent::FastPing::add_range address range must be specified as two binary IPv4 or IPv6 addresses"); 820 croak ("AnyEvent::FastPing::add_range address range must be specified as two binary IPv4 or IPv6 addresses");
804 821
805 if (lo_len == 4 && icmp4_fd < 0) croak ("IPv4 support unavailable"); 822 if (lo_len == 4 && icmp4_fd < 0) croak ("IPv4 support unavailable");
819 836
820 pinger_add_range (self, range); 837 pinger_add_range (self, range);
821} 838}
822 839
823void 840void
824add_hosts (PINGER *self, SV *addrs, NV interval) 841add_hosts (PINGER *self, SV *addrs, NV interval = 0, UV interleave = 1)
825 CODE: 842 CODE:
826{ 843{
827 AV *av; 844 AV *av;
828 int i; 845 int i, j, k;
829 int cnt; 846 int cnt;
830 int addrlen; 847 int addrlen;
831 RANGE *range; 848 RANGE *range;
849 NOT_RUNNING;
832 850
833 if (!SvROK (addrs) || SvTYPE (SvRV (addrs)) != SVt_PVAV) 851 if (!SvROK (addrs) || SvTYPE (SvRV (addrs)) != SVt_PVAV)
834 croak ("AnyEvent::FastPing::add_hosst expects an arrayref with binary IPv4 or IPv6 addresses"); 852 croak ("AnyEvent::FastPing::add_hosts expects an arrayref with binary IPv4 or IPv6 addresses");
835 853
836 av = (AV *)SvRV (addrs); 854 av = (AV *)SvRV (addrs);
837 cnt = av_len (av) + 1; 855 cnt = av_len (av) + 1;
838 856
839 if (!cnt) 857 if (!cnt)
857 range->next = 0; 875 range->next = 0;
858 range->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL; 876 range->interval = interval > MIN_INTERVAL ? interval : MIN_INTERVAL;
859 range->addrlen = addrlen; 877 range->addrlen = addrlen;
860 range->addrcnt = cnt; 878 range->addrcnt = cnt;
861 879
862 for (i = cnt; i--; ) 880 if (interleave == 0)
881 interleave = cnt <= 256 * 256 ? 256 : (int)sqrtf (cnt);
882
883 k = cnt;
884 for (j = 0; j < interleave; ++j)
885 for (i = j; i < cnt; i += interleave)
863 memcpy ((uint8_t *)(range + 1) + (cnt - 1 - i) * addrlen, 886 memcpy ((uint8_t *)(range + 1) + --k * addrlen,
864 SvPVbyte_nolen (*av_fetch (av, i, 1)), 887 SvPVbyte_nolen (*av_fetch (av, i, 1)),
865 addrlen); 888 addrlen);
866 889
867 pinger_add_range (self, range); 890 pinger_add_range (self, range);
868} 891}
869 892
870void
871on_recv (PINGER *self, SV *cb)
872 CODE:
873 SvREFCNT_dec (self->recvcb);
874 self->recvcb = newSVsv (cb);
875

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines