[Unbound-users] Using libunbound from other languages
Phil Pennock
unbound-users+phil at spodhuis.org
Mon Jul 22 22:12:31 UTC 2013
On 2013-07-22 at 16:43 +0000, Miek Gieben wrote:
> [ Quoting <unbound-users+phil at spodhu> in "Re: [Unbound-users] Using libunboun..." ]
> > On 2013-07-22 at 10:32 +0000, Miek Gieben wrote:
> > > In this case I'm talking about using libunbound in Go and the locking issues
> > > that can occur with wrt to the crypto library that is used.
> > >
> > > In Go you do not have control over the amount of OS threads the runtime uses.
> > > Go uses goroutines and N of those routines are mapped to an OS thread at any moment
> > > in time.
> >
> > For this sort of scenario, you want Go's runtime.LockOSThread().
>
> Hmmmm, that would certainly help (and maybe hurt performance), but then I still
> don't have the proper thread locking in place....
You don't need it. You create a go-routine which uses channels for
asking for some DNS and getting the response back. Something like this
(untested):
type ResolveResult struct {
// whatever
Error error
}
type ResolveResultAndError struct {
Result *ResolveResult
Error error
}
type ResolveRequest struct {
Label string
DNSType string
Response chan ResolveResult
}
var GlobalResolver chan *ResolveRequest
func QueryDNS(label, typ string) (ResolveResult, error) {
inbox := make(chan ResolveResultAndError, 1)
GlobalResolver <- &ResolveRequest{
Label: label,
DNSType: type,
Response: inbox,
}
response := <-inbox
if response.Error != nil {
return nil, response.Error
}
return response.Result, nil
}
func InitDNS() {
GlobalResolver := make(chan *ResolveRequest, 10)
oneResolverThread := func() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// do Unbound setup
for {
switch {
case req := <-GlobalResolver:
// initiate request into Unbound
case resp := <-somethingGettingUnboundResponses
// send an result/error combo back down req.Response
}
}
}
go oneResolverThread() // repeat N times (see below)
}
You can then have a pool of Unbound clients, for as many concurrent
resolver OS threads as you want, all reading from the same
GlobalResolver channel, giving you automatic load-balancing across the
resolver threads. The response goes back to the inbox supplied. If the
Unbound API is being used synchronously, then you don't even have the
inner switch in the routine, just get the client request, handle it,
respond.
Synchronous with N OS threads (no Go switch) and C.ub_resolve() should
get things going, since the callbacks for async will basically need to
be handled carefully, since if memory serves Go doesn't expose channel
write to the C layer. Or am I wrong?
-Phil
More information about the Unbound-users
mailing list