diff options
Diffstat (limited to 'src/mongo/db/ops/log_builder.cpp')
-rw-r--r-- | src/mongo/db/ops/log_builder.cpp | 235 |
1 files changed, 110 insertions, 125 deletions
diff --git a/src/mongo/db/ops/log_builder.cpp b/src/mongo/db/ops/log_builder.cpp index 437c9056e5e..21baffe246c 100644 --- a/src/mongo/db/ops/log_builder.cpp +++ b/src/mongo/db/ops/log_builder.cpp @@ -31,143 +31,128 @@ namespace mongo { - using mutablebson::Document; - using mutablebson::Element; - namespace str = mongoutils::str; - - namespace { - const char kSet[] = "$set"; - const char kUnset[] = "$unset"; - } // namespace - - inline Status LogBuilder::addToSection(Element newElt, - Element* section, - const char* sectionName) { - - // If we don't already have this section, try to create it now. - if (!section->ok()) { - - // If we already have object replacement data, we can't also have section entries. - if (hasObjectReplacement()) - return Status( - ErrorCodes::IllegalOperation, - "LogBuilder: Invalid attempt to add a $set/$unset entry" - "to a log with an existing object replacement"); - - Document& doc = _logRoot.getDocument(); - - // We should not already have an element with the section name under the root. - dassert(_logRoot[sectionName] == doc.end()); - - // Construct a new object element to represent this section in the log. - const Element newElement = doc.makeElementObject(sectionName); - if (!newElement.ok()) - return Status(ErrorCodes::InternalError, - "LogBuilder: failed to construct Object Element for $set/$unset"); - - // Enqueue the new section under the root, and record it as our out parameter. - Status result = _logRoot.pushBack(newElement); - if (!result.isOK()) - return result; - *section = newElement; - - // Invalidate attempts to add an object replacement, now that we have a named - // section under the root. - _objectReplacementAccumulator = doc.end(); - } - - // Whatever transpired, we should now have an ok accumulator for the section, and not - // have a replacement accumulator. - dassert(section->ok()); - dassert(!_objectReplacementAccumulator.ok()); - - // Enqueue the provided element to the section and propagate the result. - return section->pushBack(newElt); - } - - Status LogBuilder::addToSets(Element elt) { - return addToSection(elt, &_setAccumulator, kSet); - } +using mutablebson::Document; +using mutablebson::Element; +namespace str = mongoutils::str; + +namespace { +const char kSet[] = "$set"; +const char kUnset[] = "$unset"; +} // namespace + +inline Status LogBuilder::addToSection(Element newElt, Element* section, const char* sectionName) { + // If we don't already have this section, try to create it now. + if (!section->ok()) { + // If we already have object replacement data, we can't also have section entries. + if (hasObjectReplacement()) + return Status(ErrorCodes::IllegalOperation, + "LogBuilder: Invalid attempt to add a $set/$unset entry" + "to a log with an existing object replacement"); - Status LogBuilder::addToSetsWithNewFieldName(StringData name, - const mutablebson::Element val) { - mutablebson::Element elemToSet = - _logRoot.getDocument().makeElementWithNewFieldName(name, val); - if (!elemToSet.ok()) - return Status(ErrorCodes::InternalError, - str::stream() << "Could not create new '" - << name << "' element from existing element '" - << val.getFieldName() << "' of type " - << typeName(val.getType())); + Document& doc = _logRoot.getDocument(); - return addToSets(elemToSet); - } + // We should not already have an element with the section name under the root. + dassert(_logRoot[sectionName] == doc.end()); - Status LogBuilder::addToSetsWithNewFieldName(StringData name, - const BSONElement& val){ - mutablebson::Element elemToSet = - _logRoot.getDocument().makeElementWithNewFieldName(name, val); - if (!elemToSet.ok()) + // Construct a new object element to represent this section in the log. + const Element newElement = doc.makeElementObject(sectionName); + if (!newElement.ok()) return Status(ErrorCodes::InternalError, - str::stream() << "Could not create new '" - << name << "' element from existing element '" - << val.fieldName() << "' of type " - << typeName(val.type())); + "LogBuilder: failed to construct Object Element for $set/$unset"); - return addToSets(elemToSet); - } + // Enqueue the new section under the root, and record it as our out parameter. + Status result = _logRoot.pushBack(newElement); + if (!result.isOK()) + return result; + *section = newElement; - Status LogBuilder::addToSets(StringData name, const SafeNum& val){ - mutablebson::Element elemToSet = _logRoot.getDocument().makeElementSafeNum(name, val); - if (!elemToSet.ok()) - return Status(ErrorCodes::InternalError, - str::stream() << "Could not create new '" - << name << "' SafeNum from " - << val.debugString()); - - return addToSets(elemToSet); + // Invalidate attempts to add an object replacement, now that we have a named + // section under the root. + _objectReplacementAccumulator = doc.end(); } - Status LogBuilder::addToUnsets(StringData path) { - mutablebson::Element logElement = _logRoot.getDocument().makeElementBool(path, true); - if (!logElement.ok()) - return Status(ErrorCodes::InternalError, - str::stream() << "Cannot create $unset oplog entry for path" << path); - - return addToSection(logElement, &_unsetAccumulator, kUnset); + // Whatever transpired, we should now have an ok accumulator for the section, and not + // have a replacement accumulator. + dassert(section->ok()); + dassert(!_objectReplacementAccumulator.ok()); + + // Enqueue the provided element to the section and propagate the result. + return section->pushBack(newElt); +} + +Status LogBuilder::addToSets(Element elt) { + return addToSection(elt, &_setAccumulator, kSet); +} + +Status LogBuilder::addToSetsWithNewFieldName(StringData name, const mutablebson::Element val) { + mutablebson::Element elemToSet = _logRoot.getDocument().makeElementWithNewFieldName(name, val); + if (!elemToSet.ok()) + return Status(ErrorCodes::InternalError, + str::stream() << "Could not create new '" << name + << "' element from existing element '" << val.getFieldName() + << "' of type " << typeName(val.getType())); + + return addToSets(elemToSet); +} + +Status LogBuilder::addToSetsWithNewFieldName(StringData name, const BSONElement& val) { + mutablebson::Element elemToSet = _logRoot.getDocument().makeElementWithNewFieldName(name, val); + if (!elemToSet.ok()) + return Status(ErrorCodes::InternalError, + str::stream() << "Could not create new '" << name + << "' element from existing element '" << val.fieldName() + << "' of type " << typeName(val.type())); + + return addToSets(elemToSet); +} + +Status LogBuilder::addToSets(StringData name, const SafeNum& val) { + mutablebson::Element elemToSet = _logRoot.getDocument().makeElementSafeNum(name, val); + if (!elemToSet.ok()) + return Status(ErrorCodes::InternalError, + str::stream() << "Could not create new '" << name << "' SafeNum from " + << val.debugString()); + + return addToSets(elemToSet); +} + +Status LogBuilder::addToUnsets(StringData path) { + mutablebson::Element logElement = _logRoot.getDocument().makeElementBool(path, true); + if (!logElement.ok()) + return Status(ErrorCodes::InternalError, + str::stream() << "Cannot create $unset oplog entry for path" << path); + + return addToSection(logElement, &_unsetAccumulator, kUnset); +} + +Status LogBuilder::getReplacementObject(Element* outElt) { + // If the replacement accumulator is not ok, we must have started a $set or $unset + // already, so an object replacement is not permitted. + if (!_objectReplacementAccumulator.ok()) { + dassert(_setAccumulator.ok() || _unsetAccumulator.ok()); + return Status(ErrorCodes::IllegalOperation, + "LogBuilder: Invalid attempt to obtain the object replacement slot " + "for a log containing $set or $unset entries"); } - Status LogBuilder::getReplacementObject(Element* outElt) { + if (hasObjectReplacement()) + return Status(ErrorCodes::IllegalOperation, + "LogBuilder: Invalid attempt to acquire the replacement object " + "in a log with existing object replacement data"); - // If the replacement accumulator is not ok, we must have started a $set or $unset - // already, so an object replacement is not permitted. - if (!_objectReplacementAccumulator.ok()) { - dassert(_setAccumulator.ok() || _unsetAccumulator.ok()); - return Status( - ErrorCodes::IllegalOperation, - "LogBuilder: Invalid attempt to obtain the object replacement slot " - "for a log containing $set or $unset entries"); - } + // OK to enqueue object replacement items. + *outElt = _objectReplacementAccumulator; + return Status::OK(); +} - if (hasObjectReplacement()) - return Status( - ErrorCodes::IllegalOperation, - "LogBuilder: Invalid attempt to acquire the replacement object " - "in a log with existing object replacement data"); - - // OK to enqueue object replacement items. - *outElt = _objectReplacementAccumulator; - return Status::OK(); - } - - inline bool LogBuilder::hasObjectReplacement() const { - if (!_objectReplacementAccumulator.ok()) - return false; +inline bool LogBuilder::hasObjectReplacement() const { + if (!_objectReplacementAccumulator.ok()) + return false; - dassert(!_setAccumulator.ok()); - dassert(!_unsetAccumulator.ok()); + dassert(!_setAccumulator.ok()); + dassert(!_unsetAccumulator.ok()); - return _objectReplacementAccumulator.hasChildren(); - } + return _objectReplacementAccumulator.hasChildren(); +} -} // namespace mongo +} // namespace mongo |