From 28b3b399849939ed85aabb2267b0859853c8fdbb Mon Sep 17 00:00:00 2001 From: Andrei Lebedev Date: Tue, 5 Mar 2019 09:20:54 +0300 Subject: [PATCH] RC4 Hotfix 1 - TemporaryWsv deadlock, checkTxPresence performance (#2140) * Fix deadlock on TemporaryWsv creation Signed-off-by: Andrei Lebedev * Add hash index for transaction status Signed-off-by: Andrei Lebedev --- irohad/ametsuchi/impl/storage_impl.cpp | 10 +++++++++- .../irohad/ametsuchi/ametsuchi_fixture.hpp | 1 + .../module/irohad/ametsuchi/ametsuchi_test.cpp | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/irohad/ametsuchi/impl/storage_impl.cpp b/irohad/ametsuchi/impl/storage_impl.cpp index 3594f02e4b..8fae510ec1 100644 --- a/irohad/ametsuchi/impl/storage_impl.cpp +++ b/irohad/ametsuchi/impl/storage_impl.cpp @@ -100,6 +100,12 @@ namespace iroha { return expected::makeError("Connection was closed"); } auto sql = std::make_unique(*connection_); + // if we create temporary storage, then we intend to validate a new + // proposal. this means that any state prepared before that moment is not + // needed and must be removed to prevent locking + if (block_is_prepared) { + rollbackPrepared(*sql); + } return expected::makeValue>( std::make_unique( @@ -118,7 +124,7 @@ namespace iroha { auto sql = std::make_unique(*connection_); // if we create mutable storage, then we intend to mutate wsv // this means that any state prepared before that moment is not needed - // and must be removed to preventy locking + // and must be removed to prevent locking if (block_is_prepared) { rollbackPrepared(*sql); } @@ -547,6 +553,7 @@ DROP TABLE IF EXISTS signatory; DROP TABLE IF EXISTS peer; DROP TABLE IF EXISTS role; DROP TABLE IF EXISTS height_by_hash; +DROP INDEX IF EXISTS tx_status_by_hash_hash_index; DROP TABLE IF EXISTS tx_status_by_hash; DROP TABLE IF EXISTS height_by_account_set; DROP TABLE IF EXISTS index_by_creator_height; @@ -648,6 +655,7 @@ CREATE TABLE IF NOT EXISTS tx_status_by_hash ( hash varchar, status boolean ); +CREATE INDEX IF NOT EXISTS tx_status_by_hash_hash_index ON tx_status_by_hash USING hash (hash); CREATE TABLE IF NOT EXISTS height_by_account_set ( account_id text, diff --git a/test/module/irohad/ametsuchi/ametsuchi_fixture.hpp b/test/module/irohad/ametsuchi/ametsuchi_fixture.hpp index 8d75cd2bab..c77a501714 100644 --- a/test/module/irohad/ametsuchi/ametsuchi_fixture.hpp +++ b/test/module/irohad/ametsuchi/ametsuchi_fixture.hpp @@ -155,6 +155,7 @@ CREATE TABLE IF NOT EXISTS tx_status_by_hash ( hash varchar, status boolean ); +CREATE INDEX IF NOT EXISTS tx_status_by_hash_hash_index ON tx_status_by_hash USING hash (hash); CREATE TABLE IF NOT EXISTS height_by_account_set ( account_id text, diff --git a/test/module/irohad/ametsuchi/ametsuchi_test.cpp b/test/module/irohad/ametsuchi/ametsuchi_test.cpp index c834ede157..2268c14ab3 100644 --- a/test/module/irohad/ametsuchi/ametsuchi_test.cpp +++ b/test/module/irohad/ametsuchi/ametsuchi_test.cpp @@ -667,3 +667,21 @@ TEST_F(PreparedBlockTest, CommitPreparedFailsAfterCommit) { shared_model::interface::Amount resultingBalance{"15.00"}; validateAccountAsset(sql_query, "admin@test", "coin#test", resultingBalance); } + +/** + * @given Storage with prepared state + * @when another temporary wsv is created and transaction is applied + * @then previous state is dropped and new transaction is applied successfully + */ +TEST_F(PreparedBlockTest, TemporaryWsvUnlocks) { + auto result = temp_wsv->apply(*initial_tx); + ASSERT_TRUE(framework::expected::val(result)); + storage->prepareBlock(std::move(temp_wsv)); + + using framework::expected::val; + temp_wsv = std::move(val(storage->createTemporaryWsv())->value); + + result = temp_wsv->apply(*initial_tx); + ASSERT_TRUE(framework::expected::val(result)); + storage->prepareBlock(std::move(temp_wsv)); +}