[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Net::LDAP connection semantics problem and nested blocks.

Luke Daley

11/1/2006 2:21:00 AM

Hi,

I am working with the Net::LDAP library to communicate with active
directory. The connection semantics of that library are causing me
problems which I am trying to solve. The library was designed to
connect and then disconnect from the LDAP server before and after
each operation. I am running into a problem where the server is
refusing connections because of too many successive connections.

Some background....

I have a Net::LDAP subclass that among other things, supplies
credential and connection information to the parent on construction
based on a single key string that is given.

class MyLDAP < Net::LDAP

@cache = {}

def self.get(key)
if @cache.has_key? key
@cache[key]
else
@cache[key] = CortecsLDAP.new(key)
end
end

def initialize(key)
super self.connect_details_for_key(key)
end

def self.connect_details_for_key(key)
# Connect to DB and get details here relating to key
end

The caching business is because this it is common for 1000+ ldap
operations to happen in one execution so I thought I was being more
efficient in holding the connections open like that.

The semantics of Net::LDAP however open and close underling tcp
connection before and after each operation. Basically making my
caching obsolete. However, Net::LDAP provides the method open() at
the class and object level which takes a block and passes a Net::LDAP
object to the block, keeping its connection open for the duration of
the block. What I would like to do is be able to hold open all of the
objects in the cache for the duration of a block. This is probably
what I would want the interface to look like....

LDAPSession.open do | ldap_connection_cache |
my_ldap_instance = ldap_connection_cache.get('some_key')
my_other_ldap_instance = ldap_connection_cache.get('some_other_key')
end

The important thing here is that my_ldap_instance and
my_other_ldap_instance remain open for the whole time they are in the
block they are in. The only way to keep a Net::LDAP connection open
is to use the open() method described above and pass it a block.

I hope that makes sense to someone who can help.

Cheers.

-----------------------------
Luke Daley
http://www....
-----------------------------



2 Answers

Luke Daley

11/6/2006 12:32:00 AM

0


On 01/11/2006, at 3:11 PM, Francis Cianfrocca wrote:

> What LDAP operations are you performing here?

In the particular case when I hit the problem, it was an attribute
level modify operation. I realise my original post was extremely hard
to decipher, I was rather pressed for time when I put it together.

I have a script which consumes 'jobs' off a queue. One of the jobs
may be to update the name details for a particular user in domain a,
the next to update the phone number in domain b. Therefore opening
one connection using open() is not an option.

I have thought long and hard about this and I can't come up with a
solution. The only way for this to work the way I want would be to
have a flag that changes the connection model and maybe allows me to
specify when to open/close the underlying connection. However, I see
from the in code comments that it was an explicit design decision to
have the API work the way it does. I do understand the reason for
this, but it just doesn't suit my needs for this.

If this is something that you don't wish too change (quite
reasonable) I will go back to the other ruby ldap options.

On a side note, your ldap implementation performs very well compared
to the Perl net::ldap which I was surprised about. It may have been a
peculiarity of my environment, but when I moved to Perl to get the
task I needed done, there was a noticeable slow down in processing
large result sets compared to your ruby implementation.

Cheers.

-----------------------------
Luke Daley
http://www....
-----------------------------



Francis Cianfrocca

11/6/2006 1:26:00 PM

0

On 11/5/06, Luke Daley <ld@ldaley.com> wrote:
>
> On 01/11/2006, at 3:11 PM, Francis Cianfrocca wrote:
>
> > What LDAP operations are you performing here?
>
> In the particular case when I hit the problem, it was an attribute
> level modify operation. I realise my original post was extremely hard
> to decipher, I was rather pressed for time when I put it together.
>
> I have a script which consumes 'jobs' off a queue. One of the jobs
> may be to update the name details for a particular user in domain a,
> the next to update the phone number in domain b. Therefore opening
> one connection using open() is not an option.
>


In regard to the design decision in the library: it's essential to be
able to document and depend on the network behavior of Net::LDAP.
That's more important than that it obey one semantics or another. The
decision came from years of experience with the various
Michigan-derived C implementations, which try to wrap the connection
away from the API, which in turn leads to bizarre, hard-to-find bugs.

Why don't you put your queue consumer inside the Net::LDAP#open block
and let it run as long as it wants to? You can put multiple #open
calls on different threads if you have to connect to more than one
LDAP server. The only thing I would be concerned about is that the
LDAP servers may time out your connections, but you can manage that by
putting your own timeout in your Queue-query.