本文整理汇总了C++中Snapshotted::value方法的典型用法代码示例。如果您正苦于以下问题:C++ Snapshotted::value方法的具体用法?C++ Snapshotted::value怎么用?C++ Snapshotted::value使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Snapshotted
的用法示例。
在下文中一共展示了Snapshotted::value方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: deleteDocument
void Collection::deleteDocument(
OperationContext* txn, const RecordId& loc, bool cappedOK, bool noWarn, BSONObj* deletedId) {
if (isCapped() && !cappedOK) {
log() << "failing remove on a capped ns " << _ns << endl;
uasserted(10089, "cannot remove from a capped collection");
return;
}
Snapshotted<BSONObj> doc = docFor(txn, loc);
BSONElement e = doc.value()["_id"];
BSONObj id;
if (e.type()) {
id = e.wrap();
if (deletedId) {
*deletedId = e.wrap();
}
}
/* check if any cursors point to us. if so, advance them. */
_cursorManager.invalidateDocument(txn, loc, INVALIDATION_DELETION);
_indexCatalog.unindexRecord(txn, doc.value(), loc, noWarn);
_recordStore->deleteRecord(txn, loc);
if (!id.isEmpty()) {
getGlobalServiceContext()->getOpObserver()->onDelete(txn, ns().ns(), id);
}
}
示例2: getNext
PlanExecutor::ExecState PlanExecutor::getNext(BSONObj* objOut, RecordId* dlOut) {
Snapshotted<BSONObj> snapshotted;
ExecState state = getNextImpl(objOut ? &snapshotted : NULL, dlOut);
if (objOut) {
*objOut = snapshotted.value();
}
return state;
}
示例3: deleteDocument
void Collection::deleteDocument(
OperationContext* txn, const RecordId& loc, bool fromMigrate, bool cappedOK, bool noWarn) {
if (isCapped() && !cappedOK) {
log() << "failing remove on a capped ns " << _ns << endl;
uasserted(10089, "cannot remove from a capped collection");
return;
}
Snapshotted<BSONObj> doc = docFor(txn, loc);
auto opObserver = getGlobalServiceContext()->getOpObserver();
OpObserver::DeleteState deleteState = opObserver->aboutToDelete(txn, ns(), doc.value());
/* check if any cursors point to us. if so, advance them. */
_cursorManager.invalidateDocument(txn, loc, INVALIDATION_DELETION);
_indexCatalog.unindexRecord(txn, doc.value(), loc, noWarn);
_recordStore->deleteRecord(txn, loc);
opObserver->onDelete(txn, ns(), std::move(deleteState), fromMigrate);
}
示例4: nextCloneBatch
Status MigrationChunkClonerSourceLegacy::nextCloneBatch(OperationContext* txn,
Collection* collection,
BSONArrayBuilder* arrBuilder) {
dassert(txn->lockState()->isCollectionLockedForMode(_args.getNss().ns(), MODE_IS));
ElapsedTracker tracker(txn->getServiceContext()->getFastClockSource(),
internalQueryExecYieldIterations,
Milliseconds(internalQueryExecYieldPeriodMS.load()));
stdx::lock_guard<stdx::mutex> sl(_mutex);
std::set<RecordId>::iterator it;
for (it = _cloneLocs.begin(); it != _cloneLocs.end(); ++it) {
// We must always make progress in this method by at least one document because empty return
// indicates there is no more initial clone data.
if (arrBuilder->arrSize() && tracker.intervalHasElapsed()) {
break;
}
Snapshotted<BSONObj> doc;
if (collection->findDoc(txn, *it, &doc)) {
// Use the builder size instead of accumulating the document sizes directly so that we
// take into consideration the overhead of BSONArray indices.
if (arrBuilder->arrSize() &&
(arrBuilder->len() + doc.value().objsize() + 1024) > BSONObjMaxUserSize) {
break;
}
arrBuilder->append(doc.value());
}
}
_cloneLocs.erase(_cloneLocs.begin(), it);
return Status::OK();
}
示例5: dassert
StatusWith<RecordData> Collection::updateDocumentWithDamages(
OperationContext* txn,
const RecordId& loc,
const Snapshotted<RecordData>& oldRec,
const char* damageSource,
const mutablebson::DamageVector& damages,
oplogUpdateEntryArgs& args) {
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_IX));
invariant(oldRec.snapshotId() == txn->recoveryUnit()->getSnapshotId());
invariant(updateWithDamagesSupported());
// Broadcast the mutation so that query results stay correct.
_cursorManager.invalidateDocument(txn, loc, INVALIDATION_MUTATION);
auto newRecStatus =
_recordStore->updateWithDamages(txn, loc, oldRec.value(), damageSource, damages);
if (newRecStatus.isOK()) {
args.ns = ns().ns();
getGlobalServiceContext()->getOpObserver()->onUpdate(txn, args);
}
return newRecStatus;
}
示例6: insertAllDocumentsInCollection
Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsOut) {
const char* curopMessage = _buildInBackground ? "Index Build (background)" : "Index Build";
const auto numRecords = _collection->numRecords(_txn);
stdx::unique_lock<Client> lk(*_txn->getClient());
ProgressMeterHolder progress(*_txn->setMessage_inlock(curopMessage, curopMessage, numRecords));
lk.unlock();
Timer t;
unsigned long long n = 0;
unique_ptr<PlanExecutor> exec(InternalPlanner::collectionScan(
_txn, _collection->ns().ns(), _collection, PlanExecutor::YIELD_MANUAL));
if (_buildInBackground) {
invariant(_allowInterruption);
exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
} else {
exec->setYieldPolicy(PlanExecutor::WRITE_CONFLICT_RETRY_ONLY);
}
Snapshotted<BSONObj> objToIndex;
RecordId loc;
PlanExecutor::ExecState state;
int retries = 0; // non-zero when retrying our last document.
while (retries ||
(PlanExecutor::ADVANCED == (state = exec->getNextSnapshotted(&objToIndex, &loc)))) {
try {
if (_allowInterruption)
_txn->checkForInterrupt();
// Make sure we are working with the latest version of the document.
if (objToIndex.snapshotId() != _txn->recoveryUnit()->getSnapshotId() &&
!_collection->findDoc(_txn, loc, &objToIndex)) {
// doc was deleted so don't index it.
retries = 0;
continue;
}
// Done before insert so we can retry document if it WCEs.
progress->setTotalWhileRunning(_collection->numRecords(_txn));
WriteUnitOfWork wunit(_txn);
Status ret = insert(objToIndex.value(), loc);
if (_buildInBackground)
exec->saveState();
if (ret.isOK()) {
wunit.commit();
} else if (dupsOut && ret.code() == ErrorCodes::DuplicateKey) {
// If dupsOut is non-null, we should only fail the specific insert that
// led to a DuplicateKey rather than the whole index build.
dupsOut->insert(loc);
} else {
// Fail the index build hard.
return ret;
}
if (_buildInBackground)
exec->restoreState(); // Handles any WCEs internally.
// Go to the next document
progress->hit();
n++;
retries = 0;
} catch (const WriteConflictException& wce) {
CurOp::get(_txn)->debug().writeConflicts++;
retries++; // logAndBackoff expects this to be 1 on first call.
wce.logAndBackoff(retries, "index creation", _collection->ns().ns());
// Can't use WRITE_CONFLICT_RETRY_LOOP macros since we need to save/restore exec
// around call to abandonSnapshot.
exec->saveState();
_txn->recoveryUnit()->abandonSnapshot();
exec->restoreState(); // Handles any WCEs internally.
}
}
uassert(28550,
"Unable to complete index build due to collection scan failure: " +
WorkingSetCommon::toStatusString(objToIndex.value()),
state == PlanExecutor::IS_EOF);
progress->finished();
Status ret = doneInserting(dupsOut);
if (!ret.isOK())
return ret;
log() << "build index done. scanned " << n << " total records. " << t.seconds() << " secs"
<< endl;
return Status::OK();
}
示例7: checkValidation
StatusWith<RecordId> Collection::updateDocument(OperationContext* txn,
const RecordId& oldLocation,
const Snapshotted<BSONObj>& oldDoc,
const BSONObj& newDoc,
bool enforceQuota,
bool indexesAffected,
OpDebug* debug,
oplogUpdateEntryArgs& args) {
{
auto status = checkValidation(txn, newDoc);
if (!status.isOK()) {
if (_validationLevel == STRICT_V) {
return status;
}
// moderate means we have to check the old doc
auto oldDocStatus = checkValidation(txn, oldDoc.value());
if (oldDocStatus.isOK()) {
// transitioning from good -> bad is not ok
return status;
}
// bad -> bad is ok in moderate mode
}
}
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_IX));
invariant(oldDoc.snapshotId() == txn->recoveryUnit()->getSnapshotId());
if (_needCappedLock) {
// X-lock the metadata resource for this capped collection until the end of the WUOW. This
// prevents the primary from executing with more concurrency than secondaries.
// See SERVER-21646.
Lock::ResourceLock{txn->lockState(), ResourceId(RESOURCE_METADATA, _ns.ns()), MODE_X};
}
SnapshotId sid = txn->recoveryUnit()->getSnapshotId();
BSONElement oldId = oldDoc.value()["_id"];
if (!oldId.eoo() && (oldId != newDoc["_id"]))
return StatusWith<RecordId>(
ErrorCodes::InternalError, "in Collection::updateDocument _id mismatch", 13596);
// The MMAPv1 storage engine implements capped collections in a way that does not allow records
// to grow beyond their original size. If MMAPv1 part of a replicaset with storage engines that
// do not have this limitation, replication could result in errors, so it is necessary to set a
// uniform rule here. Similarly, it is not sufficient to disallow growing records, because this
// happens when secondaries roll back an update shrunk a record. Exactly replicating legacy
// MMAPv1 behavior would require padding shrunk documents on all storage engines. Instead forbid
// all size changes.
const auto oldSize = oldDoc.value().objsize();
if (_recordStore->isCapped() && oldSize != newDoc.objsize())
return {ErrorCodes::CannotGrowDocumentInCappedNamespace,
str::stream() << "Cannot change the size of a document in a capped collection: "
<< oldSize << " != " << newDoc.objsize()};
// At the end of this step, we will have a map of UpdateTickets, one per index, which
// represent the index updates needed to be done, based on the changes between oldDoc and
// newDoc.
OwnedPointerMap<IndexDescriptor*, UpdateTicket> updateTickets;
if (indexesAffected) {
IndexCatalog::IndexIterator ii = _indexCatalog.getIndexIterator(txn, true);
while (ii.more()) {
IndexDescriptor* descriptor = ii.next();
IndexCatalogEntry* entry = ii.catalogEntry(descriptor);
IndexAccessMethod* iam = ii.accessMethod(descriptor);
InsertDeleteOptions options;
options.logIfError = false;
options.dupsAllowed =
!(KeyPattern::isIdKeyPattern(descriptor->keyPattern()) || descriptor->unique()) ||
repl::getGlobalReplicationCoordinator()->shouldIgnoreUniqueIndex(descriptor);
UpdateTicket* updateTicket = new UpdateTicket();
updateTickets.mutableMap()[descriptor] = updateTicket;
Status ret = iam->validateUpdate(txn,
oldDoc.value(),
newDoc,
oldLocation,
options,
updateTicket,
entry->getFilterExpression());
if (!ret.isOK()) {
return StatusWith<RecordId>(ret);
}
}
}
// This can call back into Collection::recordStoreGoingToMove. If that happens, the old
// object is removed from all indexes.
StatusWith<RecordId> newLocation = _recordStore->updateRecord(
txn, oldLocation, newDoc.objdata(), newDoc.objsize(), _enforceQuota(enforceQuota), this);
if (!newLocation.isOK()) {
return newLocation;
}
// At this point, the old object may or may not still be indexed, depending on if it was
// moved. If the object did move, we need to add the new location to all indexes.
if (newLocation.getValue() != oldLocation) {
if (debug) {
if (debug->nmoved == -1) // default of -1 rather than 0
debug->nmoved = 1;
//.........这里部分代码省略.........
示例8: checkValidation
StatusWith<RecordId> Collection::updateDocument(OperationContext* txn,
const RecordId& oldLocation,
const Snapshotted<BSONObj>& oldDoc,
const BSONObj& newDoc,
bool enforceQuota,
bool indexesAffected,
OpDebug* debug,
oplogUpdateEntryArgs& args) {
{
auto status = checkValidation(txn, newDoc);
if (!status.isOK()) {
if (_validationLevel == STRICT_V) {
return status;
}
// moderate means we have to check the old doc
auto oldDocStatus = checkValidation(txn, oldDoc.value());
if (oldDocStatus.isOK()) {
// transitioning from good -> bad is not ok
return status;
}
// bad -> bad is ok in moderate mode
}
}
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_IX));
invariant(oldDoc.snapshotId() == txn->recoveryUnit()->getSnapshotId());
SnapshotId sid = txn->recoveryUnit()->getSnapshotId();
BSONElement oldId = oldDoc.value()["_id"];
if (!oldId.eoo() && (oldId != newDoc["_id"]))
return StatusWith<RecordId>(
ErrorCodes::InternalError, "in Collection::updateDocument _id mismatch", 13596);
// At the end of this step, we will have a map of UpdateTickets, one per index, which
// represent the index updates needed to be done, based on the changes between oldDoc and
// newDoc.
OwnedPointerMap<IndexDescriptor*, UpdateTicket> updateTickets;
if (indexesAffected) {
IndexCatalog::IndexIterator ii = _indexCatalog.getIndexIterator(txn, true);
while (ii.more()) {
IndexDescriptor* descriptor = ii.next();
IndexCatalogEntry* entry = ii.catalogEntry(descriptor);
IndexAccessMethod* iam = ii.accessMethod(descriptor);
InsertDeleteOptions options;
options.logIfError = false;
options.dupsAllowed =
!(KeyPattern::isIdKeyPattern(descriptor->keyPattern()) || descriptor->unique()) ||
repl::getGlobalReplicationCoordinator()->shouldIgnoreUniqueIndex(descriptor);
UpdateTicket* updateTicket = new UpdateTicket();
updateTickets.mutableMap()[descriptor] = updateTicket;
Status ret = iam->validateUpdate(txn,
oldDoc.value(),
newDoc,
oldLocation,
options,
updateTicket,
entry->getFilterExpression());
if (!ret.isOK()) {
return StatusWith<RecordId>(ret);
}
}
}
// This can call back into Collection::recordStoreGoingToMove. If that happens, the old
// object is removed from all indexes.
StatusWith<RecordId> newLocation = _recordStore->updateRecord(
txn, oldLocation, newDoc.objdata(), newDoc.objsize(), _enforceQuota(enforceQuota), this);
if (!newLocation.isOK()) {
return newLocation;
}
// At this point, the old object may or may not still be indexed, depending on if it was
// moved. If the object did move, we need to add the new location to all indexes.
if (newLocation.getValue() != oldLocation) {
if (debug) {
if (debug->nmoved == -1) // default of -1 rather than 0
debug->nmoved = 1;
else
debug->nmoved += 1;
}
Status s = _indexCatalog.indexRecord(txn, newDoc, newLocation.getValue());
if (!s.isOK())
return StatusWith<RecordId>(s);
invariant(sid == txn->recoveryUnit()->getSnapshotId());
args.ns = ns().ns();
getGlobalServiceContext()->getOpObserver()->onUpdate(txn, args);
return newLocation;
}
// Object did not move. We update each index with each respective UpdateTicket.
if (debug)
debug->keyUpdates = 0;
if (indexesAffected) {
//.........这里部分代码省略.........
示例9: clone
bool MigrationSourceManager::clone(OperationContext* txn, string& errmsg, BSONObjBuilder& result) {
ElapsedTracker tracker(internalQueryExecYieldIterations, internalQueryExecYieldPeriodMS);
int allocSize = 0;
{
AutoGetCollection autoColl(txn, _getNS(), MODE_IS);
stdx::lock_guard<stdx::mutex> sl(_mutex);
if (!_active) {
errmsg = "not active";
return false;
}
Collection* collection = autoColl.getCollection();
if (!collection) {
errmsg = str::stream() << "collection " << _nss.toString() << " does not exist";
return false;
}
allocSize = std::min(
BSONObjMaxUserSize,
static_cast<int>((12 + collection->averageObjectSize(txn)) * cloneLocsRemaining()));
}
bool isBufferFilled = false;
BSONArrayBuilder clonedDocsArrayBuilder(allocSize);
while (!isBufferFilled) {
AutoGetCollection autoColl(txn, _getNS(), MODE_IS);
stdx::lock_guard<stdx::mutex> sl(_mutex);
if (!_active) {
errmsg = "not active";
return false;
}
// TODO: fix SERVER-16540 race
Collection* collection = autoColl.getCollection();
if (!collection) {
errmsg = str::stream() << "collection " << _nss.toString() << " does not exist";
return false;
}
stdx::lock_guard<stdx::mutex> lk(_cloneLocsMutex);
std::set<RecordId>::iterator cloneLocsIter = _cloneLocs.begin();
for (; cloneLocsIter != _cloneLocs.end(); ++cloneLocsIter) {
if (tracker.intervalHasElapsed()) // should I yield?
break;
RecordId recordId = *cloneLocsIter;
Snapshotted<BSONObj> doc;
if (!collection->findDoc(txn, recordId, &doc)) {
// doc was deleted
continue;
}
// Use the builder size instead of accumulating 'doc's size so that we take
// into consideration the overhead of BSONArray indices, and *always*
// append one doc.
if (clonedDocsArrayBuilder.arrSize() != 0 &&
(clonedDocsArrayBuilder.len() + doc.value().objsize() + 1024) >
BSONObjMaxUserSize) {
isBufferFilled = true; // break out of outer while loop
break;
}
clonedDocsArrayBuilder.append(doc.value());
}
_cloneLocs.erase(_cloneLocs.begin(), cloneLocsIter);
// Note: must be holding _cloneLocsMutex, don't move this inside while condition!
if (_cloneLocs.empty()) {
break;
}
}
result.appendArray("objects", clonedDocsArrayBuilder.arr());
return true;
}
示例10: transformAndUpdate
BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj, RecordId& recordId) {
const UpdateRequest* request = _params.request;
UpdateDriver* driver = _params.driver;
CanonicalQuery* cq = _params.canonicalQuery;
UpdateLifecycle* lifecycle = request->getLifecycle();
// If asked to return new doc, default to the oldObj, in case nothing changes.
BSONObj newObj = oldObj.value();
// Ask the driver to apply the mods. It may be that the driver can apply those "in
// place", that is, some values of the old document just get adjusted without any
// change to the binary layout on the bson layer. It may be that a whole new document
// is needed to accomodate the new bson layout of the resulting document. In any event,
// only enable in-place mutations if the underlying storage engine offers support for
// writing damage events.
_doc.reset(oldObj.value(),
(_collection->updateWithDamagesSupported()
? mutablebson::Document::kInPlaceEnabled
: mutablebson::Document::kInPlaceDisabled));
BSONObj logObj;
bool docWasModified = false;
Status status = Status::OK();
const bool validateForStorage = getOpCtx()->writesAreReplicated() && _enforceOkForStorage;
FieldRefSet immutablePaths;
if (getOpCtx()->writesAreReplicated() && !request->isFromMigration()) {
if (lifecycle) {
auto immutablePathsVector =
getImmutableFields(getOpCtx(), request->getNamespaceString());
if (immutablePathsVector) {
immutablePaths.fillFrom(
transitional_tools_do_not_use::unspool_vector(*immutablePathsVector));
}
}
immutablePaths.keepShortest(&idFieldRef);
}
if (!driver->needMatchDetails()) {
// If we don't need match details, avoid doing the rematch
status = driver->update(
StringData(), &_doc, validateForStorage, immutablePaths, &logObj, &docWasModified);
} else {
// If there was a matched field, obtain it.
MatchDetails matchDetails;
matchDetails.requestElemMatchKey();
dassert(cq);
verify(cq->root()->matchesBSON(oldObj.value(), &matchDetails));
string matchedField;
if (matchDetails.hasElemMatchKey())
matchedField = matchDetails.elemMatchKey();
status = driver->update(
matchedField, &_doc, validateForStorage, immutablePaths, &logObj, &docWasModified);
}
if (!status.isOK()) {
uasserted(16837, status.reason());
}
// Skip adding _id field if the collection is capped (since capped collection documents can
// neither grow nor shrink).
const auto createIdField = !_collection->isCapped();
// Ensure if _id exists it is first
status = ensureIdFieldIsFirst(&_doc);
if (status.code() == ErrorCodes::InvalidIdField) {
// Create ObjectId _id field if we are doing that
if (createIdField) {
addObjectIDIdField(&_doc);
}
} else {
uassertStatusOK(status);
}
// See if the changes were applied in place
const char* source = NULL;
const bool inPlace = _doc.getInPlaceUpdates(&_damages, &source);
if (inPlace && _damages.empty()) {
// An interesting edge case. A modifier didn't notice that it was really a no-op
// during its 'prepare' phase. That represents a missed optimization, but we still
// shouldn't do any real work. Toggle 'docWasModified' to 'false'.
//
// Currently, an example of this is '{ $push : { x : {$each: [], $sort: 1} } }' when the 'x'
// array exists and is already sorted.
docWasModified = false;
}
if (docWasModified) {
// Prepare to write back the modified document
WriteUnitOfWork wunit(getOpCtx());
RecordId newRecordId;
OplogUpdateEntryArgs args;
if (!request->isExplain()) {
invariant(_collection);
//.........这里部分代码省略.........
示例11: cloneCollectionAsCapped
Status cloneCollectionAsCapped(OperationContext* txn,
Database* db,
const std::string& shortFrom,
const std::string& shortTo,
double size,
bool temp) {
std::string fromNs = db->name() + "." + shortFrom;
std::string toNs = db->name() + "." + shortTo;
Collection* fromCollection = db->getCollection(fromNs);
if (!fromCollection)
return Status(ErrorCodes::NamespaceNotFound,
str::stream() << "source collection " << fromNs << " does not exist");
if (db->getCollection(toNs))
return Status(ErrorCodes::NamespaceExists, "to collection already exists");
// create new collection
MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
const auto fromOptions =
fromCollection->getCatalogEntry()->getCollectionOptions(txn).toBSON();
OldClientContext ctx(txn, toNs);
BSONObjBuilder spec;
spec.appendBool("capped", true);
spec.append("size", size);
if (temp)
spec.appendBool("temp", true);
spec.appendElementsUnique(fromOptions);
WriteUnitOfWork wunit(txn);
Status status = userCreateNS(txn, ctx.db(), toNs, spec.done());
if (!status.isOK())
return status;
wunit.commit();
}
MONGO_WRITE_CONFLICT_RETRY_LOOP_END(txn, "cloneCollectionAsCapped", fromNs);
Collection* toCollection = db->getCollection(toNs);
invariant(toCollection); // we created above
// how much data to ignore because it won't fit anyway
// datasize and extentSize can't be compared exactly, so add some padding to 'size'
long long allocatedSpaceGuess =
std::max(static_cast<long long>(size * 2),
static_cast<long long>(toCollection->getRecordStore()->storageSize(txn) * 2));
long long excessSize = fromCollection->dataSize(txn) - allocatedSpaceGuess;
std::unique_ptr<PlanExecutor> exec(
InternalPlanner::collectionScan(txn, fromNs, fromCollection, InternalPlanner::FORWARD));
exec->setYieldPolicy(PlanExecutor::WRITE_CONFLICT_RETRY_ONLY);
Snapshotted<BSONObj> objToClone;
RecordId loc;
PlanExecutor::ExecState state = PlanExecutor::FAILURE; // suppress uninitialized warnings
DisableDocumentValidation validationDisabler(txn);
int retries = 0; // non-zero when retrying our last document.
while (true) {
if (!retries) {
state = exec->getNextSnapshotted(&objToClone, &loc);
}
switch (state) {
case PlanExecutor::IS_EOF:
return Status::OK();
case PlanExecutor::ADVANCED: {
if (excessSize > 0) {
// 4x is for padding, power of 2, etc...
excessSize -= (4 * objToClone.value().objsize());
continue;
}
break;
}
default:
// Unreachable as:
// 1) We require a read lock (at a minimum) on the "from" collection
// and won't yield, preventing collection drop and PlanExecutor::DEAD
// 2) PlanExecutor::FAILURE is only returned on PlanStage::FAILURE. The
// CollectionScan PlanStage does not have a FAILURE scenario.
// 3) All other PlanExecutor states are handled above
invariant(false);
}
try {
// Make sure we are working with the latest version of the document.
if (objToClone.snapshotId() != txn->recoveryUnit()->getSnapshotId() &&
!fromCollection->findDoc(txn, loc, &objToClone)) {
// doc was deleted so don't clone it.
retries = 0;
continue;
}
WriteUnitOfWork wunit(txn);
toCollection->insertDocument(txn, objToClone.value(), true, txn->writesAreReplicated());
wunit.commit();
//.........这里部分代码省略.........
示例12: cloneCollectionAsCapped
mongo::Status mongo::cloneCollectionAsCapped(OperationContext* opCtx,
Database* db,
const std::string& shortFrom,
const std::string& shortTo,
long long size,
bool temp) {
NamespaceString fromNss(db->name(), shortFrom);
NamespaceString toNss(db->name(), shortTo);
Collection* fromCollection = db->getCollection(opCtx, fromNss);
if (!fromCollection) {
if (db->getViewCatalog()->lookup(opCtx, fromNss.ns())) {
return Status(ErrorCodes::CommandNotSupportedOnView,
str::stream() << "cloneCollectionAsCapped not supported for views: "
<< fromNss.ns());
}
return Status(ErrorCodes::NamespaceNotFound,
str::stream() << "source collection " << fromNss.ns() << " does not exist");
}
if (fromNss.isDropPendingNamespace()) {
return Status(ErrorCodes::NamespaceNotFound,
str::stream() << "source collection " << fromNss.ns()
<< " is currently in a drop-pending state.");
}
if (db->getCollection(opCtx, toNss)) {
return Status(ErrorCodes::NamespaceExists,
str::stream() << "cloneCollectionAsCapped failed - destination collection "
<< toNss.ns()
<< " already exists. source collection: "
<< fromNss.ns());
}
// create new collection
{
auto options = fromCollection->getCatalogEntry()->getCollectionOptions(opCtx);
// The capped collection will get its own new unique id, as the conversion isn't reversible,
// so it can't be rolled back.
options.uuid.reset();
options.capped = true;
options.cappedSize = size;
if (temp)
options.temp = true;
BSONObjBuilder cmd;
cmd.append("create", toNss.coll());
cmd.appendElements(options.toBSON());
Status status = createCollection(opCtx, toNss.db().toString(), cmd.done());
if (!status.isOK())
return status;
}
Collection* toCollection = db->getCollection(opCtx, toNss);
invariant(toCollection); // we created above
// how much data to ignore because it won't fit anyway
// datasize and extentSize can't be compared exactly, so add some padding to 'size'
long long allocatedSpaceGuess =
std::max(static_cast<long long>(size * 2),
static_cast<long long>(toCollection->getRecordStore()->storageSize(opCtx) * 2));
long long excessSize = fromCollection->dataSize(opCtx) - allocatedSpaceGuess;
auto exec = InternalPlanner::collectionScan(opCtx,
fromNss.ns(),
fromCollection,
PlanExecutor::WRITE_CONFLICT_RETRY_ONLY,
InternalPlanner::FORWARD);
Snapshotted<BSONObj> objToClone;
RecordId loc;
PlanExecutor::ExecState state = PlanExecutor::FAILURE; // suppress uninitialized warnings
DisableDocumentValidation validationDisabler(opCtx);
int retries = 0; // non-zero when retrying our last document.
while (true) {
if (!retries) {
state = exec->getNextSnapshotted(&objToClone, &loc);
}
switch (state) {
case PlanExecutor::IS_EOF:
return Status::OK();
case PlanExecutor::ADVANCED: {
if (excessSize > 0) {
// 4x is for padding, power of 2, etc...
excessSize -= (4 * objToClone.value().objsize());
continue;
}
break;
}
default:
// Unreachable as:
// 1) We require a read lock (at a minimum) on the "from" collection
// and won't yield, preventing collection drop and PlanExecutor::DEAD
// 2) PlanExecutor::FAILURE is only returned on PlanStage::FAILURE. The
// CollectionScan PlanStage does not have a FAILURE scenario.
//.........这里部分代码省略.........
示例13: run
void run() {
OldClientWriteContext ctx(&_txn, ns());
Database* db = ctx.db();
Collection* coll = db->getCollection(ns());
if (!coll) {
WriteUnitOfWork wuow(&_txn);
coll = db->createCollection(&_txn, ns());
wuow.commit();
}
{
WriteUnitOfWork wuow(&_txn);
fillData();
wuow.commit();
}
// The data we're going to later invalidate.
set<RecordId> locs;
getLocs(&locs, coll);
std::unique_ptr<PlanExecutor> exec(makePlanExecutorWithSortStage(coll));
SortStage* ss = static_cast<SortStage*>(exec->getRootStage());
QueuedDataStage* ms = static_cast<QueuedDataStage*>(ss->getChildren()[0]);
// Have sort read in data from the queued data stage.
const int firstRead = 5;
for (int i = 0; i < firstRead; ++i) {
WorkingSetID id = WorkingSet::INVALID_ID;
PlanStage::StageState status = ss->work(&id);
ASSERT_NOT_EQUALS(PlanStage::ADVANCED, status);
}
// We should have read in the first 'firstRead' locs. Invalidate the first one.
// Since it's in the WorkingSet, the updates should not be reflected in the output.
exec->saveState();
set<RecordId>::iterator it = locs.begin();
Snapshotted<BSONObj> oldDoc = coll->docFor(&_txn, *it);
OID updatedId = oldDoc.value().getField("_id").OID();
SnapshotId idBeforeUpdate = oldDoc.snapshotId();
// We purposefully update the document to have a 'foo' value greater than limit().
// This allows us to check that we don't return the new copy of a doc by asserting
// foo < limit().
BSONObj newDoc = BSON("_id" << updatedId << "foo" << limit() + 10);
oplogUpdateEntryArgs args;
{
WriteUnitOfWork wuow(&_txn);
coll->updateDocument(&_txn, *it, oldDoc, newDoc, false, false, NULL, args);
wuow.commit();
}
exec->restoreState(&_txn);
// Read the rest of the data from the queued data stage.
while (!ms->isEOF()) {
WorkingSetID id = WorkingSet::INVALID_ID;
ss->work(&id);
}
// Let's just invalidate everything now. Already read into ss, so original values
// should be fetched.
exec->saveState();
while (it != locs.end()) {
oldDoc = coll->docFor(&_txn, *it);
{
WriteUnitOfWork wuow(&_txn);
coll->updateDocument(&_txn, *it++, oldDoc, newDoc, false, false, NULL, args);
wuow.commit();
}
}
exec->restoreState(&_txn);
// Verify that it's sorted, the right number of documents are returned, and they're all
// in the expected range.
int count = 0;
int lastVal = 0;
int thisVal;
while (!ss->isEOF()) {
WorkingSetID id = WorkingSet::INVALID_ID;
PlanStage::StageState status = ss->work(&id);
if (PlanStage::ADVANCED != status) {
ASSERT_NE(status, PlanStage::FAILURE);
ASSERT_NE(status, PlanStage::DEAD);
continue;
}
WorkingSetMember* member = exec->getWorkingSet()->get(id);
ASSERT(member->hasObj());
if (member->obj.value().getField("_id").OID() == updatedId) {
ASSERT(idBeforeUpdate == member->obj.snapshotId());
}
thisVal = member->obj.value().getField("foo").Int();
ASSERT_LTE(lastVal, thisVal);
// Expect docs in range [0, limit)
ASSERT_LTE(0, thisVal);
ASSERT_LT(thisVal, limit());
lastVal = thisVal;
++count;
}
// Returns all docs.
ASSERT_EQUALS(limit(), count);
}
示例14: run
//.........这里部分代码省略.........
wunit.commit();
}
// If we get here, we are renaming across databases, so we must copy all the data and
// indexes, then remove the source collection.
// Create the target collection. It will be removed if we fail to copy the collection.
// TODO use a temp collection and unset the temp flag on success.
Collection* targetColl = NULL;
{
CollectionOptions options;
options.setNoIdIndex();
if (sourceColl->isCapped()) {
const CollectionOptions sourceOpts =
sourceColl->getCatalogEntry()->getCollectionOptions(txn);
options.capped = true;
options.cappedSize = sourceOpts.cappedSize;
options.cappedMaxDocs = sourceOpts.cappedMaxDocs;
}
WriteUnitOfWork wunit(txn);
// No logOp necessary because the entire renameCollection command is one logOp.
targetColl = targetDB->createCollection(txn, target, options);
if (!targetColl) {
errmsg = "Failed to create target collection.";
return false;
}
wunit.commit();
}
// Dismissed on success
ScopeGuard targetCollectionDropper = MakeGuard(dropCollection, txn, targetDB, target);
MultiIndexBlock indexer(txn, targetColl);
indexer.allowInterruption();
// Copy the index descriptions from the source collection, adjusting the ns field.
{
std::vector<BSONObj> indexesToCopy;
IndexCatalog::IndexIterator sourceIndIt =
sourceColl->getIndexCatalog()->getIndexIterator(txn, true);
while (sourceIndIt.more()) {
const BSONObj currIndex = sourceIndIt.next()->infoObj();
// Process the source index.
BSONObjBuilder newIndex;
newIndex.append("ns", target);
newIndex.appendElementsUnique(currIndex);
indexesToCopy.push_back(newIndex.obj());
}
indexer.init(indexesToCopy);
}
{
// Copy over all the data from source collection to target collection.
boost::scoped_ptr<RecordIterator> sourceIt(sourceColl->getIterator(txn));
while (!sourceIt->isEOF()) {
txn->checkForInterrupt();
const Snapshotted<BSONObj> obj = sourceColl->docFor(txn, sourceIt->getNext());
WriteUnitOfWork wunit(txn);
// No logOp necessary because the entire renameCollection command is one logOp.
Status status =
targetColl->insertDocument(txn, obj.value(), &indexer, true).getStatus();
if (!status.isOK())
return appendCommandStatus(result, status);
wunit.commit();
}
}
Status status = indexer.doneInserting();
if (!status.isOK())
return appendCommandStatus(result, status);
{
// Getting here means we successfully built the target copy. We now remove the
// source collection and finalize the rename.
WriteUnitOfWork wunit(txn);
Status status = sourceDB->dropCollection(txn, source);
if (!status.isOK())
return appendCommandStatus(result, status);
indexer.commit();
if (!fromRepl) {
repl::logOp(txn, "c", (dbname + ".$cmd").c_str(), cmdObj);
}
wunit.commit();
}
targetCollectionDropper.Dismiss();
return true;
}
示例15: insertAllDocumentsInCollection
Status MultiIndexBlockImpl::insertAllDocumentsInCollection(std::set<RecordId>* dupsOut) {
const char* curopMessage = _buildInBackground ? "Index Build (background)" : "Index Build";
const auto numRecords = _collection->numRecords(_opCtx);
stdx::unique_lock<Client> lk(*_opCtx->getClient());
ProgressMeterHolder progress(
CurOp::get(_opCtx)->setMessage_inlock(curopMessage, curopMessage, numRecords));
lk.unlock();
Timer t;
unsigned long long n = 0;
PlanExecutor::YieldPolicy yieldPolicy;
if (_buildInBackground) {
invariant(_allowInterruption);
yieldPolicy = PlanExecutor::YIELD_AUTO;
} else {
yieldPolicy = PlanExecutor::WRITE_CONFLICT_RETRY_ONLY;
}
auto exec =
InternalPlanner::collectionScan(_opCtx, _collection->ns().ns(), _collection, yieldPolicy);
Snapshotted<BSONObj> objToIndex;
RecordId loc;
PlanExecutor::ExecState state;
int retries = 0; // non-zero when retrying our last document.
while (retries ||
(PlanExecutor::ADVANCED == (state = exec->getNextSnapshotted(&objToIndex, &loc))) ||
MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) {
try {
if (_allowInterruption)
_opCtx->checkForInterrupt();
if (!(retries || (PlanExecutor::ADVANCED == state))) {
// The only reason we are still in the loop is hangAfterStartingIndexBuild.
log() << "Hanging index build due to 'hangAfterStartingIndexBuild' failpoint";
invariant(_allowInterruption);
sleepmillis(1000);
continue;
}
// Make sure we are working with the latest version of the document.
if (objToIndex.snapshotId() != _opCtx->recoveryUnit()->getSnapshotId() &&
!_collection->findDoc(_opCtx, loc, &objToIndex)) {
// doc was deleted so don't index it.
retries = 0;
continue;
}
// Done before insert so we can retry document if it WCEs.
progress->setTotalWhileRunning(_collection->numRecords(_opCtx));
WriteUnitOfWork wunit(_opCtx);
Status ret = insert(objToIndex.value(), loc);
if (_buildInBackground)
exec->saveState();
if (ret.isOK()) {
wunit.commit();
} else if (dupsOut && ret.code() == ErrorCodes::DuplicateKey) {
// If dupsOut is non-null, we should only fail the specific insert that
// led to a DuplicateKey rather than the whole index build.
dupsOut->insert(loc);
} else {
// Fail the index build hard.
return ret;
}
if (_buildInBackground) {
auto restoreStatus = exec->restoreState(); // Handles any WCEs internally.
if (!restoreStatus.isOK()) {
return restoreStatus;
}
}
// Go to the next document
progress->hit();
n++;
retries = 0;
} catch (const WriteConflictException&) {
CurOp::get(_opCtx)->debug().writeConflicts++;
retries++; // logAndBackoff expects this to be 1 on first call.
WriteConflictException::logAndBackoff(
retries, "index creation", _collection->ns().ns());
// Can't use writeConflictRetry since we need to save/restore exec around call to
// abandonSnapshot.
exec->saveState();
_opCtx->recoveryUnit()->abandonSnapshot();
auto restoreStatus = exec->restoreState(); // Handles any WCEs internally.
if (!restoreStatus.isOK()) {
return restoreStatus;
}
}
}
uassert(28550,
"Unable to complete index build due to collection scan failure: " +
WorkingSetCommon::toStatusString(objToIndex.value()),
state == PlanExecutor::IS_EOF);
if (MONGO_FAIL_POINT(hangAfterStartingIndexBuildUnlocked)) {
//.........这里部分代码省略.........