summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiangyu Yao <xiangyu.yao@mongodb.com>2018-09-13 13:52:39 -0400
committerXiangyu Yao <xiangyu.yao@mongodb.com>2018-09-13 14:07:10 -0400
commit7c13a75b928ace3f65c9553352689dc0a6d0ca83 (patch)
tree87870158925b882389442fd05bc97824f68a8e6f
parent04da23e18226418856e85a9dcfecafef81488de3 (diff)
downloadmongo-7c13a75b928ace3f65c9553352689dc0a6d0ca83.tar.gz
SERVER-37070 Improve duplicate key error messages for all storage enginesr4.1.3
-rw-r--r--src/mongo/db/storage/biggie/biggie_kv_engine.cpp6
-rw-r--r--src/mongo/db/storage/biggie/biggie_sorted_impl.cpp32
-rw-r--r--src/mongo/db/storage/biggie/biggie_sorted_impl.h18
-rw-r--r--src/mongo/db/storage/biggie/biggie_sorted_impl_test.cpp3
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp48
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h2
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp4
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp7
-rw-r--r--src/mongo/db/storage/mobile/mobile_index.cpp54
-rw-r--r--src/mongo/db/storage/mobile/mobile_index.h8
-rw-r--r--src/mongo/db/storage/mobile/mobile_index_test.cpp5
-rw-r--r--src/mongo/db/storage/sorted_data_interface.h14
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp21
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.h2
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<KeyString> 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<SpecialFormatInserted> 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<SpecialFormatInserted> 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<SpecialFormatInserted> 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<SpecialFormatInserted> 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<SpecialFormatInserted> 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<mongo::SortedDataInterface> newSortedDataInterface(bool unique) final {
- return std::make_unique<SortedDataInterface>(_order, unique, "ident"_sd);
+ return std::make_unique<SortedDataInterface>(
+ _order, unique, "ident"_sd, "test.biggie", "indexName");
}
std::unique_ptr<mongo::RecoveryUnit> 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<IndexKeyEntry, IndexEntryComparison> 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<SpecialFormatInserted> 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<void>* dataInOut) {
invariant(dataInOut);
if (!*dataInOut) {
*dataInOut = std::make_shared<IndexSet>(IndexEntryComparison(ordering));
}
- return new EphemeralForTestBtreeImpl(static_cast<IndexSet*>(dataInOut->get()), isUnique);
+ return new EphemeralForTestBtreeImpl(
+ static_cast<IndexSet*>(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<void>* 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<SortedDataInterface> newSortedDataInterface(bool unique) final {
- return std::unique_ptr<SortedDataInterface>(
- getEphemeralForTestBtreeImpl(_order, unique, &_data));
+ return std::unique_ptr<SortedDataInterface>(getEphemeralForTestBtreeImpl(
+ _order, unique, "test.EphemeralForTest", "indexName", &_data));
}
std::unique_ptr<RecoveryUnit> 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<stdx::mutex> 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<SpecialFormatInserted> MobileIndex::insert(OperationContext* opCtx,
const BSONObj& key,
@@ -109,7 +113,7 @@ StatusWith<SpecialFormatInserted> 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<SpecialFormatInserted> _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<SortedDataInterface::Cursor> 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<SortedDataInterface::Cursor> 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<MobileIndexUnique>(_ordering, ident);
+ return stdx::make_unique<MobileIndexUnique>(
+ _ordering, ident, "test.mobile", "indexName");
}
- return stdx::make_unique<MobileIndexStandard>(_ordering, ident);
+ return stdx::make_unique<MobileIndexStandard>(_ordering, ident, "test.mobile", "indexName");
}
std::unique_ptr<RecoveryUnit> 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
@@ -52,6 +52,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
* support an index key size up to the maximum document size.
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<SpecialFormatInserted> 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<SpecialFormatInserted> 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<SpecialFormatInserted> 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<SpecialFormatInserted> _insert(OperationContext* opCtx,
WT_CURSOR* c,