[ 
https://issues.apache.org/jira/browse/DERBY-4741?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12923955#action_12923955
 ] 

Dag H. Wanvik edited comment on DERBY-4741 at 10/22/10 2:28 PM:
----------------------------------------------------------------

Uploading a first rev of a patch for part a): 
derby-4741-a-01-api-interruptstatus
Regressions ran ok modulo a hang in BootLockTest.

This patch contains the new helper class InterruptStatus and inserts calls to
restoreIntrFlagIfSeen in before API methods' return and in the exception 
handling (TransactionResourceImpl#handleException).

Execution of EmbedStatement#executeBatch check of interrupts and throws 08000 
if seen between each statement in the batch.

Note: Still, the machinery of InterruptStatus isn't used to save any 
interrupts, that follows in a later patch, so this patch doesn't change 
behavior. The focus here is on the correct placement of calls to
restoreIntrFlagIfSeen in the API.  Reviews appreciated!

------------------------ Patch details:

- iapi.util.InterruptStatus: new helper class for keeping track of detected and
  postponed interrupts. See also its Javadoc.

- LanguageConnectionContext
  GenericLanguageConnectionContext: 

  Methods to set/reset threads interrupt status flag to allow us to clear the 
thread's actual flag temporarily, and to reset it when we return to the user 
application, possibly by throwing an interrupted SQLException (SQL state 08000) 
if we cut something short. It also contains methods to save and retrieve the 
stack frame at the point an interrupt was detected. This is used when we throw 
the interrupt exception. 

- TransactionResourceImpl: resurrect the thread's interrupt status flag on SQL 
error (called from handleException). Use lcc if available, else thread local 
variable.

- EmbedBlob, for methods that call handleException inside synchronized on 
connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) before return

- EmbedResultSet: for methods that call handleException inside synchronized on 
connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) before return

- EmbedStatment: for methods that call handleException inside synchronized on 
connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) before return
 
  In executeBatch, use throwIf between each statement in the batch: if we saw 
an interrupt, stop execution of batch. Note that if we do throw, 
restoreIntrFlagIfSeen will be called in the finally block, but it is 
idempotent, so no harm is done. It is necessary in case we saw an interrupt in 
the last statement of the batch.

- EmbedDatabaseMetaData: for methods that call handleException inside 
synchronized on connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) 
before return

- EmbedPreparedStatement: for methods that call handleException inside 
synchronized on connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) 
before return

- EmbedConnection.java: for methods that call handleException inside 
synchronized on connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) 
before return

  For createDatabase, use InterruptStatus.restoreIntrFlagIfSeen() which 
inspects the thread local variable. This should catch I/O interrupts seen 
during the database creation phase.

  Special handling in #close to make sure we access lcc while it is still 
available.


      was (Author: dagw):
    Uploading a first rev of a patch for part a): 
derby-4741-a-01-api-interruptstatus
Regressions ran ok modulo a hang in BootLockTest.

This patch contains the new helper class InterruptStatus and inserts calls to
restoreIntrFlagIfSeen in before API methods' return and in the exception 
handling (TransactionResourceImpl#handleException).

Execution of EmbedStatement#executeBatch check of interrupts and throws 08000 
if seen between each statement in the batch.

Note: Still, the machinery of InterruptStatus isn't used to save any 
interrupts, that follows in a later patch, so this patch doesn't change 
behavior. The focus here is on the correct placement of calls to
restoreIntrFlagIfSeen in the API.  Reviews appreciated!

------------------------ Patch details:

- iapi.util.InterruptStatus: new helper class for keeping track of detected and
  postponed interrupts

- LanguageConnectionContext
  GenericLanguageConnectionContext: 

  Methods to set/reset threads interrupt status flag to allow us to clear the 
thread's actual flag temporarily, and to reset it when we return to the user 
application, possibly by throwing an interrupted SQLException (SQL state 08000) 
if we cut something short. It also contains methods to save and retrieve the 
stack frame at the point an interrupt was detected. This is used when we throw 
the interrupt exception. See also its Javadoc.

- TransactionResourceImpl: resurrect the thread's interrupt status flag on SQL 
error (called from handleException). Use lcc if available, else thread local 
variable.

- EmbedBlob, for methods that call handleException inside synchronized on 
connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) before return

- EmbedResultSet: for methods that call handleException inside synchronized on 
connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) before return

- EmbedStatment: for methods that call handleException inside synchronized on 
connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) before return
 
  In executeBatch, use throwIf between each statement in the batch: if we saw 
an interrupt, stop execution of batch. Note that if we do throw, 
restoreIntrFlagIfSeen will be called in the finally block, but it is 
idempotent, so no harm is done. It is necessary in case we saw an interrupt in 
the last statement of the batch.

- EmbedDatabaseMetaData: for methods that call handleException inside 
synchronized on connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) 
before return

- EmbedPreparedStatement: for methods that call handleException inside 
synchronized on connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) 
before return

- EmbedConnection.java: for methods that call handleException inside 
synchronized on connection: use InterruptStatus.restoreIntrFlagIfSeen(lcc) 
before return

  For createDatabase, use InterruptStatus.restoreIntrFlagIfSeen() which 
inspects the thread local variable. This should catch I/O interrupts seen 
during the database creation phase.

  Special handling in #close to make sure we access lcc while it is still 
available.

  
> Make Derby work reliably in the presence of thread interrupts
> -------------------------------------------------------------
>
>                 Key: DERBY-4741
>                 URL: https://issues.apache.org/jira/browse/DERBY-4741
>             Project: Derby
>          Issue Type: Bug
>          Components: Store
>    Affects Versions: 10.2.1.6, 10.2.2.0, 10.3.1.4, 10.3.2.1, 10.3.3.0, 
> 10.4.1.3, 10.4.2.0, 10.5.1.1, 10.5.2.0, 10.5.3.0, 10.6.1.0
>            Reporter: Dag H. Wanvik
>            Assignee: Dag H. Wanvik
>         Attachments: derby-4741-a-01-api-interruptstatus.diff, 
> derby-4741-a-01-api-interruptstatus.stat, 
> derby-4741-all+lenient+resurrect.diff, derby-4741-all+lenient+resurrect.stat, 
> derby-4741-nio-container+log+waits+locks+throws.diff, 
> derby-4741-nio-container+log+waits+locks+throws.stat, 
> derby-4741-nio-container+log+waits+locks-2.diff, 
> derby-4741-nio-container+log+waits+locks-2.stat, 
> derby-4741-nio-container+log+waits+locks.diff, 
> derby-4741-nio-container+log+waits+locks.stat, 
> derby-4741-nio-container+log+waits.diff, 
> derby-4741-nio-container+log+waits.stat, derby-4741-nio-container+log.diff, 
> derby-4741-nio-container+log.stat, derby-4741-nio-container-2.diff, 
> derby-4741-nio-container-2.log, derby-4741-nio-container-2.stat, 
> derby-4741-nio-container-2b.diff, derby-4741-nio-container-2b.stat, 
> derby.log, derby.log, MicroAPITest.java, xsbt0.log.gz
>
>
> When not executing on a small device VM, Derby has been using the Java NIO 
> classes java.nio.clannel.* for file io.
> If thread is interrupted while executing blocking IO operations in NIO, the 
> ClosedByInterruptException will get thrown. Unfortunately, Derby isn't 
> current architected to retry and complete such operations (before passing on 
> the interrupt), so the Derby database can be left in an inconsistent state 
> and we therefore have to return a database level error. This means the 
> applications can no longer access the database without a shutdown and reboot 
> including a recovery.
> It would be nice if Derby could somehow detect and finish IO operations 
> underway when thread interrupts happen before passing the exception on to the 
> application. Derby embedded is sometimes embedded in applications that use 
> Thread.interrupt to stop threads.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to