TEST( RocksRecordStoreTest, ForwardIterator ) { { unittest::TempDir td( _rocksRecordStoreTestDir ); scoped_ptr<rocksdb::DB> db( getDB( td.path() ) ); rocksdb::ColumnFamilyHandle* cf1; rocksdb::ColumnFamilyHandle* cf1_m; rocksdb::Status status; status = db->CreateColumnFamily( getColumnFamilyOptions(), "foo.bar1", &cf1 ); ASSERT_OK( toMongoStatus( status ) ); status = db->CreateColumnFamily( rocksdb::ColumnFamilyOptions(), "foo.bar1&", &cf1_m ); ASSERT_OK( toMongoStatus( status ) ); RocksRecordStore rs( "foo.bar", db.get(), cf1, cf1_m ); string s1 = "eliot was here"; string s2 = "antonio was here"; string s3 = "eliot and antonio were here"; DiskLoc loc1; DiskLoc loc2; DiskLoc loc3; { MyOperationContext opCtx( db.get() ); { WriteUnitOfWork uow( opCtx.recoveryUnit() ); StatusWith<DiskLoc> res = rs.insertRecord( &opCtx, s1.c_str(), s1.size() + 1, -1 ); ASSERT_OK( res.getStatus() ); loc1 = res.getValue(); res = rs.insertRecord( &opCtx, s2.c_str(), s2.size() + 1, -1 ); ASSERT_OK( res.getStatus() ); loc2 = res.getValue(); res = rs.insertRecord( &opCtx, s3.c_str(), s3.size() + 1, -1 ); ASSERT_OK( res.getStatus() ); loc3 = res.getValue(); } } OperationContextNoop txn; scoped_ptr<RecordIterator> iter( rs.getIterator( &txn ) ); ASSERT_EQUALS( false, iter->isEOF() ); ASSERT_EQUALS( loc1, iter->getNext() ); ASSERT_EQUALS( s1, iter->dataFor( loc1 ).data() ); ASSERT_EQUALS( false, iter->isEOF() ); ASSERT_EQUALS( loc2, iter->getNext() ); ASSERT_EQUALS( s2, iter->dataFor( loc2 ).data() ); ASSERT_EQUALS( false, iter->isEOF() ); ASSERT_EQUALS( loc3, iter->getNext() ); ASSERT_EQUALS( s3, iter->dataFor( loc3 ).data() ); ASSERT_EQUALS( true, iter->isEOF() ); ASSERT_EQUALS( DiskLoc(), iter->getNext() ); } }
TEST( RocksRecordStoreTest, Truncate1 ) { unittest::TempDir td( _rocksRecordStoreTestDir ); scoped_ptr<rocksdb::DB> db( getDB( td.path() ) ); { rocksdb::ColumnFamilyHandle* cf1; rocksdb::ColumnFamilyHandle* cf1_m; rocksdb::Status status; status = db->CreateColumnFamily( getColumnFamilyOptions(), "foo.bar1", &cf1 ); ASSERT_OK( toMongoStatus( status ) ); status = db->CreateColumnFamily( rocksdb::ColumnFamilyOptions(), "foo.bar1&", &cf1_m ); ASSERT_OK( toMongoStatus( status ) ); RocksRecordStore rs( "foo.bar", db.get(), cf1, cf1_m ); string s = "antonio was here"; { MyOperationContext opCtx( db.get() ); WriteUnitOfWork uow( opCtx.recoveryUnit() ); StatusWith<DiskLoc> res = rs.insertRecord( &opCtx, s.c_str(), s.size() + 1, -1 ); ASSERT_OK( res.getStatus() ); res = rs.insertRecord( &opCtx, s.c_str(), s.size() + 1, -1 ); ASSERT_OK( res.getStatus() ); } { MyOperationContext opCtx( db.get() ); WriteUnitOfWork uow( opCtx.recoveryUnit() ); Status stat = rs.truncate( &opCtx ); ASSERT_OK( stat ); ASSERT_EQUALS( 0, rs.numRecords() ); ASSERT_EQUALS( 0, rs.dataSize() ); } // Test that truncate does not fail on an empty collection { MyOperationContext opCtx( db.get() ); WriteUnitOfWork uow( opCtx.recoveryUnit() ); Status stat = rs.truncate( &opCtx ); ASSERT_OK( stat ); ASSERT_EQUALS( 0, rs.numRecords() ); ASSERT_EQUALS( 0, rs.dataSize() ); } } }
TEST( RocksRecordStoreTest, TwoCollections ) { unittest::TempDir td( _rocksRecordStoreTestDir ); scoped_ptr<rocksdb::DB> db( getDB( td.path() ) ); rocksdb::ColumnFamilyHandle* cf1; rocksdb::ColumnFamilyHandle* cf2; rocksdb::ColumnFamilyHandle* cf1_m; rocksdb::ColumnFamilyHandle* cf2_m; rocksdb::Status status; status = db->CreateColumnFamily( rocksdb::ColumnFamilyOptions(), "foo.bar1", &cf1 ); ASSERT_OK( toMongoStatus( status ) ); status = db->CreateColumnFamily( rocksdb::ColumnFamilyOptions(), "foo.bar2", &cf2 ); ASSERT_OK( toMongoStatus( status ) ); status = db->CreateColumnFamily( rocksdb::ColumnFamilyOptions(), "foo.bar1&", &cf1_m ); ASSERT_OK( toMongoStatus( status ) ); status = db->CreateColumnFamily( rocksdb::ColumnFamilyOptions(), "foo.bar2&", &cf2_m ); ASSERT_OK( toMongoStatus( status ) ); RocksRecordStore rs1( "foo.bar1", db.get(), cf1, cf1_m ); RocksRecordStore rs2( "foo.bar2", db.get(), cf2, cf2_m ); DiskLoc a; DiskLoc b; { MyOperationContext opCtx( db.get() ); WriteUnitOfWork uow( opCtx.recoveryUnit() ); StatusWith<DiskLoc> result = rs1.insertRecord( &opCtx, "a", 2, -1 ); ASSERT_OK( result.getStatus() ); a = result.getValue(); result = rs2.insertRecord( &opCtx, "b", 2, -1 ); ASSERT_OK( result.getStatus() ); b = result.getValue(); } ASSERT_EQUALS( a, b ); ASSERT_EQUALS( string("a"), rs1.dataFor( a ).data() ); ASSERT_EQUALS( string("b"), rs2.dataFor( b ).data() ); delete cf2; delete cf1; }
Status RocksEngine::dropIdent(OperationContext* opCtx, StringData ident) { // TODO optimize this using CompactionFilterV2 rocksdb::WriteBatch wb; wb.Delete(kMetadataPrefix + ident.toString()); std::string prefix = _getIdentPrefix(ident); rocksdb::Slice prefixSlice(prefix.data(), prefix.size()); boost::scoped_ptr<rocksdb::Iterator> _iter(_db->NewIterator(rocksdb::ReadOptions())); for (_iter->Seek(prefixSlice); _iter->Valid() && _iter->key().starts_with(prefixSlice); _iter->Next()) { ROCKS_STATUS_OK(_iter->status()); wb.Delete(_iter->key()); } auto s = _db->Write(rocksdb::WriteOptions(), &wb); if (!s.ok()) { return toMongoStatus(s); } { boost::mutex::scoped_lock lk(_identPrefixMapMutex); _identPrefixMap.erase(ident); } return Status::OK(); }
rocksdb::DB* getDBPersist( string path ) { rocksdb::Options options = RocksEngine::dbOptions(); // open DB rocksdb::DB* db; rocksdb::Status s = rocksdb::DB::Open(options, path, &db); ASSERT_OK( toMongoStatus( s ) ); return db; }
rocksdb::DB* getDB( string path) { boost::filesystem::remove_all( path ); rocksdb::Options options = RocksEngine::dbOptions(); // open DB rocksdb::DB* db; rocksdb::Status s = rocksdb::DB::Open(options, path, &db); ASSERT_OK( toMongoStatus( s ) ); return db; }
// non public api Status RocksEngine::_createIdentPrefix(StringData ident) { uint32_t prefix = 0; { boost::mutex::scoped_lock lk(_identPrefixMapMutex); if (_identPrefixMap.find(ident) != _identPrefixMap.end()) { // already exists return Status::OK(); } prefix = ++_maxPrefix; _identPrefixMap[ident] = prefix; } BSONObjBuilder builder; builder.append("prefix", static_cast<int32_t>(prefix)); BSONObj config = builder.obj(); auto s = _db->Put(rocksdb::WriteOptions(), kMetadataPrefix + ident.toString(), rocksdb::Slice(config.objdata(), config.objsize())); return toMongoStatus(s); }