void shouldReparentCollectionsOnModify() { // GIVEN auto data = Testlib::AkonadiFakeData(); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto c2 = Akonadi::Collection(43); c2.setName(QStringLiteral("43")); data.createCollection(c2); auto c3 = Akonadi::Collection(44); c3.setParentCollection(Akonadi::Collection(42)); data.createCollection(c3); // WHEN c3.setParentCollection(Akonadi::Collection(43)); data.modifyCollection(c3); // THEN QVERIFY(data.childCollections(c1.id()).isEmpty()); QCOMPARE(data.childCollections(c2.id()).size(), 1); QCOMPARE(data.childCollections(c2.id()).at(0), c3); }
void shouldReparentItemsOnModify() { // GIVEN auto data = Testlib::AkonadiFakeData(); QScopedPointer<Akonadi::MonitorInterface> monitor(data.createMonitor()); QSignalSpy spy(monitor.data(), &Akonadi::MonitorInterface::itemMoved); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto c2 = Akonadi::Collection(43); c2.setName(QStringLiteral("43")); data.createCollection(c2); auto i1 = Akonadi::Item(42); i1.setPayloadFromData("42"); i1.setParentCollection(Akonadi::Collection(42)); data.createItem(i1); // WHEN i1.setPayloadFromData("42-bis"); i1.setParentCollection(Akonadi::Collection(43)); data.modifyItem(i1); // THEN QVERIFY(data.childItems(c1.id()).isEmpty()); QCOMPARE(data.childItems(c2.id()).size(), 1); QCOMPARE(data.childItems(c2.id()).at(0), i1); QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Item>(), i1); }
void shouldNotLooseParentCollectionOnModifyCollection() { // GIVEN auto data = Testlib::AkonadiFakeData(); auto root = Akonadi::Collection(42); root.setName(QStringLiteral("root")); data.createCollection(root); auto c1 = Akonadi::Collection(43); c1.setName(QStringLiteral("43")); c1.setParentCollection(Akonadi::Collection(root.id())); data.createCollection(c1); auto c2 = Akonadi::Collection(c1.id()); c2.setName(QStringLiteral("43-bis")); // WHEN data.modifyCollection(c2); // THEN QCOMPARE(data.collections().size(), 2); QCOMPARE(data.collection(c1.id()), c2); QCOMPARE(data.collection(c1.id()).parentCollection().id(), root.id()); }
void shouldRemoveCollections() { // GIVEN auto data = Testlib::AkonadiFakeData(); QScopedPointer<Akonadi::MonitorInterface> monitor(data.createMonitor()); QSignalSpy spy(monitor.data(), &Akonadi::MonitorInterface::collectionRemoved); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto c2 = Akonadi::Collection(43); c2.setName(QStringLiteral("43")); c2.setParentCollection(Akonadi::Collection(42)); data.createCollection(c2); auto c3 = Akonadi::Collection(44); c3.setName(QStringLiteral("44")); c3.setParentCollection(Akonadi::Collection(43)); data.createCollection(c3); auto i1 = Akonadi::Item(42); i1.setPayloadFromData("42"); i1.setParentCollection(Akonadi::Collection(43)); data.createItem(i1); auto i2 = Akonadi::Item(43); i2.setPayloadFromData("43"); i2.setParentCollection(Akonadi::Collection(44)); data.createItem(i2); // WHEN data.removeCollection(c2); // THEN QCOMPARE(data.collections().size(), 1); QCOMPARE(data.collections().at(0), c1); QVERIFY(!data.collection(c2.id()).isValid()); QVERIFY(!data.collection(c3.id()).isValid()); QVERIFY(data.childCollections(c1.id()).isEmpty()); QVERIFY(data.childCollections(c2.id()).isEmpty()); QVERIFY(data.childCollections(c3.id()).isEmpty()); QVERIFY(data.items().isEmpty()); QVERIFY(!data.item(i1.id()).isValid()); QVERIFY(!data.item(i2.id()).isValid()); QVERIFY(data.childItems(c2.id()).isEmpty()); QVERIFY(data.childItems(c3.id()).isEmpty()); QCOMPARE(spy.size(), 2); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Collection>(), c3); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Collection>(), c2); }
bool _testOplogEntryIsForCappedCollection(OperationContext* txn, const NamespaceString& nss, const CollectionOptions& options) { auto writerPool = SyncTail::makeWriterPool(); MultiApplier::Operations operationsApplied; auto applyOperationFn = [&operationsApplied](MultiApplier::OperationPtrs* operationsToApply) { for (auto&& opPtr : *operationsToApply) { operationsApplied.push_back(*opPtr); } }; createCollection(txn, nss, options); auto op = makeInsertDocumentOplogEntry({Timestamp(Seconds(1), 0), 1LL}, nss, BSON("a" << 1)); ASSERT_FALSE(op.isForCappedCollection); auto lastOpTime = unittest::assertGet(multiApply(txn, writerPool.get(), {op}, applyOperationFn)); ASSERT_EQUALS(op.getOpTime(), lastOpTime); ASSERT_EQUALS(1U, operationsApplied.size()); const auto& opApplied = operationsApplied.front(); ASSERT_EQUALS(op, opApplied); // "isForCappedCollection" is not parsed from raw oplog entry document. return opApplied.isForCappedCollection; }
void shouldCreateCollections() { // GIVEN auto data = Testlib::AkonadiFakeData(); QScopedPointer<Akonadi::MonitorInterface> monitor(data.createMonitor()); QSignalSpy spy(monitor.data(), &Akonadi::MonitorInterface::collectionAdded); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); auto c2 = Akonadi::Collection(43); c2.setName(QStringLiteral("43")); const auto colSet = QSet<Akonadi::Collection>() << c1 << c2; // WHEN data.createCollection(c1); data.createCollection(c2); // THEN QCOMPARE(data.collections().toList().toSet(), colSet); QCOMPARE(data.collection(c1.id()), c1); QCOMPARE(data.collection(c2.id()), c2); QCOMPARE(spy.size(), 2); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Collection>(), c1); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Collection>(), c2); }
Collection* Database::getOrCreateCollection(OperationContext* txn, StringData ns) { Collection* c = getCollection( ns ); if ( !c ) { c = createCollection( txn, ns ); } return c; }
void shouldNotLooseParentCollectionOnModifyItem() { // GIVEN auto data = Testlib::AkonadiFakeData(); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto i1 = Akonadi::Item(42); i1.setPayloadFromData("42"); i1.setParentCollection(Akonadi::Collection(42)); data.createItem(i1); auto i2 = Akonadi::Item(i1.id()); i2.setPayloadFromData("42-bis"); // WHEN data.modifyItem(i2); // THEN QCOMPARE(data.items().size(), 1); QCOMPARE(data.item(i1.id()), i2); QCOMPARE(data.item(i1.id()).parentCollection().id(), c1.id()); }
static void readCollectionContent(xmlNode *node) { Collection *col; xmlChar *col_uri; xmlNode *child_node; // structured xml annotation int i; // create Collection col_uri = getNodeURI(node); col = createCollection(DESTINATION, (char *)col_uri); xmlFree(col_uri); // add displayID, name, description readSBOLCompoundObject(col->base, node); // scan other xml nodes attached to this Collection for structured xml annotations // @TODO factor out this block of code. This routine is generally used by each of the SBOL core objects // but it requires some custom knowledge of the calling object (in this case, Collection) child_node = node->children; while (child_node) { if (child_node->ns && !isSBOLNamespace(child_node->ns->href)) { // copy xml tree and save it in the SBOLDocument object as a structural annotation xmlNode* node_copy = xmlDocCopyNode(child_node, col->doc->xml_doc, 1); node_copy = xmlAddChild(xmlDocGetRootElement(col->doc->xml_doc), node_copy); i = xmlReconciliateNs(col->doc->xml_doc, xmlDocGetRootElement(col->doc->xml_doc)); insertPointerIntoArray(col->base->base->xml_annotations, node_copy); } child_node = child_node->next; } }
void shouldModifyItems() { // GIVEN auto data = Testlib::AkonadiFakeData(); QScopedPointer<Akonadi::MonitorInterface> monitor(data.createMonitor()); QSignalSpy spy(monitor.data(), &Akonadi::MonitorInterface::itemChanged); QSignalSpy moveSpy(monitor.data(), &Akonadi::MonitorInterface::itemMoved); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto i1 = Akonadi::Item(42); i1.setPayloadFromData("42"); i1.setParentCollection(Akonadi::Collection(42)); data.createItem(i1); auto i2 = Akonadi::Item(i1.id()); i2.setPayloadFromData("42-bis"); i2.setParentCollection(Akonadi::Collection(42)); // WHEN data.modifyItem(i2); // THEN QCOMPARE(data.items().size(), 1); QCOMPARE(data.item(i1.id()), i2); QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Item>(), i2); QCOMPARE(moveSpy.size(), 0); }
void shouldRemoveTags() { // GIVEN auto data = Testlib::AkonadiFakeData(); QScopedPointer<Akonadi::MonitorInterface> monitor(data.createMonitor()); QSignalSpy tagSpy(monitor.data(), &Akonadi::MonitorInterface::tagRemoved); QSignalSpy itemSpy(monitor.data(), &Akonadi::MonitorInterface::itemChanged); auto c1 = Akonadi::Collection(42); data.createCollection(c1); auto t1 = Akonadi::Tag(42); t1.setName(QStringLiteral("42")); data.createTag(t1); auto t2 = Akonadi::Tag(43); t2.setName(QStringLiteral("43")); data.createTag(t2); auto i1 = Akonadi::Item(42); i1.setPayloadFromData("42"); i1.setParentCollection(c1); i1.setTag(Akonadi::Tag(t1.id())); data.createItem(i1); auto i2 = Akonadi::Item(43); i2.setPayloadFromData("43"); i2.setParentCollection(c1); i2.setTag(Akonadi::Tag(t2.id())); data.createItem(i2); const auto itemSet = QSet<Akonadi::Item>() << i1 << i2; // WHEN data.removeTag(t2); // THEN QCOMPARE(data.tags().size(), 1); QCOMPARE(data.tags().at(0), t1); QVERIFY(!data.tag(t2.id()).isValid()); QCOMPARE(data.tagItems(t1.id()).size(), 1); QCOMPARE(data.tagItems(t1.id()).at(0), i1); QVERIFY(data.tagItems(t2.id()).isEmpty()); QCOMPARE(data.items().toList().toSet(), itemSet); QVERIFY(data.item(i1.id()).isValid()); QVERIFY(data.item(i2.id()).isValid()); QVERIFY(!data.item(i2.id()).tags().contains(t2)); QCOMPARE(tagSpy.size(), 1); QCOMPARE(tagSpy.takeFirst().at(0).value<Akonadi::Tag>(), t2); QCOMPARE(itemSpy.size(), 1); QCOMPARE(itemSpy.first().at(0).value<Akonadi::Item>(), i2); QVERIFY(!itemSpy.first().at(0).value<Akonadi::Item>().tags().contains(t2)); }
void run() { string ns = "unittests.rollback_set_index_head"; const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext(); OperationContext& opCtx = *opCtxPtr; NamespaceString nss(ns); dropDatabase(&opCtx, nss); createCollection(&opCtx, nss); AutoGetDb autoDb(&opCtx, nss.db(), MODE_X); Collection* coll = autoDb.getDb()->getCollection(&opCtx, nss); IndexCatalog* catalog = coll->getIndexCatalog(); string idxName = "a"; BSONObj spec = BSON("ns" << ns << "key" << BSON("a" << 1) << "name" << idxName << "v" << static_cast<int>(kIndexVersion)); { WriteUnitOfWork uow(&opCtx); ASSERT_OK(catalog->createIndexOnEmptyCollection(&opCtx, spec)); uow.commit(); } IndexDescriptor* indexDesc = catalog->findIndexByName(&opCtx, idxName); invariant(indexDesc); const IndexCatalogEntry* ice = catalog->getEntry(indexDesc); invariant(ice); HeadManager* headManager = ice->headManager(); const RecordId oldHead = headManager->getHead(&opCtx); ASSERT_EQ(oldHead, ice->head(&opCtx)); const RecordId dummyHead(123, 456); ASSERT_NE(oldHead, dummyHead); // END SETUP / START TEST { WriteUnitOfWork uow(&opCtx); headManager->setHead(&opCtx, dummyHead); ASSERT_EQ(ice->head(&opCtx), dummyHead); ASSERT_EQ(headManager->getHead(&opCtx), dummyHead); if (!rollback) { uow.commit(); } } if (rollback) { ASSERT_EQ(ice->head(&opCtx), oldHead); ASSERT_EQ(headManager->getHead(&opCtx), oldHead); } else { ASSERT_EQ(ice->head(&opCtx), dummyHead); ASSERT_EQ(headManager->getHead(&opCtx), dummyHead); } }
Status DeferredWriter::_makeCollection(OperationContext* opCtx) { BSONObjBuilder builder; builder.append("create", _nss.coll()); builder.appendElements(_collectionOptions.toBSON()); try { return createCollection(opCtx, _nss.db().toString(), builder.obj().getOwned()); } catch (const DBException& exception) { return exception.toStatus(); } }
Status createCollection(OperationContext* opCtx, const std::string& dbName, const BSONObj& cmdObj, const BSONObj& idIndex) { return createCollection(opCtx, Command::parseNsCollectionRequired(dbName, cmdObj), cmdObj, idIndex, CollectionOptions::parseForCommand); }
RecordStoreV1Base* MMAPV1DatabaseCatalogEntry::_getIndexRecordStore( OperationContext* txn ) { NamespaceString nss( name(), "system.indexes" ); RecordStoreV1Base* rs = _getRecordStore( txn, nss.ns() ); if ( rs != NULL ) return rs; CollectionOptions options; Status status = createCollection( txn, nss.ns(), options, true ); massertStatusOK( status ); rs = _getRecordStore( txn, nss.ns() ); invariant( rs ); return rs; }
/*! * This function uses our class's resolver to create a new collection but, * instead of loading the collection from a path, we instead load the given * serialized collection data. * * Other than that small detail, this function behaves identically to our * newCollection() function. See that function's documentation for more * information. * * \param n The name for the new collection. * \param p The path to the collection. * \param d The serialized collection data to load. */ void CSCollectionTypeResolver::unserializeCollection(const QString &n, const QString &p, const QByteArray &d) { /* SLOT */ CSAbstractCollection *c = NULL; /* bool u = true; for(int j = 0; j < count(); ++j) { if(collectionAt(j)->getName() == name) { u = false; break; } } if(!u) continue; */ c = createCollection(n, p); if(c == NULL) { #pragma message "TODO - Errors need to be handled here by emitting a signal" return; } // Connect the collection to our slots. QObject::connect(c, SIGNAL(jobStarted(const QString &, bool)), this, SLOT(doJobStarted(const QString &, bool))); QObject::connect(c, SIGNAL(progressLimitsUpdated(int, int)), this, SLOT(doProgressLimitsUpdated(int, int))); QObject::connect(c, SIGNAL(progressUpdated(int)), this, SLOT(doProgressUpdated(int))); QObject::connect(c, SIGNAL(jobFinished(const QString &)), this, SLOT(doJobFinished(const QString &))); /* * The collection has been created, but we still need to load its data. * Emit the signal indicating that the collection exists, but set it * disabled (until it has been loaded). */ c->setEnabled(false); Q_EMIT(collectionCreated(c)); // Try to load the collection from the path provided. c->unserialize(d); }
TEST_F(KVStorageEngineTest, RecreateIndexes) { repl::setGlobalReplicationCoordinator( new repl::ReplicationCoordinatorMock(getGlobalServiceContext(), repl::ReplSettings())); auto opCtx = cc().makeOperationContext(); // Create two indexes for `db.coll1` in the catalog named `foo` and `bar`. Verify the indexes // appear as idents in the KVEngine. ASSERT_OK(createCollection(opCtx.get(), NamespaceString("db.coll1")).getStatus()); ASSERT_OK(createIndex(opCtx.get(), NamespaceString("db.coll1"), "foo")); ASSERT_OK(createIndex(opCtx.get(), NamespaceString("db.coll1"), "bar")); auto kvIdents = getAllKVEngineIdents(opCtx.get()); ASSERT_EQUALS(2, std::count_if(kvIdents.begin(), kvIdents.end(), [](const std::string& str) { return str.find("index-") == 0; })); // Use the `getIndexNameObjs` to find the `foo` index in the IndexCatalog. DatabaseCatalogEntry* dbce = _storageEngine->getDatabaseCatalogEntry(opCtx.get(), "db"); CollectionCatalogEntry* cce = dbce->getCollectionCatalogEntry("db.coll1"); auto swIndexNameObjs = getIndexNameObjs( opCtx.get(), dbce, cce, [](const std::string& indexName) { return indexName == "foo"; }); ASSERT_OK(swIndexNameObjs.getStatus()); auto& indexNameObjs = swIndexNameObjs.getValue(); // There's one index that matched the name `foo`. ASSERT_EQUALS(static_cast<const unsigned long>(1), indexNameObjs.first.size()); // Assert the parallel vectors have matching sizes. ASSERT_EQUALS(static_cast<const unsigned long>(1), indexNameObjs.second.size()); // The index that matched should be named `foo`. ASSERT_EQUALS("foo", indexNameObjs.first[0]); ASSERT_EQUALS("db.coll1"_sd, indexNameObjs.second[0].getStringField("ns")); ASSERT_EQUALS("foo"_sd, indexNameObjs.second[0].getStringField("name")); ASSERT_EQUALS(2, indexNameObjs.second[0].getIntField("v")); ASSERT_EQUALS(1, indexNameObjs.second[0].getObjectField("key").getIntField("foo")); // Drop the `foo` index table. Count one remaining index ident according to the KVEngine. ASSERT_OK(dropIndexTable(opCtx.get(), NamespaceString("db.coll1"), "foo")); kvIdents = getAllKVEngineIdents(opCtx.get()); ASSERT_EQUALS(1, std::count_if(kvIdents.begin(), kvIdents.end(), [](const std::string& str) { return str.find("index-") == 0; })); AutoGetCollection coll(opCtx.get(), NamespaceString("db.coll1"), LockMode::MODE_X); // Find the `foo` index in the catalog. Rebuild it. Count two indexes in the KVEngine. ASSERT_OK(rebuildIndexesOnCollection(opCtx.get(), dbce, cce, indexNameObjs)); ASSERT_TRUE(cce->isIndexReady(opCtx.get(), "foo")); kvIdents = getAllKVEngineIdents(opCtx.get()); ASSERT_EQUALS(2, std::count_if(kvIdents.begin(), kvIdents.end(), [](const std::string& str) { return str.find("index-") == 0; })); }
Collection* RollbackTest::_createCollection(OperationContext* opCtx, const NamespaceString& nss, const CollectionOptions& options) { Lock::DBLock dbLock(opCtx, nss.db(), MODE_X); mongo::WriteUnitOfWork wuow(opCtx); auto databaseHolder = DatabaseHolder::get(opCtx); auto db = databaseHolder->openDb(opCtx, nss.db()); ASSERT_TRUE(db); db->dropCollection(opCtx, nss.ns()).transitional_ignore(); auto coll = db->createCollection(opCtx, nss.ns(), options); ASSERT_TRUE(coll); wuow.commit(); return coll; }
void run() { string ns = "unittests.rollback_drop_index"; const ServiceContext::UniqueOperationContext opCtxPtr = cc().makeOperationContext(); OperationContext& opCtx = *opCtxPtr; NamespaceString nss(ns); dropDatabase(&opCtx, nss); createCollection(&opCtx, nss); AutoGetDb autoDb(&opCtx, nss.db(), MODE_X); Collection* coll = autoDb.getDb()->getCollection(&opCtx, nss); IndexCatalog* catalog = coll->getIndexCatalog(); string idxName = "a"; BSONObj spec = BSON("ns" << ns << "key" << BSON("a" << 1) << "name" << idxName << "v" << static_cast<int>(kIndexVersion)); { WriteUnitOfWork uow(&opCtx); ASSERT_OK(catalog->createIndexOnEmptyCollection(&opCtx, spec)); insertRecord(&opCtx, nss, BSON("a" << 1)); insertRecord(&opCtx, nss, BSON("a" << 2)); insertRecord(&opCtx, nss, BSON("a" << 3)); uow.commit(); } ASSERT(indexReady(&opCtx, nss, idxName)); ASSERT_EQ(3u, getNumIndexEntries(&opCtx, nss, idxName)); // END SETUP / START TEST { WriteUnitOfWork uow(&opCtx); dropIndex(&opCtx, nss, idxName); ASSERT(!indexExists(&opCtx, nss, idxName)); if (!rollback) { uow.commit(); } } if (rollback) { ASSERT(indexExists(&opCtx, nss, idxName)); ASSERT(indexReady(&opCtx, nss, idxName)); ASSERT_EQ(3u, getNumIndexEntries(&opCtx, nss, idxName)); } else { ASSERT(!indexExists(&opCtx, nss, idxName)); } }
bool DBClientWithCommands::setDbProfilingLevel(const string &dbname, ProfilingLevel level, BSONObj *info ) { BSONObj o; if ( info == 0 ) info = &o; if ( level ) { // Create system.profile collection. If it already exists this does nothing. // TODO: move this into the db instead of here so that all // drivers don't have to do this. string ns = dbname + ".system.profile"; createCollection(ns.c_str(), 1024 * 1024, true, 0, info); } BSONObjBuilder b; b.append("profile", (int) level); return runCommand(dbname, b.done(), *info); }
RecordStoreV1Base* MMAP1DatabaseCatalogEntry::_getNamespaceRecordStore( OperationContext* txn, const StringData& whosAsking) { NamespaceString nss( _name, "system.namespaces" ); if ( nss == whosAsking ) return NULL; RecordStoreV1Base* rs = _getRecordStore( txn, nss.ns() ); if ( rs != NULL ) return rs; CollectionOptions options; Status status = createCollection( txn, nss.ns(), options, true ); massertStatusOK( status ); rs = _getRecordStore( txn, nss.ns() ); invariant( rs ); return rs; }
/*! * This function provides our class's main functionality - namely, taking an * input name and path and creating the appropriate type of collection object * to handle it. Note that this function should probably not be run in the * event dispatch thread; we load the collection from the path given, which can * take a nontrivial amount of time. * * Also note that we don't do any validity checking on the collection name; it * is assumed that the caller did that before calling this function. * * The returned collection will have this object as a parent, so deleting this * object will also delete any collections it created. The new collection will * also have the same thread affinity as this object. * * The new collection, instead of being returned directly, will be given to our * caller (and potentially others) via a signal emission once the collection is * loaded. This means that this operation can be done in a different thread * from our caller. * * \param n The name for the new collection. * \param p The path to the collection. * \param s Whether or not to remember the collection for next time. */ void CSCollectionTypeResolver::newCollection(const QString &n, const QString &p, bool s) { /* SLOT */ CSAbstractCollection *c = NULL; // Create our new collection object. c = createCollection(n, p); // If we didn't create one, its type must be invalid. if(c == NULL) { #pragma message "TODO - Errors need to be handled here by emitting a signal" return; } // Set our collection's save property. c->setSaveOnExit(s); // Connect the collection to our slots. QObject::connect(c, SIGNAL(jobStarted(const QString &, bool)), this, SLOT(doJobStarted(const QString &, bool))); QObject::connect(c, SIGNAL(progressLimitsUpdated(int, int)), this, SLOT(doProgressLimitsUpdated(int, int))); QObject::connect(c, SIGNAL(progressUpdated(int)), this, SLOT(doProgressUpdated(int))); QObject::connect(c, SIGNAL(jobFinished(const QString &)), this, SLOT(doJobFinished(const QString &))); /* * The collection has been created, but we still need to load its data. * Emit the signal indicating that the collection exists, but set it * disabled (until it has been loaded). */ c->setEnabled(false); Q_EMIT(collectionCreated(c)); // Try to load the collection from the path provided. c->loadCollectionFromPath(p); }
LibraryCollectionLayer::LibraryCollectionLayer( QWidget* parent ) : GestureWidget(parent) , m_page(0) { setupUi(this); items.append(collectionItem0); items.append(collectionItem1); items.append(collectionItem2); items.append(collectionItem3); connect(collectionItem0, SIGNAL(tap(int)), this, SLOT(changeCollection(int))); connect(collectionItem1, SIGNAL(tap(int)), this, SLOT(changeCollection(int))); connect(collectionItem2, SIGNAL(tap(int)), this, SLOT(changeCollection(int))); connect(collectionItem3, SIGNAL(tap(int)), this, SLOT(changeCollection(int))); connect(VerticalPagerPopup, SIGNAL(nextPageReq()), this, SLOT(showNextPage())); connect(VerticalPagerPopup, SIGNAL(previousPageReq()), this, SLOT(showPreviousPage())); connect(addNewCollection, SIGNAL(clicked()), this, SIGNAL(createCollection())); }
void shouldListChildItems() { // GIVEN auto data = Testlib::AkonadiFakeData(); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto i1 = Akonadi::Item(42); i1.setPayloadFromData("42"); i1.setParentCollection(Akonadi::Collection(42)); // WHEN data.createItem(i1); // THEN QCOMPARE(data.childItems(c1.id()).size(), 1); QCOMPARE(data.childItems(c1.id()).at(0), i1); }
void shouldListChildCollections() { // GIVEN auto data = Testlib::AkonadiFakeData(); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); auto c2 = Akonadi::Collection(43); c2.setName(QStringLiteral("43")); c2.setParentCollection(Akonadi::Collection(42)); const auto colSet = QSet<Akonadi::Collection>() << c2; // WHEN data.createCollection(c1); data.createCollection(c2); // THEN QVERIFY(data.childCollections(c2.id()).isEmpty()); QCOMPARE(data.childCollections(c1.id()).toList().toSet(), colSet); }
int execInternalCommand(int commandCode, char* collection, char *id, char *value, int isObjt) { //printf("commandCode: %d - value: %s\n", commandCode, value); int collectionCreated = 0; int addDocument = 0; switch(commandCode) { case CREATE_COLLECTION: collectionCreated = createCollection(value); (collectionCreated) ? printf("Collection created with successfully!\n") : printf("The collection already exists!\n"); return 1; break; case ADD_DOCUMENT_IN_COLLECTION: if(isObjt == 1) { addDocument = addDocumentInCollection(collection, id, value); (addDocument) ? printf("Add Document with successfully!\n") : 0; return 1; } else { printf("the 'value' field does not contain a json object!\n"); return 0; } break; case FIND: if(isObjt == 1) { find(collection, id, value); return 1; } else { printf("the 'value' field does not contain a json object!\n"); return 0; } break; } return 0; }
Document* CreateValid11() { Document* doc = createDocument(); // collection Collection *col = createCollection(doc, "http://example.com/collection1"); setCollectionDisplayID(col, "Coll1"); setCollectionName(col, "Collection1"); setCollectionDescription(col, "A collection may contain multiple components"); // components DNAComponent *dc1 = createDNAComponent(doc, "http://example.com/dc1"); DNAComponent *dc2 = createDNAComponent(doc, "http://example.com/dc2"); setDNAComponentDisplayID(dc1, "DC1"); setDNAComponentDisplayID(dc2, "DC2"); setDNAComponentName(dc1, "DnaComponent1"); setDNAComponentName(dc2, "DnaComponent2"); addDNAComponentToCollection(col, dc1); addDNAComponentToCollection(col, dc2); // sequence DNASequence *ds1 = createDNASequence(doc, "http://example.com/ds1"); setDNASequenceNucleotides(ds1, "tccctatcagtgat"); setDNAComponentSequence(dc1, ds1); return doc; }
TEST_F(KVStorageEngineTest, ReconcileIdentsTest) { auto opCtx = cc().makeOperationContext(); // Add a collection, `db.coll1` to both the KVCatalog and KVEngine. The returned value is the // `ident` name given to the collection. auto swIdentName = createCollection(opCtx.get(), NamespaceString("db.coll1")); ASSERT_OK(swIdentName); // Create a table in the KVEngine not reflected in the KVCatalog. This should be dropped when // reconciling. ASSERT_OK(createCollTable(opCtx.get(), NamespaceString("db.coll2"))); ASSERT_OK(reconcile(opCtx.get()).getStatus()); auto identsVec = getAllKVEngineIdents(opCtx.get()); auto idents = std::set<std::string>(identsVec.begin(), identsVec.end()); // There are two idents. `_mdb_catalog` and the ident for `db.coll1`. ASSERT_EQUALS(static_cast<const unsigned long>(2), idents.size()); ASSERT_TRUE(idents.find(swIdentName.getValue()) != idents.end()); ASSERT_TRUE(idents.find("_mdb_catalog") != idents.end()); // Create a catalog entry for the `_id` index. Drop the created the table. ASSERT_OK(createIndex(opCtx.get(), NamespaceString("db.coll1"), "_id")); ASSERT_OK(dropIndexTable(opCtx.get(), NamespaceString("db.coll1"), "_id")); // The reconcile response should include this index as needing to be rebuilt. auto reconcileStatus = reconcile(opCtx.get()); ASSERT_OK(reconcileStatus.getStatus()); ASSERT_EQUALS(static_cast<const unsigned long>(1), reconcileStatus.getValue().size()); StorageEngine::CollectionIndexNamePair& toRebuild = reconcileStatus.getValue()[0]; ASSERT_EQUALS("db.coll1", toRebuild.first); ASSERT_EQUALS("_id", toRebuild.second); // Now drop the `db.coll1` table, while leaving the KVCatalog entry. ASSERT_OK(dropIdent(opCtx.get(), swIdentName.getValue())); ASSERT_EQUALS(static_cast<const unsigned long>(1), getAllKVEngineIdents(opCtx.get()).size()); // Reconciling this should result in an error. reconcileStatus = reconcile(opCtx.get()); ASSERT_NOT_OK(reconcileStatus.getStatus()); ASSERT_EQUALS(ErrorCodes::UnrecoverableRollbackError, reconcileStatus.getStatus()); }
void shouldModifyCollections() { // GIVEN auto data = Testlib::AkonadiFakeData(); QScopedPointer<Akonadi::MonitorInterface> monitor(data.createMonitor()); QSignalSpy spy(monitor.data(), &Akonadi::MonitorInterface::collectionChanged); auto c1 = Akonadi::Collection(42); c1.setName(QStringLiteral("42")); data.createCollection(c1); auto c2 = Akonadi::Collection(c1.id()); c2.setName(QStringLiteral("42-bis")); // WHEN data.modifyCollection(c2); // THEN QCOMPARE(data.collections().size(), 1); QCOMPARE(data.collection(c1.id()), c2); QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).value<Akonadi::Collection>(), c2); }
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); }