// This is the only iteration method that should ever be called so it does all of the work. bool DocumentSourceOut::eof() { // make sure we only write out once if (_done) return true; _done = true; verify(_conn); prepTempCollection(); verify(_tempNs.size() != 0); for (bool haveNext = !pSource->eof(); haveNext; haveNext = pSource->advance()) { BSONObj toInsert = pSource->getCurrent().toBson(); _conn->insert(_tempNs.ns(), toInsert); BSONObj err = _conn->getLastErrorDetailed(); uassert(16996, str::stream() << "insert for $out failed: " << err, DBClientWithCommands::getLastErrorString(err).empty()); } BSONObj rename = BSON("renameCollection" << _tempNs.ns() << "to" << _outputNs.ns() << "dropTarget" << true ); BSONObj info; bool ok = _conn->runCommand("admin", rename, info); uassert(16997, str::stream() << "renameCollection for $out failed: " << info, ok); // We don't need to drop the temp collection in our destructor if the rename succeeded. _tempNs = NamespaceString(""); // This "DocumentSource" doesn't produce output documents. This can change in the future // if we support using $out in "tee" mode. return true; }
boost::optional<Document> DocumentSourceOut::getNext() { pExpCtx->checkForInterrupt(); // make sure we only write out once if (_done) return boost::none; _done = true; verify(_mongod); DBClientBase* conn = _mongod->directClient(); prepTempCollection(); verify(_tempNs.size() != 0); vector<BSONObj> bufferedObjects; int bufferedBytes = 0; while (boost::optional<Document> next = pSource->getNext()) { BSONObj toInsert = next->toBson(); bufferedBytes += toInsert.objsize(); if (!bufferedObjects.empty() && bufferedBytes > BSONObjMaxUserSize) { spill(conn, bufferedObjects); bufferedObjects.clear(); bufferedBytes = toInsert.objsize(); } bufferedObjects.push_back(toInsert); } if (!bufferedObjects.empty()) spill(conn, bufferedObjects); // Checking again to make sure we didn't become sharded while running. uassert(17018, str::stream() << "namespace '" << _outputNs.ns() << "' became sharded so it can't be used for $out'", !_mongod->isSharded(_outputNs)); BSONObj rename = BSON("renameCollection" << _tempNs.ns() << "to" << _outputNs.ns() << "dropTarget" << true ); BSONObj info; bool ok = conn->runCommand("admin", rename, info); uassert(16997, str::stream() << "renameCollection for $out failed: " << info, ok); // We don't need to drop the temp collection in our destructor if the rename succeeded. _tempNs = NamespaceString(""); // This "DocumentSource" doesn't produce output documents. This can change in the future // if we support using $out in "tee" mode. return boost::none; }