You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jena.apache.org by "Mark Buquor (JIRA)" <ji...@apache.org> on 2012/09/17 17:02:07 UTC

[jira] [Created] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Mark Buquor created JENA-324:
--------------------------------

             Summary: An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
                 Key: JENA-324
                 URL: https://issues.apache.org/jira/browse/JENA-324
             Project: Apache Jena
          Issue Type: Bug
          Components: TDB
    Affects Versions: TDB 0.9.3, TDB 0.9.2, TDB 0.9.1, TDB 0.9.4
            Reporter: Mark Buquor


An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
    dataset.isInTransaction() == false
    dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
    dataset.end() appears OK
    dataset.begin(ReadWrite.READ) appears OK
    dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()

 
The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
    TransactionManager.activeWriters: 1
    TransactionManager.activeTransactions: 1
        [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
            changesPending=true
            outcome=UNFINISHED


Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".


There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").

Rough outline of a commit:
    state == TxnState.PREPARING
    -- commitPrepare()
    -- journal.write()
    -- journal.sync() // Commit point.
    state == TxnState.COMMITED
    -- noteTxnCommit()
    -- currentReaderView.set(null)
    -- writersWaiting.release()

noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Andy Seaborne (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13459558#comment-13459558 ] 

Andy Seaborne commented on JENA-324:
------------------------------------

If the system has run out of disk, only read-transactions will be possible until the system issue is fixed.  Writes need disk space.

Later reads may generate errors but no committed data is lost.

                
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Closed] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Andy Seaborne (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Andy Seaborne closed JENA-324.
------------------------------

    
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>            Assignee: Andy Seaborne
>             Fix For: TDB 0.9.4
>
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Mark Buquor (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13461779#comment-13461779 ] 

Mark Buquor commented on JENA-324:
----------------------------------

Thanks, Andy. Will test it out.
                
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>            Assignee: Andy Seaborne
>             Fix For: TDB 0.9.4
>
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Andy Seaborne (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13461205#comment-13461205 ] 

Andy Seaborne commented on JENA-324:
------------------------------------

The code now catches exceptions at the various points of the commit (and abort) phase and tries to cleanup tidily.  An exception in the prepare phase will lead to an attempt to abort.

There is always a narrow window 9which is now much smaller) when the journal commit record is written and sync'ed and if this causes a low level system problem (e.g. IOException), the system is broken and the best course of action is to stop the app and fix it.

IO problems are more likely during the prepare phase due to the size of data written at this point.

A transaction either aborts, or commits.  There is no possibility of visible partially committed data.

                
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Resolved] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Andy Seaborne (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Andy Seaborne resolved JENA-324.
--------------------------------

       Resolution: Fixed
    Fix Version/s: TDB 0.9.4
         Assignee: Andy Seaborne

"fixed" in the sense of "recovery is attempted".  If the hardware is broken, few guarantees can be given.  Partial commits were not possible and still aren't.
                
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>            Assignee: Andy Seaborne
>             Fix For: TDB 0.9.4
>
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Simon Helsen (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13459682#comment-13459682 ] 

Simon Helsen commented on JENA-324:
-----------------------------------

thanks for the response Andy. However, I am not sure how your comment addresses the concern. The problem we observe is that if something goes wrong during commit, it seems like a transaction gets in a stuck state which can only be recovered from when you call StoreConnection.expel(location, true), which does not seem official API
                
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (JENA-324) An exception thrown from commit() leaves the StoreConnection in an inconsistent state.

Posted by "Mark Buquor (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JENA-324?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13457141#comment-13457141 ] 

Mark Buquor commented on JENA-324:
----------------------------------

Just a note on severity. This is not a critical issue for me if I can safely recover from these situations. For my needs, I can treat any exception from commit() as an abort and retry the operation later. With the example IOException in 0.9.1, the journal was corrupt and the implications were more serious. With 0.9.4 enhancements, the corrupt journal appears to be recoverable. StoreConnection.expel(location, true) looks like it will clear the stuck transaction and trigger journal recovery without restarting, but I'd like to get this blessed as a workaround due to its "testing only" status.
                
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> --------------------------------------------------------------------------------------
>
>                 Key: JENA-324
>                 URL: https://issues.apache.org/jira/browse/JENA-324
>             Project: Apache Jena
>          Issue Type: Bug
>          Components: TDB
>    Affects Versions: TDB 0.9.1, TDB 0.9.2, TDB 0.9.3, TDB 0.9.4
>            Reporter: Mark Buquor
>
> An exception thrown from commit() leaves the StoreConnection in an inconsistent state.
> Example: After a commit() throws an IOException in prepare() due to insufficient disk space, I see the following behavior:
>     dataset.isInTransaction() == false
>     dataset.abort() throws TDBTransactionException: "Transaction has already committed or aborted"
>     dataset.end() appears OK
>     dataset.begin(ReadWrite.READ) appears OK
>     dataset.begin(ReadWrite.WRITE) blocks on writersWaiting.acquire()
>  
> The debugger shows that the transaction is stuck in limbo: active, closed, and unfinished.
>     TransactionManager.activeWriters: 1
>     TransactionManager.activeTransactions: 1
>         [Transaction: 151 : Mode=WRITE : State=CLOSED : X:\RELM1\]
>             changesPending=true
>             outcome=UNFINISHED
> Short of a fix, it looks like the only option to clear the stuck transaction is StoreConnection.expel(location, true), which has the comment "testing only".
> There's also the indeterminacy of ending a transaction that, as far as I can tell at the Dataset level, may or may not be committed ("Transaction has already committed or aborted").
> Rough outline of a commit:
>     state == TxnState.PREPARING
>     -- commitPrepare()
>     -- journal.write()
>     -- journal.sync() // Commit point.
>     state == TxnState.COMMITED
>     -- noteTxnCommit()
>     -- currentReaderView.set(null)
>     -- writersWaiting.release()
> noteTxnCommit() is called after the commit and performs IO, so it appears that if commit() throws an exception, it's not necessarily true that the transaction is effectively aborted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira