> On Mar 23, 2021, at 3:00 AM, Emmanuel Lécharny <elecha...@gmail.com> wrote:
> 
> 
> On 22/03/2021 19:41, Shawn McKinney wrote:
>>> On Mar 22, 2021, at 11:05 AM, Emmanuel Lécharny <elecha...@gmail.com> wrote:
>>> 
>>> LDAP connections are quite stable. Again, this check is there to respect 
>>> the commons-pool API contract. If the connection is dead, then doing this 
>>> check will let the pool fetching another connection, which is good. OTOH, 
>>> if you don't want to check connections while fetching one, then you are on 
>>> your own (ie, deal with the consequences of a bad connection).
>> Again, I must disagree.  Connections aren’t stable, subjected to env 
>> conditions and we can never assume a connection is good. 
> 
> You *can* assume it's good, and react exceptionally if it's not. That the 
> fastest way to deal with potential bad connections, if you want to avoid a 
> check every time you pull a connection from the pool. (but see later for 
> another option)

There are 150 locations in fortress core where an ldap connection is being 
pulled from the pool. No way I want to revisit all of that code. 

> 
> Something in the API chain must do the job of testing and reconnect, every 
> time it’s pulled from the pool.
> 
> This is exactly what the testOnBorrow does ;-) But it's costly... (see later 
> for another option)
> 
>> Now, having said that, that’s exactly what I’m observing currently, with the 
>> test on borrow flag turned off.
>> Let me explain the scenario:
>> 1. Start server
>> 2. Start client
>> This initializes a connection pool which creates and stores exactly 1 
>> connection (min 1, max1 )
>> 3. Set breakpoint in client on pool.getConnection method
>> 4. Restart the server.
>> 5. Client performs ldap op which triggers the breakpoint on getConnection
>> 6. Server at this point still hasn’t any connections with the client.  The 
>> client ‘thinks’ it has connections in the pool, but these were broken on 
>> step 4.
>> 7. Step over the getConnection which then triggers the commons pool to 
>> execute:
>> ```                
>> GenericObjectPool._factory.activateObject(latch.getPair().value)
>> ```
>> 8. A connection is made with the server, along with bind
>> ```
>> 6058e163 conn=1000 fd=14 ACCEPT from IP=127.0.0.1:35246 (IP=127.0.0.1:389)
>>      [exec] 6058e163 conn=1000 op=0 BIND dn="cn=manager,dc=example,dc=com" 
>> method=128
>>      [exec] 6058e163 conn=1000 op=0 BIND dn="cn=manager,dc=example,dc=com" 
>> mech=SIMPLE ssf=0
>>      [exec] 6058e163 conn=1000 op=0 RESULT tag=97 err=0 duration=1.667ms
>> ```
>> 9. Client continues with its ldap op successfully and is never the wiser 
>> that the connections were all forcibly closed on server restart.
>> This is EXACTLY what I want to see all of which is done without the test on 
>> borrow eliminating the extraneous search on every connection retrieval.
> 
> So that would mean we have some kind of 'retry' on connection operation: if 
> it fails, then let's assume the connection is broken, and redo it with a 
> fresh connection.
> 

Yes, that’s what’s happening.  
In the Commons pool lib, this is the block that gets executed:

```             this._factory.activateObject(latch.getPair().value);
if (this._testOnBorrow &&     
!this._factory.validateObject(latch.getPair().value)) {
throw new Exception("ValidateObject failed");
}
```

In the first line above, activateObject, this code gets called, from our 
AbstractPoolableLdapConnectionFactory class:

```
public void activateObject(LdapConnection connection) throws LdapException {
  LOG.debug("Activating {}", connection);
  if (!connection.isConnected() ||
      !connection.isAuthenticated()) {
    LOG.debug("rebind due to connection dropped on {}", connection);
    this.connectionFactory.bindConnection(connection);
}
```

The code performs a rebind which renews the connection.

All of this with testOnBorrow being false! 

So, I’m still scratching my head figuring why we need this secondary level that 
is wasting a round trip to the server.


> The problem is that the pool is passive: it does not react to any connection 
> event, like a connection closure. OTOH, when a connection is properly closed 
> by the server (ie an NoticeOfDisconnect - aka NoD - is generated by the 
> server), the connection should process it and die. Now we have an issue: the 
> connection is just lying in the pool, not being used by any client, so there 
> is a missing step: removing the connection from the pool in this very case. 
> That can be something we can add to the current LDAP pool.
> 
> Note that if the server does not send a NoD, you are screwed. There is no way 
> to be sure that the connection is ok until you use it. OTOH, leveraging the 
> setTestWhileIdle() could be a solution to partially workaround the issue.

Here you’ve lost me.  I’m running the server in debug mode, inside a bash 
shell, running in the foreground.

In my test I stop the server by ‘ctrl-c’ killing the shell.

The server is not reacting to this and sending a NoD.

—
Shawn


---------------------------------------------------------------------
To unsubscribe, e-mail: api-unsubscr...@directory.apache.org
For additional commands, e-mail: api-h...@directory.apache.org

Reply via email to