Question about integrating udns in Ruby EventMachine

Iñaki Baz Castillo ibc at aliax.net
Wed Feb 9 01:59:38 MSK 2011


2011/2/8 Michael Tokarev <mjt at tls.msk.ru>:

> I don't know which code should be ruby and which
> should be C.  Ruby is able to call C code, and
> C code - probably - is able to call Ruby code, but
> I'm not sure.

Yes, in C code you can call methods of Ruby objects :)


> 1. You submit a first query to udns.  It calls the callback routine (timer_fn above) with zero timeout, to mean "queue the timer event right at next main loop cycle", or "queue this timer to fire right after now".

Question: couldn't dns_timeout() be called right "now" rather than in
the very next loop cycle? which is the difference? (assuming I don't
need to run more code after calling dns_submit_xxx). This is:

void timer_fn(ctx, int timeout, timer) {
 if (!ctx)
    EventMachine::DestroyTimer(timer);
 else if (timeout < 0)
    EventMachine::StopTimer(timer);
 else if (timeout == 0)
    dns_timeouts();
 else
    EventMachine::StartTimer(timer, timeout, dns_timeouts);
}



> So if you can't hook into the pre-poll() point, you
> should have ability to use timers in a way similar
> to above, and this is the alternative designed especially
> for this case - clean and more or less understandable.
>
> Or I hope anyway... ;)

Thanks Michael. But the behaviour you have described is exactly what
I've implemented (now improved) without using dns_set_tmcbck(). Let me
comment after each of your above steps (note: at least in my system
DNS retransmissions occur after 4 and 8 seconds instead of 2 and 4 as
you describe):



> 1. You submit a first query to udns.  It calls the callback routine (timer_fn above) with zero timeout, to mean "queue the timer event right at next main loop cycle", or "queue this timer to fire right after now".

I sumbit the first query to udns, and invoke my custom Ruby function
set_timeout(). This function manages a EventMachine timer.

set_timeout() calls dns_timeouts() so the DNS request is sent.
set_timeouts() returned 4, so the EventMachine timer is set to fire
after 4 seconds. This is, after 4 seconds EventMachine will  call
set_timeout() again.

The control comes back to EventMachine.




> 2. When this "after now" happens, EventMachine calls the provided callback routine, which is dns_timeouts().  udns executes your query by sending appropriate UDP packet.

In my case dns_timeouts() was called in step 1, right after calling
dns_submit_xxxx.  I see no difference, maybe I miss something.


> 3. now udns has a 2-second timeout to wait for the reply (the control is still in the dns_timeouts() routine).
udns calls the timer callback (timer_fn above) again, now with "2" as
the timeout value - it means "call my
dns_timeouts() routine after 2 seconds".

In my case dns_timeout() returned 4 (and not 2) so the timer was
already set (in step 1) to fire after 4 seconds.


> 4. your timer_fn() renews the timer with EventMachine, to fire after 2 seconds.

Already in step 1.


> 5. Now we've one of two choices: either the nameserver responds, in which case dns_ioevent() will be called
and udns will cancel the 2-second timer by calling the same timer_fn
routine again with timeout=-1;

In this case my solution is worse as upon receipt of the DNS response
(dns_ioevent() is called) I don't stop the EventMachine timer. Instead
it will fire after ~4 seconds (if the DNS reply was instant). When it
fires it invokes my Ruby function "set_timeout" which runs
dns_timeouts, gets -1 so stops the timer. Less efficient, right.


> or, in case there will be no reply, EventMachine will fire dns_timeouts() after 2sec delay, and in that case dns_timeouts() will send another query, and call your timer_fn with timeout=4 to fire it after 4 seconds.

In my case my EventMachine timer expires after 4 seconds (rather than
2) and incokes set_timeouts() which calls dns_timeouts, gets 8 seconds
and set the timer to fire after 8 seconds.


> And so on.
> When you submit more queries, this timer will be set and reset multiple times, according to internal udns logic.

Same here :)


Indeed you solution is cleaner so I'll try to implement it :)


Thanks a lot!

-- 
Iñaki Baz Castillo
<ibc at aliax.net>


More information about the udns mailing list