From 34a31f2b97c25a2a8a37d4ce9ac143af7a0f58e9 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 25 Aug 2016 13:11:25 +0200 Subject: [PATCH 1/3] issue #2006: added more diagnostic output for some replication errors --- arangod/Replication/Syncer.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/arangod/Replication/Syncer.cpp b/arangod/Replication/Syncer.cpp index 42050aa088..9ba427b62a 100644 --- a/arangod/Replication/Syncer.cpp +++ b/arangod/Replication/Syncer.cpp @@ -406,13 +406,15 @@ int Syncer::applyCollectionDumpMarker( res = opRes.code; } catch (arangodb::basics::Exception const& ex) { res = ex.code(); - } catch (...) { - res = TRI_ERROR_INTERNAL; - } - - if (res != TRI_ERROR_NO_ERROR) { errorMsg = "document insert/replace operation failed: " + std::string(TRI_errno_string(res)); + } catch (std::exception const& ex) { + res = TRI_ERROR_INTERNAL; + errorMsg = "document insert/replace operation failed: " + + std::string(ex.what()); + } catch (...) { + res = TRI_ERROR_INTERNAL; + errorMsg = "document insert/replace operation failed: unknown exception"; } return res; @@ -436,15 +438,16 @@ int Syncer::applyCollectionDumpMarker( res = opRes.code; } catch (arangodb::basics::Exception const& ex) { res = ex.code(); - } catch (...) { - res = TRI_ERROR_INTERNAL; - } - - if (res != TRI_ERROR_NO_ERROR) { errorMsg = "document remove operation failed: " + std::string(TRI_errno_string(res)); + } catch (std::exception const& ex) { + errorMsg = "document remove operation failed: " + + std::string(ex.what()); + } catch (...) { + res = TRI_ERROR_INTERNAL; + errorMsg = "document remove operation failed: unknown exception"; } - + return res; } From 3600ed40f85a18fdeb6cb56bb15b3c6da466f482 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 25 Aug 2016 14:00:55 +0200 Subject: [PATCH 2/3] more diagnostic output --- arangod/VocBase/transaction.cpp | 49 +++++-- .../shell/shell-transactions-noncluster.js | 131 ++++++++++++++++++ 2 files changed, 168 insertions(+), 12 deletions(-) diff --git a/arangod/VocBase/transaction.cpp b/arangod/VocBase/transaction.cpp index f7e7722fe4..939e5b2aa4 100644 --- a/arangod/VocBase/transaction.cpp +++ b/arangod/VocBase/transaction.cpp @@ -611,18 +611,25 @@ static int WriteBeginMarker(TRI_transaction_t* trx) { try { arangodb::wal::TransactionMarker marker(TRI_DF_MARKER_VPACK_BEGIN_TRANSACTION, trx->_vocbase->_id, trx->_id); res = GetLogfileManager()->allocateAndWrite(marker, false).errorCode; + + TRI_IF_FAILURE("TransactionWriteBeginMarkerThrow") { + throw std::bad_alloc(); + } if (res == TRI_ERROR_NO_ERROR) { trx->_beginWritten = true; + } else { + THROW_ARANGO_EXCEPTION(res); } } catch (arangodb::basics::Exception const& ex) { res = ex.code(); + LOG(WARN) << "could not save transaction begin marker in log: " << ex.what(); + } catch (std::exception const& ex) { + res = TRI_ERROR_INTERNAL; + LOG(WARN) << "could not save transaction begin marker in log: " << ex.what(); } catch (...) { res = TRI_ERROR_INTERNAL; - } - - if (res != TRI_ERROR_NO_ERROR) { - LOG(WARN) << "could not save transaction begin marker in log: " << TRI_errno_string(res); + LOG(WARN) << "could not save transaction begin marker in log: unknown exception"; } return res; @@ -650,14 +657,23 @@ static int WriteAbortMarker(TRI_transaction_t* trx) { try { arangodb::wal::TransactionMarker marker(TRI_DF_MARKER_VPACK_ABORT_TRANSACTION, trx->_vocbase->_id, trx->_id); res = GetLogfileManager()->allocateAndWrite(marker, false).errorCode; + + TRI_IF_FAILURE("TransactionWriteAbortMarkerThrow") { + throw std::bad_alloc(); + } + + if (res != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(res); + } } catch (arangodb::basics::Exception const& ex) { res = ex.code(); + LOG(WARN) << "could not save transaction abort marker in log: " << ex.what(); + } catch (std::exception const& ex) { + res = TRI_ERROR_INTERNAL; + LOG(WARN) << "could not save transaction abort marker in log: " << ex.what(); } catch (...) { res = TRI_ERROR_INTERNAL; - } - - if (res != TRI_ERROR_NO_ERROR) { - LOG(WARN) << "could not save transaction abort marker in log: " << TRI_errno_string(res); + LOG(WARN) << "could not save transaction abort marker in log: unknown exception"; } return res; @@ -693,15 +709,24 @@ static int WriteCommitMarker(TRI_transaction_t* trx) { // also sync RocksDB WAL RocksDBFeature::syncWal(); } + + TRI_IF_FAILURE("TransactionWriteCommitMarkerThrow") { + throw std::bad_alloc(); + } + + if (res != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(res); + } #endif } catch (arangodb::basics::Exception const& ex) { res = ex.code(); + LOG(WARN) << "could not save transaction commit marker in log: " << ex.what(); + } catch (std::exception const& ex) { + res = TRI_ERROR_INTERNAL; + LOG(WARN) << "could not save transaction commit marker in log: " << ex.what(); } catch (...) { res = TRI_ERROR_INTERNAL; - } - - if (res != TRI_ERROR_NO_ERROR) { - LOG(WARN) << "could not save transaction commit marker in log: " << TRI_errno_string(res); + LOG(WARN) << "could not save transaction commit marker in log: unknown exception"; } return res; diff --git a/js/server/tests/shell/shell-transactions-noncluster.js b/js/server/tests/shell/shell-transactions-noncluster.js index e36a97f2e7..97a5b8c724 100644 --- a/js/server/tests/shell/shell-transactions-noncluster.js +++ b/js/server/tests/shell/shell-transactions-noncluster.js @@ -5011,6 +5011,137 @@ function transactionServerFailuresSuite () { } catch (err) { // ignore the intentional error + assertEqual(internal.errors.ERROR_DEBUG.code, err.errorNum); + } + + internal.debugClearFailAt(); + + testHelper.waitUnload(c); + + assertEqual(100, c.count()); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test: cannot write begin marker for trx +//////////////////////////////////////////////////////////////////////////////// + + testNoBeginMarkerThrow : function () { + internal.debugClearFailAt(); + + db._drop(cn); + c = db._create(cn); + + var i; + for (i = 0; i < 100; ++i) { + c.save({ _key: "test" + i, a: i }); + } + assertEqual(100, c.count()); + + internal.wal.flush(true, true); + internal.debugSetFailAt("TransactionWriteBeginMarkerThrow"); + + try { + TRANSACTION({ + collections: { + write: [ cn ], + }, + action: function () { + c.save({ _key: "test100" }); + fail(); + } + }); + fail(); + } + catch (err) { + assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum); + } + + assertEqual(100, c.count()); + internal.debugClearFailAt(); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test: cannot write commit marker for trx +//////////////////////////////////////////////////////////////////////////////// + + testNoCommitMarkerThrow : function () { + internal.debugClearFailAt(); + + db._drop(cn); + c = db._create(cn); + + var i; + for (i = 0; i < 100; ++i) { + c.save({ _key: "test" + i, a: i }); + } + assertEqual(100, c.count()); + + internal.wal.flush(true, true); + internal.debugSetFailAt("TransactionWriteCommitMarkerThrow"); + + try { + TRANSACTION({ + collections: { + write: [ cn ], + }, + action: function () { + var i; + for (i = 100; i < 1000; ++i) { + c.save({ _key: "test" + i, a: i }); + } + + assertEqual(1000, c.count()); + } + }); + fail(); + } + catch (err) { + assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum); + } + + assertEqual(100, c.count()); + internal.debugClearFailAt(); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test: cannot write abort marker for trx +//////////////////////////////////////////////////////////////////////////////// + + testNoAbortMarkerThrow : function () { + internal.debugClearFailAt(); + + db._drop(cn); + c = db._create(cn); + + var i; + for (i = 0; i < 100; ++i) { + c.save({ _key: "test" + i, a: i }); + } + assertEqual(100, c.count()); + + internal.wal.flush(true, true); + internal.debugSetFailAt("TransactionWriteAbortMarkerThrow"); + + try { + TRANSACTION({ + collections: { + write: [ cn ], + }, + action: function () { + var i; + for (i = 100; i < 1000; ++i) { + c.save({ _key: "test" + i, a: i }); + } + + assertEqual(1000, c.count()); + + throw "rollback!"; + } + }); + } + catch (err) { + // ignore the intentional error + assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum); } internal.debugClearFailAt(); From 9436b411db82be02140a947c6a29768cead98e2f Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 25 Aug 2016 14:40:54 +0200 Subject: [PATCH 3/3] fixed tests --- js/server/tests/shell/shell-transactions-noncluster.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/server/tests/shell/shell-transactions-noncluster.js b/js/server/tests/shell/shell-transactions-noncluster.js index 97a5b8c724..edfb37e140 100644 --- a/js/server/tests/shell/shell-transactions-noncluster.js +++ b/js/server/tests/shell/shell-transactions-noncluster.js @@ -5011,7 +5011,6 @@ function transactionServerFailuresSuite () { } catch (err) { // ignore the intentional error - assertEqual(internal.errors.ERROR_DEBUG.code, err.errorNum); } internal.debugClearFailAt(); @@ -5141,7 +5140,6 @@ function transactionServerFailuresSuite () { } catch (err) { // ignore the intentional error - assertEqual(internal.errors.ERROR_INTERNAL.code, err.errorNum); } internal.debugClearFailAt();