db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mamta Satoor" <msat...@gmail.com>
Subject How is Statement.setQueryTimeout implemented in Derby?
Date Tue, 03 Jun 2008 20:49:58 GMT
Hello,

While researching the random behavior of DERBY-1848, I looked through
the Derby code to understand how we implement
Statement.setQueryTimeout and following is what I found out. I would
appreciate if someone can verify if my understanding is correct or
not. And if yes, then why under weme6.1, we might not be disabling the
timer associated with Statement.setQueryTimeout implementation?

Will appreciate any feedback. Thanks


Around each position moving request on a ResultSet object
(next/previous/first/last etc), Derby pushes the StatementContext for
that Statement (EmbedResultSet.movePosition). And once the ResultSet
positioning is over, the StatementContext is popped back. This happens
in EmbedResultSet.moveposition(int,int,String) method.

During the pushing of the StatementContext (in
GenericLangaugeConnectionContext.pushStatementContext), we mark the
StatementContext to be in use by calling
GenericStatementContext.setInUse. This setInUse method checks if query
timeout is set on the Statement, and if yes, then it starts a Timer
which uses CancelQueryTask to keep track of when the Statement
execution should be marked timedout (The setting of the
CancelQueryTask happens in GenericStatementContext.setInUse).

Once the requested positioning is done on the ResultSet object, Derby
goes through the process of popping the StatementContext. This happens
in GenericLangaugeConnectionContext.popStatementContext. Here, we mark
the StatementContext as not in use since we are going to pop the
StatementContext. This work gets done in
GenericStatementContext.clearInUse. clearInUse checks if there is a
timeout timer associated with the StatementContext (this association
was done in pushStatementContext) and if yes, then it disassociates
the timer and then marks the timer object as null. It also goes ahead
and marks the cancel query flag to flase (cancellationFlag). The
cancellationFlag tells whether the query associated with the
StatementContext has exceeded the timeout limit. If user never set a
query timeout on the Statement object, cancellationFlag will always be
false. But if the user has set a query timeout, then this flag will be
set to true by the CancelQueryTask when it finds that the Statement
has run over it's limit of timeout amount. We do not throw an
exception for query timeout as soon as the flag gets set to true. The
cancellationFlag gets checked only when the user has requested a
position movement on the ResultSet object.

So, one possible scenario can be that we push a StatementContext
because user has requested say, ResultSet.next. During push, we set a
query timeout timer because user has requested for timeout on the
query. Then we go through the code for moving to next row in the
ResultSet. The first thing we check there is if the query is marked
cancelled (by checking cancellationFlag on StatementContext). If yes,
then we throw an exception. But for this case, let's assume the query
has not timeed out yet. Hence we go through the rest of the code for
moving to next row. While we are doing this(ie before we are finished
with the code for moving to next row), say the timer times out and the
timer goes and sets cancellationFlag to true (this happens in
CancelQueryTask.run() which lives in the class
GenericStatementContext). But this setting of flag is little too late
for the current movement within the ResultSet object because we had
just checked the flag earlier and it was set to false at that time.
So, at this point, we just finish the ResultSet movement and then pop
the StatementContext without throwning any exception. If the user has
asked for another ResultSet movement after the current one, we will
catch the query timeout, go through popping the current Statement
Context and then throw an exception. The popping of the
StatementContext marks the StatementContext associated with the query
timeout timer to false and then it nullifies the query timeout timer.

What seems to be happening in case of weme6.1 occassionally is that
once the query timeout has been set and detected (which causes us to
nullify the CancelQueryTask associated with the StatementContext being
popped and throw exception), Derby somehow manages to set the query
timeout to true again and we end up detecting it again and apparently
we associate that timeout with a StatementContext that has not even
requested a query timeout on it.


I wondered if someone familiar with this query timeout code can see
what can cause us to set the timeout again when apparently we have
nulled out the timer (in
GenericLangaugeConnectionContext.popStatementContext).

Mime
View raw message