ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/EV-ADNS/ADNS.xs
(Generate patch)

Comparing cvsroot/EV-ADNS/ADNS.xs (file contents):
Revision 1.6 by root, Sat Dec 1 20:52:30 2007 UTC vs.
Revision 1.16 by root, Thu Dec 20 07:13:36 2007 UTC

5#include <poll.h> 5#include <poll.h>
6#include <adns.h> 6#include <adns.h>
7 7
8#include "EVAPI.h" 8#include "EVAPI.h"
9 9
10static HV *stash; 10static struct pollfd *fds;
11static adns_state ads; 11static int nfd, mfd;
12static ev_io *iow;
13static ev_timer tw;
14static ev_idle iw;
15static ev_prepare pw;
16static struct timeval tv_now;
17static int outstanding;
18
19static void
20outstanding_inc (adns_state ads)
21{
22 if (!outstanding++)
23 ev_prepare_start (EV_DEFAULT, &pw);
24}
25
26static void
27outstanding_dec (adns_state ads)
28{
29 --outstanding;
30}
12 31
13struct ctx 32struct ctx
14{ 33{
15 SV *self; 34 SV *self;
35 adns_state ads;
16 adns_query query; 36 adns_query query;
17 SV *cb; 37 SV *cb;
18}; 38};
19 39
20static SV * 40static SV *
26 46
27 return newRV_noinc ((SV *)av); 47 return newRV_noinc ((SV *)av);
28} 48}
29 49
30static void 50static void
31process () 51process (adns_state ads)
32{ 52{
33 dSP; 53 dSP;
34 54
35 for (;;) 55 for (;;)
36 { 56 {
45 if (r) 65 if (r)
46 break; 66 break;
47 67
48 c = (struct ctx *)ctx; 68 c = (struct ctx *)ctx;
49 cb = c->cb; 69 cb = c->cb;
50 c->cb = 0; 70 c->cb = 0; outstanding_dec (ads);
51 ev_unref ();
52 SvREFCNT_dec (c->self); 71 SvREFCNT_dec (c->self);
53 printf ("refrefclr\n"); 72
73 assert (cb);
54 74
55 PUSHMARK (SP); 75 PUSHMARK (SP);
56 76
57 EXTEND (SP, a->nrrs + 2); 77 EXTEND (SP, a->nrrs + 2);
58 PUSHs (sv_2mortal (newSViv (a->status))); 78 PUSHs (sv_2mortal (newSViv (a->status)));
70 case adns_r_ptr_raw: 90 case adns_r_ptr_raw:
71 sv = newSVpv (a->rrs.str [i], 0); 91 sv = newSVpv (a->rrs.str [i], 0);
72 break; 92 break;
73 93
74 case adns_r_txt: 94 case adns_r_txt:
75 sv = newSVpvn (a->rrs.manyistr [i]->str, a->rrs.manyistr [i]->i); 95 {
96 AV *av = newAV ();
97 adns_rr_intstr *rr = a->rrs.manyistr [i];
98
99 while (rr->str)
100 {
101 av_push (av, newSVpvn (rr->str, rr->i));
102 ++rr;
103 }
104
105 sv = newRV_noinc ((SV *)av);
106 }
76 break; 107 break;
77 108
78 case adns_r_a: 109 case adns_r_a:
79 sv = newSVpv (inet_ntoa (a->rrs.inaddr [i]), 0); 110 sv = newSVpv (inet_ntoa (a->rrs.inaddr [i]), 0);
80 break; 111 break;
85 116
86 case adns_r_hinfo: 117 case adns_r_hinfo:
87 { 118 {
88 /* untested */ 119 /* untested */
89 AV *av = newAV (); 120 AV *av = newAV ();
90 sv = newRV_noinc ((SV *)av);
91 adns_rr_intstrpair *rr = a->rrs.intstrpair + i; 121 adns_rr_intstrpair *rr = a->rrs.intstrpair + i;
92 122
93 av_push (av, newSVpvn (rr->array [0].str, rr->array [0].i)); 123 av_push (av, newSVpvn (rr->array [0].str, rr->array [0].i));
94 av_push (av, newSVpvn (rr->array [1].str, rr->array [1].i)); 124 av_push (av, newSVpvn (rr->array [1].str, rr->array [1].i));
125
126 sv = newRV_noinc ((SV *)av);
95 } 127 }
96 break; 128 break;
97 129
98 case adns_r_rp: 130 case adns_r_rp:
99 case adns_r_rp_raw: 131 case adns_r_rp_raw:
100 { 132 {
101 /* untested */ 133 /* untested */
102 AV *av = newAV (); 134 AV *av = newAV ();
103 sv = newRV_noinc ((SV *)av);
104 adns_rr_strpair *rr = a->rrs.strpair + i; 135 adns_rr_strpair *rr = a->rrs.strpair + i;
105 136
106 av_push (av, newSVpv (rr->array [0], 0)); 137 av_push (av, newSVpv (rr->array [0], 0));
107 av_push (av, newSVpv (rr->array [1], 0)); 138 av_push (av, newSVpv (rr->array [1], 0));
139
140 sv = newRV_noinc ((SV *)av);
108 } 141 }
109 break; 142 break;
110 143
111 case adns_r_mx: 144 case adns_r_mx:
112 { 145 {
113 AV *av = newAV (); 146 AV *av = newAV ();
114 sv = newRV_noinc ((SV *)av);
115 adns_rr_inthostaddr *rr = a->rrs.inthostaddr + i; 147 adns_rr_inthostaddr *rr = a->rrs.inthostaddr + i;
116 148
117 av_push (av, newSViv (rr->i)); 149 av_push (av, newSViv (rr->i));
118 av_push (av, ha2sv (&rr->ha)); 150 av_push (av, ha2sv (&rr->ha));
151
152 sv = newRV_noinc ((SV *)av);
119 } 153 }
120 break; 154 break;
121 155
122 case adns_r_mx_raw: 156 case adns_r_mx_raw:
123 { 157 {
124 AV *av = newAV (); 158 AV *av = newAV ();
125 sv = newRV_noinc ((SV *)av);
126 adns_rr_intstr *rr = a->rrs.intstr + i; 159 adns_rr_intstr *rr = a->rrs.intstr + i;
127 160
128 av_push (av, newSViv (rr->i)); 161 av_push (av, newSViv (rr->i));
129 av_push (av, newSVpv (rr->str, 0)); 162 av_push (av, newSVpv (rr->str, 0));
163
164 sv = newRV_noinc ((SV *)av);
130 } 165 }
131 break; 166 break;
132 167
133 case adns_r_soa: 168 case adns_r_soa:
134 case adns_r_soa_raw: 169 case adns_r_soa_raw:
135 { 170 {
136 AV *av = newAV (); 171 AV *av = newAV ();
137 sv = newRV_noinc ((SV *)av);
138 adns_rr_soa *rr = a->rrs.soa + i; 172 adns_rr_soa *rr = a->rrs.soa + i;
139 173
140 av_push (av, newSVpv (rr->mname, 0)); 174 av_push (av, newSVpv (rr->mname, 0));
141 av_push (av, newSVpv (rr->rname, 0)); 175 av_push (av, newSVpv (rr->rname, 0));
142 av_push (av, newSVuv (rr->serial)); 176 av_push (av, newSVuv (rr->serial));
143 av_push (av, newSVuv (rr->refresh)); 177 av_push (av, newSVuv (rr->refresh));
144 av_push (av, newSVuv (rr->retry)); 178 av_push (av, newSVuv (rr->retry));
145 av_push (av, newSVuv (rr->expire)); 179 av_push (av, newSVuv (rr->expire));
146 av_push (av, newSVuv (rr->minimum)); 180 av_push (av, newSVuv (rr->minimum));
181
182 sv = newRV_noinc ((SV *)av);
147 } 183 }
148 break; 184 break;
149 185
150 case adns_r_srv_raw: 186 case adns_r_srv_raw:
151 { 187 {
152 AV *av = newAV (); 188 AV *av = newAV ();
153 sv = newRV_noinc ((SV *)av);
154 adns_rr_srvraw *rr = a->rrs.srvraw + i; 189 adns_rr_srvraw *rr = a->rrs.srvraw + i;
155 190
156 av_push (av, newSViv (rr->priority)); 191 av_push (av, newSViv (rr->priority));
157 av_push (av, newSViv (rr->weight)); 192 av_push (av, newSViv (rr->weight));
158 av_push (av, newSViv (rr->port)); 193 av_push (av, newSViv (rr->port));
159 av_push (av, newSVpv (rr->host, 0)); 194 av_push (av, newSVpv (rr->host, 0));
195
196 sv = newRV_noinc ((SV *)av);
160 } 197 }
161 break; 198 break;
162 199
163 case adns_r_srv: 200 case adns_r_srv:
164 { 201 {
165 AV *av = newAV (); 202 AV *av = newAV ();
166 sv = newRV_noinc ((SV *)av);
167 adns_rr_srvha *rr = a->rrs.srvha + i; 203 adns_rr_srvha *rr = a->rrs.srvha + i;
168 204
169 av_push (av, newSViv (rr->priority)); 205 av_push (av, newSViv (rr->priority));
170 av_push (av, newSViv (rr->weight)); 206 av_push (av, newSViv (rr->weight));
171 av_push (av, newSViv (rr->port)); 207 av_push (av, newSViv (rr->port));
172 av_push (av, ha2sv (&rr->ha)); 208 av_push (av, ha2sv (&rr->ha));
209
210 sv = newRV_noinc ((SV *)av);
173 } 211 }
174 break; 212 break;
175 213
176 case adns_r_unknown: 214 case adns_r_unknown:
177 sv = newSVpvn (a->rrs.byteblock [i].data, a->rrs.byteblock [i].len); 215 sv = newSVpvn (a->rrs.byteblock [i].data, a->rrs.byteblock [i].len);
190 228
191 PUTBACK; 229 PUTBACK;
192 call_sv (cb, G_VOID | G_DISCARD | G_EVAL); 230 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
193 SPAGAIN; 231 SPAGAIN;
194 232
233 if (SvTRUE (ERRSV))
234 warn ("%s", SvPV_nolen (ERRSV));
235
195 SvREFCNT_dec (cb); 236 SvREFCNT_dec (cb);
196 } 237 }
197} 238}
198 239
199static struct pollfd *fds;
200static int nfd, mfd;
201static ev_io *iow;
202static ev_timer tw;
203static ev_prepare prepare_ev;
204static struct timeval tv_now;
205
206static void 240static void
207update_now (EV_P) 241update_now (EV_P)
208{ 242{
209 ev_tstamp t = ev_now (); 243 ev_tstamp t = ev_now (EV_A);
210 244
211 tv_now.tv_sec = (long)t; 245 tv_now.tv_sec = (long)t;
212 tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.tv_sec) * 1e-6); 246 tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.tv_sec) * 1e6);
247}
248
249static void
250idle_cb (EV_P_ ev_idle *w, int revents)
251{
252 ev_idle_stop (EV_A, w);
213} 253}
214 254
215static void 255static void
216timer_cb (EV_P_ ev_timer *w, int revents) 256timer_cb (EV_P_ ev_timer *w, int revents)
217{ 257{
258 adns_state ads = (adns_state)w->data;
259 update_now (EV_A);
260
261 adns_processtimeouts (ads, &tv_now);
218} 262}
219 263
220static void 264static void
221io_cb (EV_P_ ev_io *w, int revents) 265io_cb (EV_P_ ev_io *w, int revents)
222{ 266{
267 adns_state ads = (adns_state)w->data;
223 update_now (EV_A); 268 update_now (EV_A);
224 269
225 if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now); 270 if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now);
226 if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now); 271 if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
227} 272}
230static void 275static void
231prepare_cb (EV_P_ ev_prepare *w, int revents) 276prepare_cb (EV_P_ ev_prepare *w, int revents)
232{ 277{
233 int i; 278 int i;
234 int timeout = 3600000; 279 int timeout = 3600000;
280 adns_state ads = (adns_state)w->data;
235 281
236 if (ev_is_active (&tw)) 282 if (ev_is_active (&tw))
283 ev_timer_stop (EV_A, &tw);
284
285 if (ev_is_active (&iw))
286 ev_idle_stop (EV_A, &iw);
287
288 for (i = 0; i < nfd; ++i)
289 ev_io_stop (EV_A, iow + i);
290
291 process (ads);
292
293 if (!outstanding)
237 { 294 {
238 ev_ref ();
239 ev_timer_stop (EV_A_ &tw); 295 ev_prepare_stop (EV_A, w);
296 return;
240 } 297 }
241
242 for (i = 0; i < nfd; ++i)
243 {
244 ev_ref ();
245 ev_io_stop (EV_A_ iow + i);
246 }
247
248 process ();
249 298
250 update_now (EV_A); 299 update_now (EV_A);
251 300
252 nfd = mfd; 301 nfd = mfd;
253 302
254 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now)) 303 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now))
255 { 304 {
256 mfd = nfd; 305 mfd = nfd;
257 306
307 free (iow); iow = malloc (mfd * sizeof (ev_io));
258 free (iow); iow = malloc (mfd * sizeof (struct pollfd)); 308 free (fds); fds = malloc (mfd * sizeof (struct pollfd));
259 free (fds); fds = malloc (mfd * sizeof (ev_io));
260 } 309 }
261 310
262 ev_timer_set (&tw, timeout * 1e-3, 0.); 311 ev_timer_set (&tw, timeout * 1e-3, 0.);
263 ev_timer_start (EV_A_ &tw); 312 ev_timer_start (EV_A, &tw);
264 ev_unref ();
265 313
266 // create one ev_io per pollfd 314 // create one ev_io per pollfd
267 for (i = 0; i < nfd; ++i) 315 for (i = 0; i < nfd; ++i)
268 { 316 {
317 ev_io *w = iow + i;
318
269 ev_io_init (iow + i, io_cb, fds [i].fd, 319 ev_io_init (w, io_cb, fds [i].fd,
270 ((fds [i].events & POLLIN ? EV_READ : 0) 320 ((fds [i].events & POLLIN ? EV_READ : 0)
271 | (fds [i].events & POLLOUT ? EV_WRITE : 0))); 321 | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
272 322
323 w->data = (void *)ads;
273 ev_io_start (EV_A_ iow + i); 324 ev_io_start (EV_A, w);
274 ev_unref ();
275 } 325 }
276} 326}
327
328static HV *stash;
329static adns_state ads;
277 330
278MODULE = EV::ADNS PACKAGE = EV::ADNS 331MODULE = EV::ADNS PACKAGE = EV::ADNS
279 332
280PROTOTYPES: ENABLE 333PROTOTYPES: ENABLE
281 334
369 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 422 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
370 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 423 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
371 424
372 I_EV_API ("EV::ADNS"); 425 I_EV_API ("EV::ADNS");
373 426
374 ev_prepare_init (&prepare_ev, prepare_cb); ev_prepare_start (EV_DEFAULT_ &prepare_ev); 427 adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
375 ev_unref ();
376 428
429 ev_prepare_init (&pw, prepare_cb);
430 pw.data = (void *)ads;
431
432 ev_init (&iw, idle_cb); ev_set_priority (&iw, EV_MINPRI);
433 iw.data = (void *)ads;
377 ev_init (&tw, timer_cb); 434 ev_init (&tw, timer_cb);
378 435 tw.data = (void *)ads;
379 adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
380} 436}
381 437
382void submit (char *owner, int type, int flags, SV *cb) 438void submit (char *owner, int type, int flags, SV *cb)
383 PPCODE: 439 PPCODE:
384{ 440{
385 SV *csv = NEWSV (0, sizeof (struct ctx)); 441 SV *csv = NEWSV (0, sizeof (struct ctx));
386 struct ctx *c = (struct ctx *)SvPVX (csv); 442 struct ctx *c = (struct ctx *)SvPVX (csv);
387 int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query); 443 int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query);
444
445 outstanding_inc (ads);
388 446
389 if (r) 447 if (r)
390 { 448 {
391 SvREFCNT_dec (csv); 449 SvREFCNT_dec (csv);
392 errno = r; 450 errno = r;
393 XSRETURN_EMPTY; 451 XSRETURN_EMPTY;
394 } 452 }
395 else 453 else
396 { 454 {
397 ev_ref ();
398 SvPOK_only (csv); 455 SvPOK_only (csv);
399 SvCUR_set (csv, sizeof (struct ctx)); 456 SvCUR_set (csv, sizeof (struct ctx));
400 457
401 c->self = csv; 458 c->self = csv;
402 c->cb = newSVsv (cb); 459 c->cb = newSVsv (cb);
460 c->ads = ads;
461
462 if (!ev_is_active (&iw))
463 ev_idle_start (EV_DEFAULT, &iw);
403 464
404 if (GIMME_V != G_VOID) 465 if (GIMME_V != G_VOID)
405 { 466 {
406 csv = sv_2mortal (newRV_inc (csv)); 467 csv = sv_2mortal (newRV_inc (csv));
407 sv_bless (csv, stash); 468 sv_bless (csv, stash);
415 cancel = 1 476 cancel = 1
416 CODE: 477 CODE:
417{ 478{
418 struct ctx *c; 479 struct ctx *c;
419 480
420 printf ("destroy\n");
421 if (!(SvROK (req) && SvOBJECT (SvRV (req)) 481 if (!(SvROK (req) && SvOBJECT (SvRV (req))
422 && (SvSTASH (SvRV (req)) == stash))) 482 && (SvSTASH (SvRV (req)) == stash)))
423 croak ("object is not of type EV::ADNS"); 483 croak ("object is not of type EV::ADNS");
424 484
425 c = (struct ctx *)SvPVX (SvRV (req)); 485 c = (struct ctx *)SvPVX (SvRV (req));
426 486
427 if (c->cb) 487 if (c->cb)
428 { 488 {
429 ev_unref ();
430 SvREFCNT_dec (c->cb); 489 SvREFCNT_dec (c->cb);
431 c->cb = 0; 490 c->cb = 0; outstanding_dec (c->ads);
432 adns_cancel (c->query); 491 adns_cancel (c->query);
433 SvREFCNT_dec (c->self); 492 SvREFCNT_dec (c->self);
434 printf ("refrefcl2\n");
435 } 493 }
436} 494}
437 495
438 496
439 497

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines