From 7c13a75b928ace3f65c9553352689dc0a6d0ca83 Mon Sep 17 00:00:00 2001 From: Xiangyu Yao Date: Thu, 13 Sep 2018 13:52:39 -0400 Subject: SERVER-37070 Improve duplicate key error messages for all storage engines --- src/mongo/db/storage/biggie/biggie_kv_engine.cpp | 6 ++- src/mongo/db/storage/biggie/biggie_sorted_impl.cpp | 32 +++++++------ src/mongo/db/storage/biggie/biggie_sorted_impl.h | 18 ++++++-- .../db/storage/biggie/biggie_sorted_impl_test.cpp | 3 +- .../ephemeral_for_test_btree_impl.cpp | 48 ++++++++++++------- .../ephemeral_for_test_btree_impl.h | 2 + .../ephemeral_for_test_btree_impl_test.cpp | 4 +- .../ephemeral_for_test_engine.cpp | 7 ++- src/mongo/db/storage/mobile/mobile_index.cpp | 54 ++++++++++++++-------- src/mongo/db/storage/mobile/mobile_index.h | 8 +++- src/mongo/db/storage/mobile/mobile_index_test.cpp | 5 +- src/mongo/db/storage/sorted_data_interface.h | 14 ++++++ .../db/storage/wiredtiger/wiredtiger_index.cpp | 21 +++------ src/mongo/db/storage/wiredtiger/wiredtiger_index.h | 2 - 14 files changed, 144 insertions(+), 80 deletions(-) diff --git a/src/mongo/db/storage/biggie/biggie_kv_engine.cpp b/src/mongo/db/storage/biggie/biggie_kv_engine.cpp index b99d45ccd1c..7c79a822d03 100644 --- a/src/mongo/db/storage/biggie/biggie_kv_engine.cpp +++ b/src/mongo/db/storage/biggie/biggie_kv_engine.cpp @@ -94,7 +94,11 @@ Status KVEngine::createSortedDataInterface(OperationContext* opCtx, mongo::SortedDataInterface* KVEngine::getSortedDataInterface(OperationContext* opCtx, StringData ident, const IndexDescriptor* desc) { - return new SortedDataInterface(Ordering::make(desc->keyPattern()), desc->unique(), ident); + return new SortedDataInterface(Ordering::make(desc->keyPattern()), + desc->unique(), + ident, + desc->parentNS(), + desc->indexName()); } diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp b/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp index 6dc78eb4e06..e7ce7750c79 100644 --- a/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp +++ b/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp @@ -83,13 +83,6 @@ BSONObj stripFieldNames(const BSONObj& obj) { return bob.obj(); } -Status dupKeyError(const BSONObj& key) { - StringBuilder sb; - sb << "E11000 duplicate key error "; - sb << "dup key: " << key; - return Status(ErrorCodes::DuplicateKey, sb.str()); -} - // This function converts a key and an ordering to a KeyString. std::unique_ptr keyToKeyString(const BSONObj& key, Ordering order) { KeyString::Version version = KeyString::Version::V1; @@ -220,13 +213,17 @@ int compareTwoKeys( SortedDataBuilderInterface::SortedDataBuilderInterface(OperationContext* opCtx, bool dupsAllowed, Ordering order, - std::string prefix, - std::string identEnd) + const std::string& prefix, + const std::string& identEnd, + const std::string& collectionNamespace, + const std::string& indexName) : _opCtx(opCtx), _dupsAllowed(dupsAllowed), _order(order), _prefix(prefix), _identEnd(identEnd), + _collectionNamespace(collectionNamespace), + _indexName(indexName), _hasLast(false), _lastKeyToString(""), _lastRID(-1) {} @@ -261,7 +258,7 @@ StatusWith SortedDataBuilderInterface::addKey(const BSONO "expected ascending (key, RecordId) order in bulk builder"); } if (!_dupsAllowed && twoKeyCmp == 0 && twoRIDCmp != 0) { - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } std::string workingCopyInsertKey = combineKeyAndRID(key, loc, _prefix, _order); @@ -283,18 +280,25 @@ StatusWith SortedDataBuilderInterface::addKey(const BSONO SortedDataBuilderInterface* SortedDataInterface::getBulkBuilder(OperationContext* opCtx, bool dupsAllowed) { - return new SortedDataBuilderInterface(opCtx, dupsAllowed, _order, _prefix, _identEnd); + return new SortedDataBuilderInterface( + opCtx, dupsAllowed, _order, _prefix, _identEnd, _collectionNamespace, _indexName); } // We append \1 to all idents we get, and therefore the KeyString with ident + \0 will only be // before elements in this ident, and the KeyString with ident + \2 will only be after elements in // this ident. -SortedDataInterface::SortedDataInterface(const Ordering& ordering, bool isUnique, StringData ident) +SortedDataInterface::SortedDataInterface(const Ordering& ordering, + bool isUnique, + StringData ident, + const std::string& collectionNamespace, + const std::string& indexName) : _order(ordering), // All entries in this ident will have a prefix of ident + \1. _prefix(ident.toString().append(1, '\1')), // Therefore, the string ident + \2 will be greater than all elements in this ident. _identEnd(ident.toString().append(1, '\2')), + _collectionNamespace(collectionNamespace), + _indexName(indexName), _isUnique(isUnique) { // This is the string representation of the KeyString before elements in this ident, which is // ident + \0. This is before all elements in this ident. @@ -340,7 +344,7 @@ StatusWith SortedDataInterface::insert(OperationContext* auto ks1 = keyToKeyString(ike.key, _order); auto ks2 = keyToKeyString(key, _order); if (ks1->compare(*ks2) == 0 && ike.loc.repr() != loc.repr()) { - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } } } @@ -398,7 +402,7 @@ Status SortedDataInterface::dupKeyCheck(OperationContext* opCtx, lowerBoundIterator->first.compare(_KSForIdentEnd) < 0 && lowerBoundIterator->first.compare( combineKeyAndRID(key, RecordId::max(), _prefix, _order)) <= 0) { - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } return Status::OK(); } diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl.h b/src/mongo/db/storage/biggie/biggie_sorted_impl.h index 8ebf74a8c93..09a049981c4 100644 --- a/src/mongo/db/storage/biggie/biggie_sorted_impl.h +++ b/src/mongo/db/storage/biggie/biggie_sorted_impl.h @@ -41,8 +41,10 @@ public: SortedDataBuilderInterface(OperationContext* opCtx, bool dupsAllowed, Ordering order, - std::string prefix, - std::string identEnd); + const std::string& prefix, + const std::string& identEnd, + const std::string& collectionNamespace, + const std::string& indexName); SpecialFormatInserted commit(bool mayInterrupt) override; virtual StatusWith addKey(const BSONObj& key, const RecordId& loc); @@ -54,6 +56,9 @@ private: // Prefix and identEnd for the ident. std::string _prefix; std::string _identEnd; + // Index metadata. + const std::string _collectionNamespace; + const std::string _indexName; // Whether or not we've already added something before. bool _hasLast; // This is the KeyString of the last key added. @@ -67,7 +72,11 @@ public: // Truncate is not required at the time of writing but will be when the truncate command is // created Status truncate(OperationContext* opCtx); - SortedDataInterface(const Ordering& ordering, bool isUnique, StringData ident); + SortedDataInterface(const Ordering& ordering, + bool isUnique, + StringData ident, + const std::string& collectionNamespace, + const std::string& indexName); virtual SortedDataBuilderInterface* getBulkBuilder(OperationContext* opCtx, bool dupsAllowed) override; virtual StatusWith insert(OperationContext* opCtx, @@ -168,6 +177,9 @@ private: // These two are the same as before. std::string _prefix; std::string _identEnd; + // Index metadata. + const std::string _collectionNamespace; + const std::string _indexName; // These are the keystring representations of the _prefix and the _identEnd. std::string _KSForIdentStart; std::string _KSForIdentEnd; diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl_test.cpp b/src/mongo/db/storage/biggie/biggie_sorted_impl_test.cpp index 6fdcb589627..68a82231ddd 100644 --- a/src/mongo/db/storage/biggie/biggie_sorted_impl_test.cpp +++ b/src/mongo/db/storage/biggie/biggie_sorted_impl_test.cpp @@ -47,7 +47,8 @@ private: public: SortedDataInterfaceTestHarnessHelper() : _order(Ordering::make(BSONObj())) {} std::unique_ptr newSortedDataInterface(bool unique) final { - return std::make_unique(_order, unique, "ident"_sd); + return std::make_unique( + _order, unique, "ident"_sd, "test.biggie", "indexName"); } std::unique_ptr newRecoveryUnit() final { //! not correct lol diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp index 1f7b8a02f26..aafbf42a148 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp @@ -70,15 +70,6 @@ BSONObj stripFieldNames(const BSONObj& query) { typedef std::set IndexSet; -// taken from btree_logic.cpp -Status dupKeyError(const BSONObj& key) { - StringBuilder sb; - sb << "E11000 duplicate key error "; - // sb << "index: " << _indexName << " "; // TODO - sb << "dup key: " << key; - return Status(ErrorCodes::DuplicateKey, sb.str()); -} - bool isDup(const IndexSet& data, const BSONObj& key, RecordId loc) { const IndexSet::const_iterator it = data.find(IndexKeyEntry(key, RecordId())); if (it == data.end()) @@ -90,11 +81,17 @@ bool isDup(const IndexSet& data, const BSONObj& key, RecordId loc) { class EphemeralForTestBtreeBuilderImpl : public SortedDataBuilderInterface { public: - EphemeralForTestBtreeBuilderImpl(IndexSet* data, long long* currentKeySize, bool dupsAllowed) + EphemeralForTestBtreeBuilderImpl(IndexSet* data, + long long* currentKeySize, + bool dupsAllowed, + const std::string& collectionNamespace, + const std::string& indexName) : _data(data), _currentKeySize(currentKeySize), _dupsAllowed(dupsAllowed), - _comparator(_data->key_comp()) { + _comparator(_data->key_comp()), + _collectionNamespace(collectionNamespace), + _indexName(indexName) { invariant(_data->empty()); } @@ -111,7 +108,7 @@ public: return Status(ErrorCodes::InternalError, "expected ascending (key, RecordId) order in bulk builder"); } else if (!_dupsAllowed && cmp == 0 && loc != _last->loc) { - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } } @@ -129,16 +126,27 @@ private: IndexEntryComparison _comparator; // used by the bulk builder to detect duplicate keys IndexSet::const_iterator _last; // or (key, RecordId) ordering violations + + const std::string _collectionNamespace; + const std::string _indexName; }; class EphemeralForTestBtreeImpl : public SortedDataInterface { public: - EphemeralForTestBtreeImpl(IndexSet* data, bool isUnique) : _data(data), _isUnique(isUnique) { + EphemeralForTestBtreeImpl(IndexSet* data, + bool isUnique, + const std::string& collectionNamespace, + const std::string& indexName) + : _data(data), + _isUnique(isUnique), + _collectionNamespace(collectionNamespace), + _indexName(indexName) { _currentKeySize = 0; } virtual SortedDataBuilderInterface* getBulkBuilder(OperationContext* opCtx, bool dupsAllowed) { - return new EphemeralForTestBtreeBuilderImpl(_data, &_currentKeySize, dupsAllowed); + return new EphemeralForTestBtreeBuilderImpl( + _data, &_currentKeySize, dupsAllowed, _collectionNamespace, _indexName); } virtual StatusWith insert(OperationContext* opCtx, @@ -151,7 +159,7 @@ public: // TODO optimization: save the iterator from the dup-check to speed up insert if (!dupsAllowed && isDup(*_data, key, loc)) - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); IndexKeyEntry entry(key.getOwned(), loc); if (_data->insert(entry).second) { @@ -197,7 +205,7 @@ public: virtual Status dupKeyCheck(OperationContext* opCtx, const BSONObj& key, const RecordId& loc) { invariant(!hasFieldNames(key)); if (isDup(*_data, key, loc)) - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); return Status::OK(); } @@ -492,6 +500,9 @@ private: IndexSet* _data; long long _currentKeySize; const bool _isUnique; + + const std::string _collectionNamespace; + const std::string _indexName; }; } // namespace @@ -499,12 +510,15 @@ private: // factories. We don't actually modify it. SortedDataInterface* getEphemeralForTestBtreeImpl(const Ordering& ordering, bool isUnique, + const std::string& collectionNamespace, + const std::string& indexName, std::shared_ptr* dataInOut) { invariant(dataInOut); if (!*dataInOut) { *dataInOut = std::make_shared(IndexEntryComparison(ordering)); } - return new EphemeralForTestBtreeImpl(static_cast(dataInOut->get()), isUnique); + return new EphemeralForTestBtreeImpl( + static_cast(dataInOut->get()), isUnique, collectionNamespace, indexName); } } // namespace mongo diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h index 9d44e3e80cd..57432888662 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h @@ -43,6 +43,8 @@ class IndexCatalogEntry; */ SortedDataInterface* getEphemeralForTestBtreeImpl(const Ordering& ordering, bool isUnique, + const std::string& collectionNamespace, + const std::string& indexName, std::shared_ptr* dataInOut); } // namespace mongo diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp index 700628c4331..21c943a2fd9 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp @@ -44,8 +44,8 @@ public: EphemeralForBtreeImplTestHarnessHelper() : _order(Ordering::make(BSONObj())) {} std::unique_ptr newSortedDataInterface(bool unique) final { - return std::unique_ptr( - getEphemeralForTestBtreeImpl(_order, unique, &_data)); + return std::unique_ptr(getEphemeralForTestBtreeImpl( + _order, unique, "test.EphemeralForTest", "indexName", &_data)); } std::unique_ptr newRecoveryUnit() final { diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp index 0bc0f4f8412..b8814c3bdd0 100644 --- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp +++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp @@ -89,8 +89,11 @@ SortedDataInterface* EphemeralForTestEngine::getSortedDataInterface(OperationCon StringData ident, const IndexDescriptor* desc) { stdx::lock_guard lk(_mutex); - return getEphemeralForTestBtreeImpl( - Ordering::make(desc->keyPattern()), desc->unique(), &_dataMap[ident]); + return getEphemeralForTestBtreeImpl(Ordering::make(desc->keyPattern()), + desc->unique(), + desc->parentNS(), + desc->indexName(), + &_dataMap[ident]); } Status EphemeralForTestEngine::dropIdent(OperationContext* opCtx, StringData ident) { diff --git a/src/mongo/db/storage/mobile/mobile_index.cpp b/src/mongo/db/storage/mobile/mobile_index.cpp index 0eec0ce72d8..3c5000c4929 100644 --- a/src/mongo/db/storage/mobile/mobile_index.cpp +++ b/src/mongo/db/storage/mobile/mobile_index.cpp @@ -72,7 +72,11 @@ BSONObj stripFieldNames(const BSONObj& query) { MobileIndex::MobileIndex(OperationContext* opCtx, const IndexDescriptor* desc, const std::string& ident) - : _isUnique(desc->unique()), _ordering(Ordering::make(desc->keyPattern())), _ident(ident) {} + : _isUnique(desc->unique()), + _ordering(Ordering::make(desc->keyPattern())), + _ident(ident), + _collectionNamespace(desc->parentNS()), + _indexName(desc->indexName()) {} StatusWith MobileIndex::insert(OperationContext* opCtx, const BSONObj& key, @@ -109,7 +113,7 @@ StatusWith MobileIndex::doInsert(OperationContext* opCtx, // Return error if duplicate key inserted in a unique index. BSONObj bson = KeyString::toBson(key.getBuffer(), key.getSize(), _ordering, key.getTypeBits()); - return _dupKeyError(bson); + return dupKeyError(bson, _collectionNamespace, _indexName); } else { // A record with same key could already be present in a standard index, that is OK. This // can happen when building a background index while documents are being written in @@ -239,7 +243,7 @@ Status MobileIndex::dupKeyCheck(OperationContext* opCtx, invariant(_isUnique); if (_isDup(opCtx, key, recId)) - return _dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); return Status::OK(); } @@ -273,18 +277,18 @@ bool MobileIndex::_isDup(OperationContext* opCtx, const BSONObj& key, RecordId r return isEntryFound; } -Status MobileIndex::_dupKeyError(const BSONObj& key) { - StringBuilder sb; - sb << "E11000 duplicate key error "; - sb << "index: " << _ident << " "; - sb << "dup key: " << key; - return Status(ErrorCodes::DuplicateKey, sb.str()); -} - class MobileIndex::BulkBuilderBase : public SortedDataBuilderInterface { public: - BulkBuilderBase(MobileIndex* index, OperationContext* opCtx, bool dupsAllowed) - : _index(index), _opCtx(opCtx), _dupsAllowed(dupsAllowed) {} + BulkBuilderBase(MobileIndex* index, + OperationContext* opCtx, + bool dupsAllowed, + const std::string& collectionNamespace, + const std::string& indexName) + : _index(index), + _opCtx(opCtx), + _dupsAllowed(dupsAllowed), + _collectionNamespace(collectionNamespace), + _indexName(indexName) {} virtual ~BulkBuilderBase() {} @@ -314,7 +318,7 @@ protected: Status _checkNextKey(const BSONObj& key) { const int cmp = key.woCompare(_lastKey, _index->getOrdering()); if (!_dupsAllowed && cmp == 0) { - return _index->_dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } else if (cmp < 0) { return Status(ErrorCodes::InternalError, "expected higher RecordId in bulk builder"); } @@ -328,6 +332,8 @@ protected: OperationContext* const _opCtx; BSONObj _lastKey; const bool _dupsAllowed; + const std::string _collectionNamespace; + const std::string _indexName; }; /** @@ -335,8 +341,12 @@ protected: */ class MobileIndex::BulkBuilderStandard final : public BulkBuilderBase { public: - BulkBuilderStandard(MobileIndex* index, OperationContext* opCtx, bool dupsAllowed) - : BulkBuilderBase(index, opCtx, dupsAllowed) {} + BulkBuilderStandard(MobileIndex* index, + OperationContext* opCtx, + bool dupsAllowed, + const std::string& collectionNamespace, + const std::string& indexName) + : BulkBuilderBase(index, opCtx, dupsAllowed, collectionNamespace, indexName) {} protected: StatusWith _addKey(const BSONObj& key, const RecordId& recId) override { @@ -351,8 +361,12 @@ protected: */ class MobileIndex::BulkBuilderUnique : public BulkBuilderBase { public: - BulkBuilderUnique(MobileIndex* index, OperationContext* opCtx, bool dupsAllowed) - : BulkBuilderBase(index, opCtx, dupsAllowed) { + BulkBuilderUnique(MobileIndex* index, + OperationContext* opCtx, + bool dupsAllowed, + const std::string& collectionNamespace, + const std::string& indexName) + : BulkBuilderBase(index, opCtx, dupsAllowed, collectionNamespace, indexName) { // Replication is not supported so dups are not allowed. invariant(!dupsAllowed); } @@ -652,7 +666,7 @@ MobileIndexStandard::MobileIndexStandard(OperationContext* opCtx, SortedDataBuilderInterface* MobileIndexStandard::getBulkBuilder(OperationContext* opCtx, bool dupsAllowed) { invariant(dupsAllowed); - return new BulkBuilderStandard(this, opCtx, dupsAllowed); + return new BulkBuilderStandard(this, opCtx, dupsAllowed, _collectionNamespace, _indexName); } std::unique_ptr MobileIndexStandard::newCursor(OperationContext* opCtx, @@ -690,7 +704,7 @@ SortedDataBuilderInterface* MobileIndexUnique::getBulkBuilder(OperationContext* bool dupsAllowed) { // Replication is not supported so dups are not allowed. invariant(!dupsAllowed); - return new BulkBuilderUnique(this, opCtx, dupsAllowed); + return new BulkBuilderUnique(this, opCtx, dupsAllowed, _collectionNamespace, _indexName); } std::unique_ptr MobileIndexUnique::newCursor(OperationContext* opCtx, diff --git a/src/mongo/db/storage/mobile/mobile_index.h b/src/mongo/db/storage/mobile/mobile_index.h index c7ef60d7061..69c3ee08bca 100644 --- a/src/mongo/db/storage/mobile/mobile_index.h +++ b/src/mongo/db/storage/mobile/mobile_index.h @@ -43,7 +43,11 @@ class MobileIndex : public SortedDataInterface { public: MobileIndex(OperationContext* opCtx, const IndexDescriptor* desc, const std::string& ident); - MobileIndex(bool isUnique, const Ordering& ordering, const std::string& ident); + MobileIndex(bool isUnique, + const Ordering& ordering, + const std::string& ident, + const std::string& collectionNamespace, + const std::string& indexName); virtual ~MobileIndex() {} @@ -135,6 +139,8 @@ protected: const Ordering _ordering; const KeyString::Version _keyStringVersion = KeyString::kLatestVersion; const std::string _ident; + const std::string _collectionNamespace; + const std::string _indexName; }; class MobileIndexStandard final : public MobileIndex { diff --git a/src/mongo/db/storage/mobile/mobile_index_test.cpp b/src/mongo/db/storage/mobile/mobile_index_test.cpp index 31419df65fb..4a2502509e2 100644 --- a/src/mongo/db/storage/mobile/mobile_index_test.cpp +++ b/src/mongo/db/storage/mobile/mobile_index_test.cpp @@ -60,9 +60,10 @@ public: fassert(37052, status); if (isUnique) { - return stdx::make_unique(_ordering, ident); + return stdx::make_unique( + _ordering, ident, "test.mobile", "indexName"); } - return stdx::make_unique(_ordering, ident); + return stdx::make_unique(_ordering, ident, "test.mobile", "indexName"); } std::unique_ptr newRecoveryUnit() { diff --git a/src/mongo/db/storage/sorted_data_interface.h b/src/mongo/db/storage/sorted_data_interface.h index 74355bc96f9..4b720468344 100644 --- a/src/mongo/db/storage/sorted_data_interface.h +++ b/src/mongo/db/storage/sorted_data_interface.h @@ -51,6 +51,20 @@ struct ValidateResults; */ enum SpecialFormatInserted { NoSpecialFormatInserted = 0, LongTypeBitsInserted = 1 }; +/** + * Returns the formatted error status about the duplicate key. + */ +inline Status dupKeyError(const BSONObj& key, + const std::string& collectionNamespace, + const std::string& indexName) { + StringBuilder sb; + sb << "E11000 duplicate key error"; + sb << " collection: " << collectionNamespace; + sb << " index: " << indexName; + sb << " dup key: " << key; + return Status(ErrorCodes::DuplicateKey, sb.str()); +} + /** * This is the uniform interface for storing indexes and supporting point queries as well as range * queries. The actual implementation is up to the storage engine. All the storage engines must diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index 8043c206ebe..f260ffe13e0 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -114,15 +114,6 @@ const int kDataFormatV4KeyStringV1UniqueIndexVersionV2 = 12; const int kMinimumIndexVersion = kDataFormatV1KeyStringV0IndexVersionV1; const int kMaximumIndexVersion = kDataFormatV4KeyStringV1UniqueIndexVersionV2; -Status WiredTigerIndex::dupKeyError(const BSONObj& key) { - StringBuilder sb; - sb << "E11000 duplicate key error"; - sb << " collection: " << _collectionNamespace; - sb << " index: " << _indexName; - sb << " dup key: " << key; - return Status(ErrorCodes::DuplicateKey, sb.str()); -} - void WiredTigerIndex::setKey(WT_CURSOR* cursor, const WT_ITEM* item) { if (_prefix == KVPrefix::kNotPrefixed) { cursor->set_key(cursor, item); @@ -422,7 +413,7 @@ Status WiredTigerIndex::dupKeyCheck(OperationContext* opCtx, WT_CURSOR* c = curwrap.get(); if (isDup(opCtx, c, key, id)) - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); return Status::OK(); } @@ -690,7 +681,7 @@ private: if (cmp == 0) { // Duplicate found! if (!_dupsAllowed) { - return _idx->dupKeyError(newKey); + return dupKeyError(newKey, _idx->collectionNamespace(), _idx->indexName()); } } else { // _previousKey.isEmpty() is only true on the first call to addKey(). @@ -737,7 +728,7 @@ private: } else { // Dup found! if (!_dupsAllowed) { - return _idx->dupKeyError(newKey); + return dupKeyError(newKey, _idx->collectionNamespace(), _idx->indexName()); } // If we get here, we are in the weird mode where dups are allowed on a unique @@ -1406,7 +1397,7 @@ StatusWith WiredTigerIndexUnique::_insertTimestampUnsafe( } if (!dupsAllowed) - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); if (!insertedId) { // This id is higher than all currently in the index for this key @@ -1452,7 +1443,7 @@ StatusWith WiredTigerIndexUnique::_insertTimestampSafe( // An entry with prefix key already exists. This can happen only during rolling upgrade when // both timestamp unsafe and timestamp safe index format keys could be present. if (ret == WT_DUPLICATE_KEY) { - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } invariantWTOK(ret); @@ -1465,7 +1456,7 @@ StatusWith WiredTigerIndexUnique::_insertTimestampSafe( // Second phase looks up for existence of key to avoid insertion of duplicate key if (isDup(opCtx, c, key, id)) - return dupKeyError(key); + return dupKeyError(key, _collectionNamespace, _indexName); } // Now create the table key/value, the actual data record. diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.h b/src/mongo/db/storage/wiredtiger/wiredtiger_index.h index 2b5e1ba3e07..47f8aff0bb3 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.h +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.h @@ -155,8 +155,6 @@ public: virtual bool unique() const = 0; virtual bool isTimestampSafeUniqueIdx() const = 0; - Status dupKeyError(const BSONObj& key); - protected: virtual StatusWith _insert(OperationContext* opCtx, WT_CURSOR* c, -- cgit v1.2.1