summaryrefslogtreecommitdiff
path: root/src/mongo/db/field_ref.cpp
diff options
context:
space:
mode:
authorAndrew Morrow <acm@10gen.com>2013-08-25 10:55:22 -0400
committerAndrew Morrow <acm@10gen.com>2013-09-25 14:21:49 -0400
commit4616eae3efe8301ac12574bfc7c6d54338b58bd7 (patch)
treec89a9f2716fdee0a3c11a28ab601ef94fb2d65fa /src/mongo/db/field_ref.cpp
parent6faea24a8e6889c7a46c8e1c305cfa9cd430b0e7 (diff)
downloadmongo-4616eae3efe8301ac12574bfc7c6d54338b58bd7.tar.gz
SERVER-10159 Re-serialize and cache dotted form in FieldRef on request
Diffstat (limited to 'src/mongo/db/field_ref.cpp')
-rw-r--r--src/mongo/db/field_ref.cpp75
1 files changed, 47 insertions, 28 deletions
diff --git a/src/mongo/db/field_ref.cpp b/src/mongo/db/field_ref.cpp
index 85d0c123fd9..15a1ed8c19f 100644
--- a/src/mongo/db/field_ref.cpp
+++ b/src/mongo/db/field_ref.cpp
@@ -108,6 +108,37 @@ namespace mongo {
return ++_size;
}
+ void FieldRef::reserialize() const {
+ std::string nextDotted;
+ // Reserve some space in the string. We know we will have, at minimum, a character for
+ // each component we are writing, and a dot for each component, less one. We don't want
+ // to reserve more, since we don't want to forfeit the SSO if it is applicable.
+ nextDotted.reserve((_size * 2) - 1);
+
+ // Concatenate the fields to a new string
+ for (size_t i = 0; i != _size; ++i) {
+ if (i > 0)
+ nextDotted.append(1, '.');
+ const StringData part = getPart(i);
+ nextDotted.append(part.rawData(), part.size());
+ }
+
+ // Make the new string our contents
+ _dotted.swap(nextDotted);
+
+ // Fixup the parts to refer to the new string
+ std::string::const_iterator where = _dotted.begin();
+ for (size_t i = 0; i != _size; ++i) {
+ StringData& part = (i < kReserveAhead) ? _fixed[i] : _variable[getIndex(i)];
+ const size_t size = part.size();
+ part = StringData(&*where, size);
+ where += (size + 1); // account for '.'
+ }
+
+ // Drop any replacements
+ _replacements.clear();
+ }
+
StringData FieldRef::getPart(size_t i) const {
dassert(i < _size);
@@ -152,25 +183,23 @@ namespace mongo {
return prefixSize;
}
- std::string FieldRef::dottedField( size_t offset ) const {
- std::string result;
+ StringData FieldRef::dottedField( size_t offset ) const {
+ if (_size == 0 || offset >= numParts() )
+ return StringData();
- if (_size == 0 || offset >= numParts() ) {
- // fall through, we will return the empty string.
- }
- else if (_replacements.empty() && (offset == 0)) {
- result = _dotted;
- }
- else {
- // Reserve some space in the string. We know we will have, at minimum, a character
- // for each component we are writing, and a dot for each component, less one.
- result.reserve(((_size - offset) * 2) - 1);
- for (size_t i=offset; i<_size; i++) {
- if ( i > offset )
- result.append(1, '.');
- StringData part = getPart(i);
- result.append(part.rawData(), part.size());
- }
+ if (!_replacements.empty())
+ reserialize();
+ dassert(_replacements.empty());
+
+ // Assume we want the whole thing
+ StringData result(_dotted);
+
+ // Strip off any leading parts we were asked to ignore
+ for (size_t i = 0; i < offset; ++i) {
+ const StringData part = getPart(i);
+ result = StringData(
+ result.rawData() + part.size() + 1,
+ result.size() - part.size() - 1);
}
return result;
@@ -231,16 +260,6 @@ namespace mongo {
_replacements.clear();
}
- size_t FieldRef::numReplaced() const {
- size_t res = 0;
- for (size_t i = 0; i < _replacements.size(); i++) {
- if (!_replacements[i].empty()) {
- res++;
- }
- }
- return res;
- }
-
std::ostream& operator<<(std::ostream& stream, const FieldRef& field) {
return stream << field.dottedField();
}