Philip,

On 8/18/15 11:42 AM, Wernersbach, Philip wrote:
> Christopher,
> 
> On 8/17/15, 5:59 PM, "Christopher Schultz" <ch...@christopherschultz.net>
> wrote:
> 
>> Philip,
>>
>> On 8/17/15 12:27 PM, Wernersbach, Philip wrote:
>>> We are developing a JDBC driver that implements the JDBC API. Our
>>> driver works and we can use it in servlets, but Tomcat doesn¹t seem
>>> to know that the connections in the thread pool can be reused, so
>>> after all of the connection slots in the thread pool are used, the
>>> servlets hang trying to get a connection.
>>
>> If you set maxTotal="1", you get a timeout when you try to fetch a
>> second connection?
> 
> Yes. To test this I modified the code and got two connections
> consecutively, and it hung on getting the second connection.

Did you return the first one before requesting a second one?

>> Are you sure the servlet called Connection.close()?
> 
> That seemed to be the problem. I audited our code and found a corner case
> where Connection.close() was not called. I fixed it, and all seems to work
> as it should.

Good.

>> What does the stack trace of the request-processing thread look like
>> when it's hung up?
> 
> It hung at DataSource.getConnection() with this stack trace:
> 
> Unsafe.park(boolean, long) line: not available [native method]        
> LockSupport.park(Object) line: 175    
> AbstractQueuedSynchronizer$ConditionObject.await() line: 2039 
> LinkedBlockingDeque<E>.takeFirst() line: 582  
> GenericObjectPool<T>.borrowObject(long) line: 439     
> GenericObjectPool<T>.borrowObject() line: 360 
> PoolingDataSource<C>.getConnection() line: 133        
> BasicDataSource.getConnection() line: 1532    
> IngDb.getDbConnection() line: 42

I think this is expected behavior; when all the connections are
checked-out, client code has to wait for a connection to be returned, or
for the pool to consider the connection to be "abandoned", evict the
abandoned connection from the pool, and create a new connection (which
can then be given-out to clients).

>>> What API does the Tomcat DataSource Connection thread pool use to
>>> know a connection can be reused? This is an API question, but our
>>> specific version of Tomcat is 8.0.24.
>>
>> Are you using DBCP2 (the default) or Tomcat's jdbc-pool?
> 
> DBCP2
> 
>>
>> Do you mean to check to see if a connection is valid for re-use?
> 
> Our servlet code doesn¹t need to check if a connection is valid for
> re-use, we just need Tomcat to know that our connections are always valid
> for re-use in the pool (the database connection is automatically kept
> alive until it is explicitly closed).
> 
>>
>> I think the answer for /both/ is that they use this call:
>>
>>  Connection.isValid(int timeout)
>>
>> What version of JDBC are you implementing? It seems that Java 6 is when
>> the Connection.isValid method was added.
> 
> JDBC 4.2, which does have Connection.isValid(), we¹ve implemented it.
> 
>>
>> Or did you mean to check to see if a connection can be re-used *at all*
>> -- meaning, can the connection even really be used in a pool?
>>
>> What does your <Resource> element look like in context.xml?
>>
>> -chris
> 
> I¹m assuming Tomcat will automatically take care of pooling even though
> we¹re calling Connection.close()? Our close() implementation explicitly
> closes the database connection, in such a way that it can¹t be reused.

When client code calls Connection.close(), they are calling close() on a
wrapper object. Your code won't see these close() calls because the
pooled connections will intercept them and the connections will be
returned to the pool.

If/when the pool is shut-down, your Connection objects should see a
.close() call.

I'm concerned about your lack of understanding of the way a connection
pool works and inability to debug it sufficiently before asking in this
forum, if you are to be implementing a JDBC driver. :/

-chris

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to