コード例 #1
0
TEST_F(DocumentSourceFacetTest, ShouldRejectNonArrayFacets) {
    auto ctx = getExpCtx();
    auto spec = BSON("$facet" << BSON("a" << 1));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$skip" << 4)) << "b" << 2));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);
}
コード例 #2
0
TEST_F(DocumentSourceFacetTest, ShouldRejectFacetsWithStagesThatMustBeTheFirstStage) {
    auto ctx = getExpCtx();
    auto spec = BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$indexStats" << BSONObj()))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = BSON("$facet" << BSON(
                    "a" << BSON_ARRAY(BSON("$limit" << 1) << BSON("$indexStats" << BSONObj()))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);
}
コード例 #3
0
TEST_F(DocumentSourceFacetTest, ShouldRejectFacetsWithInvalidNames) {
    auto ctx = getExpCtx();
    auto spec = BSON("$facet" << BSON("" << BSON_ARRAY(BSON("$skip" << 4))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = BSON("$facet" << BSON("a.b" << BSON_ARRAY(BSON("$skip" << 4))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = BSON("$facet" << BSON("$a" << BSON_ARRAY(BSON("$skip" << 4))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);
}
コード例 #4
0
TEST_F(DocumentSourceFacetTest, ShouldRejectFacetsContainingAFacetStage) {
    auto ctx = getExpCtx();
    auto spec = fromjson("{$facet: {a: [{$facet: {a: [{$skip: 2}]}}]}}");
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = fromjson("{$facet: {a: [{$skip: 2}, {$facet: {a: [{$skip: 2}]}}]}}");
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = fromjson("{$facet: {a: [{$skip: 2}], b: [{$facet: {a: [{$skip: 2}]}}]}}");
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);
}
コード例 #5
0
TEST_F(DocumentSourceFacetTest, ShouldAcceptLegalSpecification) {
    auto ctx = getExpCtx();
    auto spec = BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$skip" << 4)) << "b"
                                          << BSON_ARRAY(BSON("$limit" << 3))));
    auto facetStage = DocumentSourceFacet::createFromBson(spec.firstElement(), ctx);
    ASSERT_TRUE(facetStage.get());
}
コード例 #6
0
TEST_F(DocumentSourceFacetTest, ShouldRejectFacetsContainingAnOutStage) {
    auto ctx = getExpCtx();
    auto spec = BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$out"
                                                             << "out_collection"))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec =
        BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$skip" << 1) << BSON("$out"
                                                                           << "out_collection"))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);

    spec = BSON("$facet" << BSON("a" << BSON_ARRAY(BSON("$out"
                                                        << "out_collection")
                                                   << BSON("$skip" << 1))));
    ASSERT_THROWS(DocumentSourceFacet::createFromBson(spec.firstElement(), ctx), UserException);
}
コード例 #7
0
List *mergesort(List *list)
{
	if (length(list) == 1)
	{
		return list;
	}
	Position testOnConstr = NULL;
	bool test = 0;
	List *leftHalf = createList(testOnConstr);
	List *rightHalf = createList(testOnConstr);
	Position posLeft = head(leftHalf);
	Position posRight = head(rightHalf);
	for (Position temp = firstElement(list); temp != next(list, middle(list)); temp = next(list, temp))
	{
		insert(leftHalf, returnByPos(list, temp), posLeft);
		posLeft = next(leftHalf, posLeft);
	}
	for (Position temp = next(list, middle(list)); temp != last(list); temp = next(list, temp))
	{
		insert(rightHalf, returnByPos(list, temp), posRight);
		posRight = next(rightHalf, posRight);
	}
	leftHalf = mergesort(leftHalf);
	rightHalf = mergesort(rightHalf);
	List *result = createList(testOnConstr);
	Position posResult = head(result);
	posLeft = head(leftHalf);
	posRight = head(rightHalf);
	while (length(leftHalf) && length(rightHalf) != 0)
	{
		if (returnByPos(leftHalf, firstElement(leftHalf)) <= returnByPos(rightHalf, firstElement(rightHalf)))
		{
			insert(result, returnByPos(leftHalf, firstElement(leftHalf)), posResult);
			remove(leftHalf, posLeft);
			posResult = next(result, posResult);
		}
		else
		{
			insert(result, returnByPos(rightHalf, firstElement(rightHalf)), posResult);
			remove(rightHalf, posRight);
			posResult = next(result, posResult);
		}
	}
	while (length(leftHalf) != 0)
	{
		insert(result, returnByPos(leftHalf, firstElement(leftHalf)), posResult);
		remove(leftHalf, posLeft);
		posResult = next(result, posResult);
	}
	while (length(rightHalf) != 0)
	{
		insert(result, returnByPos(rightHalf, firstElement(rightHalf)), posResult);
		remove(rightHalf, posRight);
		posResult = next(result, posResult);
	}
	deleteList(leftHalf);
	deleteList(rightHalf);
	return result;
}
コード例 #8
0
void printList(ListPoint *list)
{
	ElementOfList *temp = firstElement(list);
	while (temp != nullptr)
	{
		std::cout << temp->value << " ";
		temp = temp->next;
	}
	std::cout << std::endl;
}
コード例 #9
0
ファイル: stanza.cpp プロジェクト: Nikoli/vacuum-im
bool Stanza::isValid() const
{
	if (element().isNull())
		return false;

	if (type()=="error" && firstElement("error").isNull())
		return false;

	return true;
}
コード例 #10
0
ElementOfList *middle(ListPoint *list)
{
	int middleCount = length(list) / 2 - 1;
	ElementOfList *temp = firstElement(list);
	while(middleCount > 0)
	{
		middleCount--;
		temp = temp->next;
	}
	return temp;
}
コード例 #11
0
ファイル: bsonobj.cpp プロジェクト: kingfs/tokumxse
void BSONObj::_assertInvalid() const {
    StringBuilder ss;
    int os = objsize();
    ss << "BSONObj size: " << os << " (0x" << integerToHex( os ) << ") is invalid. "
       << "Size must be between 0 and " << BSONObjMaxInternalSize
       << "(" << ( BSONObjMaxInternalSize/(1024*1024) ) << "MB)";
    try {
        BSONElement e = firstElement();
        ss << " First element: " << e.toString();
    }
    catch ( ... ) { }
    massert( 10334 , ss.str() , 0 );
}
コード例 #12
0
// calculation of every element for one tile
int tile_fill(struct TileQueue *tiles)
{
	INDEX i,j;
	COLOR *TileColor;
	INIT_MEM(TileColor, TILE_SIZE * TILE_SIZE, COLOR);
	struct timeval t1, t2;
	gettimeofday(&t1, NULL);
	
	while(!terminated){
		pthread_mutex_lock(&mutex);
		if (!isEmpty(tiles)) {
			int current_tile = firstElement(tiles);
			pop(tiles);
			pthread_mutex_unlock(&mutex);

			if (fake) { // fake tasks
				usleep(-current_tile);
			}
			else { // regular tasks
				// assigning first and final index of tile
				int j_begin = rank_j(current_tile, Cj);
				int j_end = MIN(j_begin + TILE_SIZE, Img.Pixel.j);
				int i_begin = rank_i(current_tile, Ci);
				int i_end = MIN(i_begin + TILE_SIZE, Img.Pixel.i);
				for (j = j_begin; j < j_end ; j++) {
					for (i = i_begin ; i < i_end; i++) {
						TileColor [(j-j_begin) * TILE_SIZE + (i-i_begin)] = pixel_basic (i, j);
					}
				}
				// Sending current tile to proc 0
				MPI_Send(TileColor, TILE_SIZE * TILE_SIZE, MPI_COLOR, 0, current_tile + TILE_TAG_INDEX, MPI_COMM_WORLD);
			}
		} else {
			pthread_mutex_unlock(&mutex);
			if (!vol){
				terminated = 1;
				break;
			}
			// if vol de travail, ask for work and wait until we receive it
			sem_post(&ask_work);
			sem_wait(&wait_work);
		}
	}
	
	pthread_mutex_lock(&mutex_time);
	gettimeofday(&t2, NULL);
	local_time = MAX(local_time,(t2.tv_sec - t1.tv_sec)*1000000 + t2.tv_usec - t1.tv_usec);
	printf("time %ld\n",(t2.tv_sec - t1.tv_sec)*1000000 + t2.tv_usec - t1.tv_usec);
	pthread_mutex_unlock(&mutex_time);
	return 0;
}
コード例 #13
0
ファイル: QPubNub.cpp プロジェクト: SebastianVoigt/PubNub4Qt
void QPubNub::onSubscribeReadyRead() {
  QNetworkReply * reply = qobject_cast<QNetworkReply*>(sender());
  QJsonArray response;
  if (handleResponse(reply, response)) {
    return;
  }
  QJsonValue firstElement(response.at(0));
  if (!firstElement.isArray()) {
    emit error("First element of response is not an JSON array", 0);
    subscribe();
  }
  
  QJsonValue timeTokenElement = response.at(1);
  if (!timeTokenElement.isString()) {
    emit error("Second element of response is not a string", 0);
    subscribe();
  }
  m_timeToken = timeTokenElement.toString();
  QJsonValue channelListString = response.at(2);
  QStringList channels;
  QJsonArray messages = firstElement.toArray();
  if (channelListString.isString()) {
    channels = channelListString.toString().split(',');
  } else {
    int len = messages.isEmpty() ? 0 : messages.size();
    for (int i = 0; i < len; i++)
    {
        channels << m_channelUrlPart;
    }
  }
  if (messages.isEmpty()) {
    emit connected();
  } else {
#ifdef Q_PUBNUB_CRYPT
    if (m_cipherKey.isEmpty()) {
      for (int i=0,len=messages.size();i<len;++i) {
        emit message(messages[i], m_timeToken, channels[i]);
      }
    } else {
      decrypt(messages, channels);
    }
  #else
    for (int i=0,len=messages.size();i<len;++i) {
      emit message(messages[i], m_timeToken, channels[i]);
    }
#endif // Q_PUBNUB_CRYPT
  }
  subscribe();
}
コード例 #14
0
int length(ListPoint *list)
{
	if (head(list) == 0)
	{
		return 0;
	}
	int count = 0;
	ElementOfList *temp = firstElement(list);
	while(temp != nullptr)
	{
		count++;
		temp = temp->next;
	}
	return count;
}
コード例 #15
0
ファイル: create_collection.cpp プロジェクト: DINKIN/mongo
Status createCollectionForApplyOps(OperationContext* opCtx,
                                   const std::string& dbName,
                                   const BSONElement& ui,
                                   const BSONObj& cmdObj,
                                   const BSONObj& idIndex) {
    invariant(opCtx->lockState()->isDbLockedForMode(dbName, MODE_X));
    auto db = dbHolder().get(opCtx, dbName);
    const NamespaceString newCollName(Command::parseNsCollectionRequired(dbName, cmdObj));
    auto newCmd = cmdObj;

    // If a UUID is given, see if we need to rename a collection out of the way, and whether the
    // collection already exists under a different name. If so, rename it into place. As this is
    // done during replay of the oplog, the operations do not need to be atomic, just idempotent.
    // We need to do the renaming part in a separate transaction, as we cannot transactionally
    // create a database on MMAPv1, which could result in createCollection failing if the database
    // does not yet exist.
    if (ui.ok()) {
        // Return an optional, indicating whether we need to early return (if the collection already
        // exists, or in case of an error).
        using Result = boost::optional<Status>;
        auto result =
            writeConflictRetry(opCtx, "createCollectionForApplyOps", newCollName.ns(), [&] {
                WriteUnitOfWork wunit(opCtx);
                // Options need the field to be named "uuid", so parse/recreate.
                auto uuid = uassertStatusOK(UUID::parse(ui));
                uassert(ErrorCodes::InvalidUUID,
                        "Invalid UUID in applyOps create command: " + uuid.toString(),
                        uuid.isRFC4122v4());

                auto& catalog = UUIDCatalog::get(opCtx);
                auto currentName = catalog.lookupNSSByUUID(uuid);
                OpObserver* opObserver = getGlobalServiceContext()->getOpObserver();
                if (currentName == newCollName)
                    return Result(Status::OK());

                // In the case of oplog replay, a future command may have created or renamed a
                // collection with that same name. In that case, renaming this future collection to
                // a random temporary name is correct: once all entries are replayed no temporary
                // names will remain.  On MMAPv1 the rename can result in index names that are too
                // long. However this should only happen for initial sync and "resync collection"
                // for rollback, so we can let the error propagate resulting in an abort and restart
                // of the initial sync or result in rollback to fassert, requiring a resync of that
                // node.
                const bool stayTemp = true;
                if (auto futureColl = db ? db->getCollection(opCtx, newCollName) : nullptr) {
                    auto tmpNameResult = db->makeUniqueCollectionNamespace(opCtx, "tmp%%%%%");
                    if (!tmpNameResult.isOK()) {
                        return Result(Status(tmpNameResult.getStatus().code(),
                                             str::stream() << "Cannot generate temporary "
                                                              "collection namespace for applyOps "
                                                              "create command: collection: "
                                                           << newCollName.ns()
                                                           << ". error: "
                                                           << tmpNameResult.getStatus().reason()));
                    }
                    const auto& tmpName = tmpNameResult.getValue();
                    Status status =
                        db->renameCollection(opCtx, newCollName.ns(), tmpName.ns(), stayTemp);
                    if (!status.isOK())
                        return Result(status);
                    opObserver->onRenameCollection(opCtx,
                                                   newCollName,
                                                   tmpName,
                                                   futureColl->uuid(),
                                                   /*dropTarget*/ false,
                                                   /*dropTargetUUID*/ {},
                                                   stayTemp);
                }

                // If the collection with the requested UUID already exists, but with a different
                // name, just rename it to 'newCollName'.
                if (catalog.lookupCollectionByUUID(uuid)) {
                    Status status =
                        db->renameCollection(opCtx, currentName.ns(), newCollName.ns(), stayTemp);
                    if (!status.isOK())
                        return Result(status);
                    opObserver->onRenameCollection(opCtx,
                                                   currentName,
                                                   newCollName,
                                                   uuid,
                                                   /*dropTarget*/ false,
                                                   /*dropTargetUUID*/ {},
                                                   stayTemp);

                    wunit.commit();
                    return Result(Status::OK());
                }

                // A new collection with the specific UUID must be created, so add the UUID to the
                // creation options. Regular user collection creation commands cannot do this.
                auto uuidObj = uuid.toBSON();
                newCmd = cmdObj.addField(uuidObj.firstElement());
                wunit.commit();

                return Result(boost::none);
            });

        if (result) {
            return *result;
        }
    }

    return createCollection(
        opCtx, newCollName, newCmd, idIndex, CollectionOptions::parseForStorage);
}
コード例 #16
0
void
img (const char *FileNameImg)
{
	FILE   *FileImg; 
	COLOR  *TabColor, *Color, *TileColor;
	STRING Name;
	INDEX  i, j, rank;
	BYTE   Byte;
	int N = 18988, err, provided;
	int next_proc;
	MPI_Request rs;

	MPI_Status status;
	MPI_Init_thread(NULL, NULL, MPI_THREAD_MULTIPLE, &provided);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &P);
	next_proc = (rank + 1) % P;
	if (next_proc == 0) next_proc++;
	P--;

	MPI_Type_vector(1, 3, 0, MPI_FLOAT, &MPI_COLOR);
	MPI_Type_commit(&MPI_COLOR);

	if (rank == 0) {
		strcpy (Name, FileNameImg);
		strcat (Name, ".ppm");
		INIT_FILE (FileImg, Name, "w");
		fprintf (FileImg, "P6\n%d %d\n255\n", Img.Pixel.i, Img.Pixel.j);
	}

	// number of tiles
	Ci = Img.Pixel.i / TILE_SIZE + (Img.Pixel.i % TILE_SIZE?1:0); // number of tiles in dimension i
	Cj = Img.Pixel.j / TILE_SIZE + (Img.Pixel.i % TILE_SIZE?1:0);  // number of tiles in dimension j
	int C = Ci * Cj;
	int q = (C+P-1)/P;
	int size = Img.Pixel.i * Img.Pixel.j ;
	N = C/2+1;

	// buffer for each tile
	INIT_MEM (TileColor, TILE_SIZE * TILE_SIZE, COLOR);


	if (rank != 0) {
		struct TileQueue tiles = {NULL, NULL};

		// Init tasks
		init(&tiles,rank,q,N,C);

		// Init mutex, semaphores & threads
		pthread_mutex_init(&mutex,NULL);
		pthread_mutex_init(&mutex_time,NULL);
		sem_init(&wait_work, 0, 0);
		sem_init(&ask_work, 0, 0);
		pthread_t tid[NB_THREADS];

		for (i = 0; i < NB_THREADS; i++){
			err = pthread_create(&(tid[i]), NULL, (void*)tile_fill, (void*)&tiles);
			if (err != 0)
				printf("\ncan't create thread :[%s]", strerror(err));
		}

		// vol de travail ?
		if (vol){
		// Main thread: Communicator
			while (!terminated)
			{
				int flag = 0, msg;
				MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &status);
				if (flag) {
				// We DID receive a communication so we CAN do a blocking receive
					MPI_Recv(&msg, 1, MPI_INT, status.MPI_SOURCE, status.MPI_TAG, MPI_COMM_WORLD, &status);
				// TAG contains the information about what the message is
					switch (status.MPI_TAG){
						case TERMINATE: // No more jobs; threads can finish their jobs and return
						MPI_Isend(&msg, 1, MPI_INT, next_proc, TERMINATE, MPI_COMM_WORLD, &rs);
						terminated = 1;
						break;
						case WORK_ASK: // msg-th process is seeking for job
						pthread_mutex_lock(&mutex);
						if(!isEmpty(&tiles)){
							int tile = firstElement(&tiles);
							pop(&tiles);
							pthread_mutex_unlock(&mutex);
							MPI_Isend(&tile, 1, MPI_INT, msg, WORK_SEND, MPI_COMM_WORLD, &rs);
						}
						else {
							pthread_mutex_unlock(&mutex);
							if (msg == rank){
								MPI_Isend(&msg, 1, MPI_INT, next_proc, TERMINATE, MPI_COMM_WORLD, &rs);
								terminated = 1;
							} else { 
								MPI_Isend(&msg, 1, MPI_INT, next_proc, WORK_ASK, MPI_COMM_WORLD, &rs);
							}
						}
						break;
						case WORK_SEND: // Received a job
						pthread_mutex_lock(&mutex);
						addTile(&tiles, msg);
						pthread_mutex_unlock(&mutex);
						sem_post(&wait_work);
						break;
						default: 
						fprintf(stderr, "Err: Unknown message: %d, with tag %d\n", msg,status.MPI_TAG); 
						break;
					}
				}
				if (sem_trywait(&ask_work) == 0){
					MPI_Isend(&rank, 1, MPI_INT, next_proc, WORK_ASK, MPI_COMM_WORLD, &rs);
				}
			}
			for (i = 0; i < NB_THREADS; i++){
				sem_post(&wait_work);
			}
		}

		for (i = 0; i < NB_THREADS; i++){
			pthread_join(tid[i],NULL);
		}

		pthread_mutex_destroy(&mutex);
		pthread_mutex_destroy(&mutex_time);
		sem_destroy(&wait_work);
		sem_destroy(&ask_work);
		fprintf(stderr, "%d %ld\n", rank, local_time);
	}

	// process 0 gathers all the tiles
	if (rank == 0){ 

		// If fake tasks: we don't receive anything and don't write the image
		FILE* fd = fopen("config","r");
		if (fd != NULL){
			int fake;
			fscanf(fd,"%d\n",&fake);
			if (fake){
				EXIT_FILE(FileImg);
				EXIT_MEM(TileColor);
				MPI_Finalize();
				return;
			}
		}

		// final image buffer that will receive the tiles
		INIT_MEM (TabColor, size, COLOR);

		// Receive tiles from other procs
		for (i = 0; i < C ; i++){
			MPI_Recv(TileColor, TILE_SIZE * TILE_SIZE, MPI_COLOR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
			int current_tile = status.MPI_TAG - TILE_TAG_INDEX;
			int j_begin = rank_j(current_tile,Cj);
			int index_begin = rank_i(current_tile,Ci) + j_begin * Img.Pixel.i;
			for (j = 0; j < TILE_SIZE && j_begin + j < Img.Pixel.j; j++) {
				memcpy(&TabColor[index_begin + j * Img.Pixel.i],&TileColor[j * TILE_SIZE],MIN(Img.Pixel.i - rank_i(current_tile,Ci),TILE_SIZE) * sizeof(COLOR));
			}
		}

		// writing in file
		for (j = 0, Color = TabColor; j < size; j++, Color++) {
			Byte = Color->r < 1.0 ? 255.0*Color->r : 255.0;
			putc (Byte, FileImg);
			Byte = Color->g < 1.0 ? 255.0*Color->g : 255.0;
			putc (Byte, FileImg);
			Byte = Color->b < 1.0 ? 255.0*Color->b : 255.0;
			putc (Byte, FileImg);
		}
		EXIT_FILE (FileImg);
		printf("Copied in file\n");
		EXIT_MEM (TabColor);
	}
	EXIT_MEM (TileColor);
	MPI_Finalize();
}
コード例 #17
0
StatusWith<std::set<NamespaceString>> RollbackImpl::_namespacesForOp(const OplogEntry& oplogEntry) {
    NamespaceString opNss = oplogEntry.getNamespace();
    OpTypeEnum opType = oplogEntry.getOpType();
    std::set<NamespaceString> namespaces;

    // No namespaces for a no-op.
    if (opType == OpTypeEnum::kNoop) {
        return std::set<NamespaceString>();
    }

    // CRUD ops have the proper namespace in the operation 'ns' field.
    if (opType == OpTypeEnum::kInsert || opType == OpTypeEnum::kUpdate ||
        opType == OpTypeEnum::kDelete) {
        return std::set<NamespaceString>({opNss});
    }

    // If the operation is a command, then we need to extract the appropriate namespaces from the
    // command object, as opposed to just using the 'ns' field of the oplog entry itself.
    if (opType == OpTypeEnum::kCommand) {
        auto obj = oplogEntry.getObject();
        auto firstElem = obj.firstElement();

        // Does not handle 'applyOps' entries.
        invariant(oplogEntry.getCommandType() != OplogEntry::CommandType::kApplyOps,
                  "_namespacesForOp does not handle 'applyOps' oplog entries.");

        switch (oplogEntry.getCommandType()) {
            case OplogEntry::CommandType::kRenameCollection: {
                // Add both the 'from' and 'to' namespaces.
                namespaces.insert(NamespaceString(firstElem.valuestrsafe()));
                namespaces.insert(NamespaceString(obj.getStringField("to")));
                break;
            }
            case OplogEntry::CommandType::kDropDatabase: {
                // There is no specific namespace to save for a drop database operation.
                break;
            }
            case OplogEntry::CommandType::kDbCheck:
            case OplogEntry::CommandType::kConvertToCapped:
            case OplogEntry::CommandType::kEmptyCapped: {
                // These commands do not need to be supported by rollback. 'convertToCapped' should
                // always be converted to lower level DDL operations, and 'emptycapped' is a
                // testing-only command.
                std::string message = str::stream() << "Encountered unsupported command type '"
                                                    << firstElem.fieldName()
                                                    << "' during rollback.";
                return Status(ErrorCodes::UnrecoverableRollbackError, message);
            }
            case OplogEntry::CommandType::kCreate:
            case OplogEntry::CommandType::kDrop:
            case OplogEntry::CommandType::kCreateIndexes:
            case OplogEntry::CommandType::kDropIndexes:
            case OplogEntry::CommandType::kCollMod: {
                // For all other command types, we should be able to parse the collection name from
                // the first command argument.
                try {
                    auto cmdNss = CommandHelpers::parseNsCollectionRequired(opNss.db(), obj);
                    namespaces.insert(cmdNss);
                } catch (const DBException& ex) {
                    return ex.toStatus();
                }
                break;
            }
            case OplogEntry::CommandType::kApplyOps:
            default:
                // Every possible command type should be handled above.
                MONGO_UNREACHABLE
        }
    }