Ejemplo n.º 1
0
void bLSM::insertTuple(dataTuple *tuple)
{
    if(log_mode && !recovering) {
        logUpdate(tuple);
        batch_size++;
        if(batch_size >= log_mode) {
        	log_file->force_tail(log_file, LOG_FORCE_COMMIT);
        	batch_size = 0;
        }
    }
    // Note, this is where we block for backpressure.  Do this without holding
    // any locks!
    merge_mgr->read_tuple_from_small_component(0, tuple);

    dataTuple * pre_t = 0; // this is a pointer to any data tuples that we'll be deleting below.  We need to update the merge_mgr statistics with it, but have to do so outside of the rb_mut region.

    pre_t = insertTupleHelper(tuple);

    if(pre_t) {
      // needs to be here; calls update_progress, which sometimes grabs mutexes..
      merge_mgr->read_tuple_from_large_component(0, pre_t);  // was interspersed with the erase, insert above...
      dataTuple::freetuple(pre_t); //free the previous tuple
    }

    DEBUG("tree size %d tuples %lld bytes.\n", tsize, tree_bytes);
}
Ejemplo n.º 2
0
void bLSM::insertManyTuples(dataTuple ** tuples, int tuple_count) {
  for(int i = 0; i < tuple_count; i++) {
    merge_mgr->read_tuple_from_small_component(0, tuples[i]);
  }
  if(log_mode && !recovering) {
	  for(int i = 0; i < tuple_count; i++) {
	    logUpdate(tuples[i]);
	  }
	  batch_size ++;
	  if(batch_size >= log_mode) {
		  log_file->force_tail(log_file, LOG_FORCE_COMMIT);
		  batch_size = 0;
	  }
  }

  int num_old_tups = 0;
  pageid_t sum_old_tup_lens = 0;
  for(int i = 0; i < tuple_count; i++) {
    dataTuple * old_tup = insertTupleHelper(tuples[i]);
    if(old_tup) {
      num_old_tups++;
      sum_old_tup_lens += old_tup->byte_length();
      dataTuple::freetuple(old_tup);
    }
  }

  merge_mgr->read_tuple_from_large_component(0, num_old_tups, sum_old_tup_lens);
}
Ejemplo n.º 3
0
UpdateNode::ApplyResult ModifierNode::applyToNonexistentElement(ApplyParams applyParams) const {
    if (allowCreation()) {
        auto newElementFieldName =
            applyParams.pathToCreate->getPart(applyParams.pathToCreate->numParts() - 1);
        auto newElement = applyParams.element.getDocument().makeElementNull(newElementFieldName);
        setValueForNewElement(&newElement);

        invariant(newElement.ok());
        auto statusWithFirstCreatedElem = pathsupport::createPathAt(
            *(applyParams.pathToCreate), 0, applyParams.element, newElement);
        if (!statusWithFirstCreatedElem.isOK()) {
            // $set operaions on non-viable paths are ignored when the update came from replication.
            // We do not error because idempotency requires that any other update modifiers must
            // still be applied. For example, consider applying the following updates twice to an
            // initially empty document:
            // {$set: {c: 0}}
            // {$set: {'a.b': 0, c: 1}}
            // {$set: {a: 0}}
            // Setting 'a.b' will fail the second time, but we must still set 'c'.
            // (There are modifiers besides $set that use this code path, but they are not used for
            // replication, so we are not concerned with their behavior when "fromReplication" is
            // true.)
            if (statusWithFirstCreatedElem.getStatus().code() == ErrorCodes::PathNotViable &&
                applyParams.fromReplication) {
                return ApplyResult::noopResult();
            }
            uassertStatusOK(statusWithFirstCreatedElem);
            MONGO_UNREACHABLE;  // The previous uassertStatusOK should always throw.
        }

        if (applyParams.validateForStorage) {
            const uint32_t recursionLevel = applyParams.pathTaken->numParts() + 1;
            mutablebson::ConstElement elementForValidation = statusWithFirstCreatedElem.getValue();
            validateUpdate(elementForValidation,
                           elementForValidation.leftSibling(),
                           elementForValidation.rightSibling(),
                           recursionLevel,
                           ModifyResult::kCreated);
        }

        for (auto immutablePath = applyParams.immutablePaths.begin();
             immutablePath != applyParams.immutablePaths.end();
             ++immutablePath) {

            // If 'immutablePath' is a (strict or non-strict) prefix of 'pathTaken', then we are
            // modifying 'immutablePath'. For example, adding '_id.x' will illegally modify '_id'.
            // (Note that this behavior is subtly different from checkImmutablePathsNotModified(),
            // because we just created this element.)
            uassert(ErrorCodes::ImmutableField,
                    str::stream() << "Updating the path '" << applyParams.pathTaken->dottedField()
                                  << "' to "
                                  << applyParams.element.toString()
                                  << " would modify the immutable field '"
                                  << (*immutablePath)->dottedField()
                                  << "'",
                    applyParams.pathTaken->commonPrefixSize(**immutablePath) !=
                        (*immutablePath)->numParts());
        }

        invariant(!applyParams.pathToCreate->empty());
        std::string fullPath;
        if (applyParams.pathTaken->empty()) {
            fullPath = applyParams.pathToCreate->dottedField().toString();
        } else {
            fullPath = str::stream() << applyParams.pathTaken->dottedField() << "."
                                     << applyParams.pathToCreate->dottedField();
        }

        ApplyResult applyResult;

        // Determine if indexes are affected.
        if (!applyParams.indexData || !applyParams.indexData->mightBeIndexed(fullPath)) {
            applyResult.indexesAffected = false;
        }

        if (applyParams.logBuilder) {
            logUpdate(applyParams.logBuilder, fullPath, newElement, ModifyResult::kCreated);
        }

        return applyResult;
    } else {
        // This path is for modifiers like $pop or $pull that generally have no effect when applied
        // to a path that does not exist.
        if (!allowNonViablePath()) {
            // One exception: some of these modifiers still fail when the nonexistent path is
            // "non-viable," meaning it couldn't be created even if we intended to.
            UpdateLeafNode::checkViability(
                applyParams.element, *(applyParams.pathToCreate), *(applyParams.pathTaken));
        }

        return ApplyResult::noopResult();
    }
}
Ejemplo n.º 4
0
UpdateNode::ApplyResult ModifierNode::applyToExistingElement(ApplyParams applyParams) const {
    invariant(!applyParams.pathTaken->empty());
    invariant(applyParams.pathToCreate->empty());
    invariant(applyParams.element.ok());

    mutablebson::ConstElement leftSibling = applyParams.element.leftSibling();
    mutablebson::ConstElement rightSibling = applyParams.element.rightSibling();

    bool compareWithOriginal = false;
    if (canSetObjectValue()) {
        for (auto immutablePath = applyParams.immutablePaths.begin();
             immutablePath != applyParams.immutablePaths.end();
             ++immutablePath) {
            if (applyParams.pathTaken->isPrefixOf(**immutablePath)) {
                compareWithOriginal = true;
                break;
            }
        }
    }

    // We have two different ways of checking for changes to immutable paths, depending on the style
    // of update. See the comments above checkImmutablePathsNotModifiedFromOriginal() and
    // checkImmutablePathsNotModified().
    ModifyResult updateResult;
    if (compareWithOriginal) {
        BSONObj original = applyParams.element.getDocument().getObject();
        updateResult = updateExistingElement(&applyParams.element, applyParams.pathTaken);
        if (updateResult == ModifyResult::kNoOp) {
            return ApplyResult::noopResult();
        }
        checkImmutablePathsNotModifiedFromOriginal(
            applyParams.element, applyParams.pathTaken.get(), applyParams.immutablePaths, original);
    } else {
        updateResult = updateExistingElement(&applyParams.element, applyParams.pathTaken);
        if (updateResult == ModifyResult::kNoOp) {
            return ApplyResult::noopResult();
        }
        checkImmutablePathsNotModified(
            applyParams.element, applyParams.pathTaken.get(), applyParams.immutablePaths);
    }
    invariant(updateResult != ModifyResult::kCreated);

    ApplyResult applyResult;

    if (!applyParams.indexData ||
        !applyParams.indexData->mightBeIndexed(applyParams.pathTaken->dottedField())) {
        applyResult.indexesAffected = false;
    }

    if (applyParams.validateForStorage) {
        const uint32_t recursionLevel = applyParams.pathTaken->numParts();
        validateUpdate(
            applyParams.element, leftSibling, rightSibling, recursionLevel, updateResult);
    }

    if (applyParams.logBuilder) {
        logUpdate(applyParams.logBuilder,
                  applyParams.pathTaken->dottedField(),
                  applyParams.element,
                  updateResult);
    }

    return applyResult;
}