Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

[CBR-475] adds MVar for any sqlite-operation #3870

Merged
merged 5 commits into from
Nov 20, 2018
Merged

Conversation

kderme
Copy link
Member

@kderme kderme commented Nov 19, 2018

Description

Multithreading at SQlite is not the greatest. The intermediate libraries we use make things slightly worse. We already suffer from 2 known issues:

StorageFailure (SQLOtherError SQLite3 returned ErrorConstraint while attempting to perform step: not an error)
cardano-node: StorageFailure (SQLOtherError SQLite3 returned ErrorConstraint while attempting to perform step: not an error)
  • withTransaction is not multithreaded. If 2 threads (which for example restore/sync at the same time) tries to use it, the node may crash. I tried this:
thread0 conn = 
    forM_ [1..5000] $ \n -> do
        withTransaction conn (return ())

thread1 conn = 
    forM_ [1..5000] $ \n -> do
        withTransaction conn (return ())

and I get different results like:
SQLite3 returned ErrorError while attempting to perform step: not an error
SQLite3 returned ErrorError while attempting to perform step: cannot start a transaction within a transaction
so even trying to handle the IS_BUSY error, we may get the wrong error because of the previous isssue!

Given the above and despite as cruel as it is, I think we should use our own MVars and use mutually exclusive uses of the connection.

Linked issue

Type of change

  • 🐞 Bug fix (non-breaking change which fixes an issue)

How to merge

Send the message bors r+ to merge this PR. For more information, see
docs/how-to/bors.md.

Copy link
Contributor

@dcoutts dcoutts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Serialising access to the connection on our side is much cleaner than relying on the sqlite serialised mode.

@kderme kderme force-pushed the kderme/CBR-475-lock branch 2 times, most recently from 9c41f87 to 1d6cb47 Compare November 19, 2018 16:45
Copy link
Contributor

@parsonsmatt parsonsmatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic, love the tests.

The `waitAny` function calls were killing threads, causing some work to
not be completed.
Copy link
Member Author

@kderme kderme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @parsonsmatt for the fix. I cherry-picked only the unit-tests, without the MVars here #3872 and it fails pretty convincingly. I missed the failing stylish-Haskell frm Hydra, now fixed 🙏 . I added bindings for sqlite_threadSafe3 and tests indicate THREADSAFE=1, which means Serialized mode https://www.sqlite.org/threadsafe.html.

@@ -201,8 +201,7 @@ txMetaStorageSpecs = do
run $ withTemporaryDb $ \hdl -> do
t0 <- async $ threadWriteWithNoOp meta0 hdl
t1 <- async $ threadWriteWithNoOp meta1 hdl
_ <- waitAny [t0, t1]
return ()
traverse_ wait [t0, t1]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️ 🤦‍♂️

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants