diff --git a/src/cluster/cluster.cc b/src/cluster/cluster.cc index 6a90d39df3b..69703f7eed0 100644 --- a/src/cluster/cluster.cc +++ b/src/cluster/cluster.cc @@ -116,6 +116,7 @@ Status Cluster::SetSlotRanges(const std::vector &slot_ranges, const s // 3. Update the map of slots to nodes. // remember: The atomicity of the process is based on // the transactionality of ClearKeysOfSlotRange(). + engine::Context ctx(srv_->storage); for (auto [s_start, s_end] : slot_ranges) { for (int slot = s_start; slot <= s_end; slot++) { std::shared_ptr old_node = slots_nodes_[slot]; @@ -129,7 +130,7 @@ Status Cluster::SetSlotRanges(const std::vector &slot_ranges, const s if (old_node == myself_ && old_node != to_assign_node) { // If slot is migrated from this node if (migrated_slots_.count(slot) > 0) { - auto s = srv_->slot_migrator->ClearKeysOfSlotRange(kDefaultNamespace, SlotRange::GetPoint(slot)); + auto s = srv_->slot_migrator->ClearKeysOfSlotRange(ctx, kDefaultNamespace, SlotRange::GetPoint(slot)); if (!s.ok()) { LOG(ERROR) << "failed to clear data of migrated slot: " << s.ToString(); } @@ -212,9 +213,10 @@ Status Cluster::SetClusterNodes(const std::string &nodes_str, int64_t version, b // Clear data of migrated slots if (!migrated_slots_.empty()) { + engine::Context ctx(srv_->storage); for (const auto &[slot, _] : migrated_slots_) { if (slots_nodes_[slot] != myself_) { - auto s = srv_->slot_migrator->ClearKeysOfSlotRange(kDefaultNamespace, SlotRange::GetPoint(slot)); + auto s = srv_->slot_migrator->ClearKeysOfSlotRange(ctx, kDefaultNamespace, SlotRange::GetPoint(slot)); if (!s.ok()) { LOG(ERROR) << "failed to clear data of migrated slots: " << s.ToString(); } diff --git a/src/cluster/slot_import.cc b/src/cluster/slot_import.cc index ef04aba7a70..2b1830b28b7 100644 --- a/src/cluster/slot_import.cc +++ b/src/cluster/slot_import.cc @@ -40,7 +40,8 @@ Status SlotImport::Start(const SlotRange &slot_range) { } // Clean slot data first - auto s = ClearKeysOfSlotRange(namespace_, slot_range); + engine::Context ctx(srv_->storage); + auto s = ClearKeysOfSlotRange(ctx, namespace_, slot_range); if (!s.ok()) { return {Status::NotOK, fmt::format("clear keys of slot(s) error: {}", s.ToString())}; } @@ -74,7 +75,8 @@ Status SlotImport::Fail(const SlotRange &slot_range) { } // Clean imported slot data - auto s = ClearKeysOfSlotRange(namespace_, slot_range); + engine::Context ctx(srv_->storage); + auto s = ClearKeysOfSlotRange(ctx, namespace_, slot_range); if (!s.ok()) { return {Status::NotOK, fmt::format("clear keys of slot(s) error: {}", s.ToString())}; } @@ -99,7 +101,8 @@ Status SlotImport::StopForLinkError() { // from new master. if (!srv_->IsSlave()) { // Clean imported slot data - auto s = ClearKeysOfSlotRange(namespace_, import_slot_range_); + engine::Context ctx(srv_->storage); + auto s = ClearKeysOfSlotRange(ctx, namespace_, import_slot_range_); if (!s.ok()) { return {Status::NotOK, fmt::format("clear keys of slot error: {}", s.ToString())}; } diff --git a/src/cluster/slot_migrate.cc b/src/cluster/slot_migrate.cc index cd7e9e42486..e59aee1b91f 100644 --- a/src/cluster/slot_migrate.cc +++ b/src/cluster/slot_migrate.cc @@ -1254,7 +1254,8 @@ Status SlotMigrator::sendSnapshotByRawKV() { read_options.snapshot = slot_snapshot_; rocksdb::Slice prefix_slice(prefix); read_options.iterate_lower_bound = &prefix_slice; - engine::DBIterator iter(storage_, read_options); + auto no_txn_ctx = engine::Context::NoTransactionContext(storage_); + engine::DBIterator iter(no_txn_ctx, read_options); BatchSender batch_sender(*dst_fd_, migrate_batch_size_bytes_, migrate_batch_bytes_per_sec_); diff --git a/src/commands/cmd_bit.cc b/src/commands/cmd_bit.cc index 42447d2f691..973c803e031 100644 --- a/src/commands/cmd_bit.cc +++ b/src/commands/cmd_bit.cc @@ -49,7 +49,8 @@ class CommandGetBit : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { bool bit = false; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - auto s = bitmap_db.GetBit(args_[1], offset_, &bit); + engine::Context ctx(srv->storage); + auto s = bitmap_db.GetBit(ctx, args_[1], offset_, &bit); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(bit ? 1 : 0); @@ -80,7 +81,8 @@ class CommandSetBit : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { bool old_bit = false; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - auto s = bitmap_db.SetBit(args_[1], offset_, bit_, &old_bit); + engine::Context ctx(srv->storage); + auto s = bitmap_db.SetBit(ctx, args_[1], offset_, bit_, &old_bit); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(old_bit ? 1 : 0); @@ -135,7 +137,8 @@ class CommandBitCount : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint32_t cnt = 0; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - auto s = bitmap_db.BitCount(args_[1], start_, stop_, is_bit_index_, &cnt); + engine::Context ctx(srv->storage); + auto s = bitmap_db.BitCount(ctx, args_[1], start_, stop_, is_bit_index_, &cnt); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(cnt); @@ -194,7 +197,8 @@ class CommandBitPos : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t pos = 0; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - auto s = bitmap_db.BitPos(args_[1], bit_, start_, stop_, stop_given_, &pos, is_bit_index_); + engine::Context ctx(srv->storage); + auto s = bitmap_db.BitPos(ctx, args_[1], bit_, start_, stop_, stop_given_, &pos, is_bit_index_); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(pos); @@ -239,7 +243,8 @@ class CommandBitOp : public Commander { int64_t dest_key_len = 0; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - auto s = bitmap_db.BitOp(op_flag_, args_[1], args_[2], op_keys, &dest_key_len); + engine::Context ctx(srv->storage); + auto s = bitmap_db.BitOp(ctx, op_flag_, args_[1], args_[2], op_keys, &dest_key_len); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(dest_key_len); @@ -336,10 +341,11 @@ class CommandBitfield : public Commander { redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); std::vector> rets; rocksdb::Status s; + engine::Context ctx(srv->storage); if (read_only_) { - s = bitmap_db.BitfieldReadOnly(args_[1], cmds_, &rets); + s = bitmap_db.BitfieldReadOnly(ctx, args_[1], cmds_, &rets); } else { - s = bitmap_db.Bitfield(args_[1], cmds_, &rets); + s = bitmap_db.Bitfield(ctx, args_[1], cmds_, &rets); } std::vector str_rets(rets.size()); for (size_t i = 0; i != rets.size(); ++i) { diff --git a/src/commands/cmd_bloom_filter.cc b/src/commands/cmd_bloom_filter.cc index 8f2963755a4..1020954fef2 100644 --- a/src/commands/cmd_bloom_filter.cc +++ b/src/commands/cmd_bloom_filter.cc @@ -90,7 +90,8 @@ class CommandBFReserve : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloomfilter_db(srv->storage, conn->GetNamespace()); - auto s = bloomfilter_db.Reserve(args_[1], capacity_, error_rate_, expansion_); + engine::Context ctx(srv->storage); + auto s = bloomfilter_db.Reserve(ctx, args_[1], capacity_, error_rate_, expansion_); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::SimpleString("OK"); @@ -108,7 +109,8 @@ class CommandBFAdd : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); BloomFilterAddResult ret = BloomFilterAddResult::kOk; - auto s = bloom_db.Add(args_[1], args_[2], &ret); + engine::Context ctx(srv->storage); + auto s = bloom_db.Add(ctx, args_[1], args_[2], &ret); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; switch (ret) { @@ -139,7 +141,8 @@ class CommandBFMAdd : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); std::vector rets(items_.size(), BloomFilterAddResult::kOk); - auto s = bloom_db.MAdd(args_[1], items_, &rets); + engine::Context ctx(srv->storage); + auto s = bloom_db.MAdd(ctx, args_[1], items_, &rets); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::MultiLen(items_.size()); @@ -234,7 +237,8 @@ class CommandBFInsert : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); std::vector rets(items_.size(), BloomFilterAddResult::kOk); - auto s = bloom_db.InsertCommon(args_[1], items_, insert_options_, &rets); + engine::Context ctx(srv->storage); + auto s = bloom_db.InsertCommon(ctx, args_[1], items_, insert_options_, &rets); if (s.IsNotFound()) return {Status::RedisExecErr, "key is not found"}; if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; @@ -265,7 +269,8 @@ class CommandBFExists : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); bool exist = false; - auto s = bloom_db.Exists(args_[1], args_[2], &exist); + engine::Context ctx(srv->storage); + auto s = bloom_db.Exists(ctx, args_[1], args_[2], &exist); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(exist ? 1 : 0); @@ -286,7 +291,8 @@ class CommandBFMExists : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); std::vector exists(items_.size(), false); - auto s = bloom_db.MExists(args_[1], items_, &exists); + engine::Context ctx(srv->storage); + auto s = bloom_db.MExists(ctx, args_[1], items_, &exists); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::MultiLen(items_.size()); @@ -329,7 +335,8 @@ class CommandBFInfo : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); BloomFilterInfo info; - auto s = bloom_db.Info(args_[1], &info); + engine::Context ctx(srv->storage); + auto s = bloom_db.Info(ctx, args_[1], &info); if (s.IsNotFound()) return {Status::RedisExecErr, "key is not found"}; if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; @@ -376,7 +383,8 @@ class CommandBFCard : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::BloomChain bloom_db(srv->storage, conn->GetNamespace()); BloomFilterInfo info; - auto s = bloom_db.Info(args_[1], &info); + engine::Context ctx(srv->storage); + auto s = bloom_db.Info(ctx, args_[1], &info); if (!s.ok() && !s.IsNotFound()) return {Status::RedisExecErr, s.ToString()}; if (s.IsNotFound()) { *output = redis::Integer(0); diff --git a/src/commands/cmd_function.cc b/src/commands/cmd_function.cc index 7d831f80845..475ed72481f 100644 --- a/src/commands/cmd_function.cc +++ b/src/commands/cmd_function.cc @@ -22,6 +22,7 @@ #include "commands/command_parser.h" #include "parse_util.h" #include "server/redis_reply.h" +#include "server/server.h" #include "storage/scripting.h" #include "string_util.h" @@ -30,6 +31,7 @@ namespace redis { struct CommandFunction : Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { CommandParser parser(args_, 1); + engine::Context ctx(srv->storage); if (parser.EatEqICase("load")) { bool replace = false; if (parser.EatEqICase("replace")) { @@ -70,8 +72,7 @@ struct CommandFunction : Commander { if (!lua::FunctionIsLibExist(conn, libname)) { return {Status::NotOK, "no such library"}; } - - auto s = lua::FunctionDelete(srv, libname); + auto s = lua::FunctionDelete(ctx, srv, libname); if (!s) return s; *output = SimpleString("OK"); diff --git a/src/commands/cmd_geo.cc b/src/commands/cmd_geo.cc index a95bd927cb7..4c01a665f70 100644 --- a/src/commands/cmd_geo.cc +++ b/src/commands/cmd_geo.cc @@ -114,7 +114,8 @@ class CommandGeoAdd : public CommandGeoBase { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.Add(args_[1], &geo_points_, &ret); + engine::Context ctx(srv->storage); + auto s = geo_db.Add(ctx, args_[1], &geo_points_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -142,7 +143,8 @@ class CommandGeoDist : public CommandGeoBase { Status Execute(Server *srv, Connection *conn, std::string *output) override { double distance = 0; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.Dist(args_[1], args_[2], args_[3], &distance); + engine::Context ctx(srv->storage); + auto s = geo_db.Dist(ctx, args_[1], args_[2], args_[3], &distance); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -168,7 +170,8 @@ class CommandGeoHash : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::vector hashes; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.Hash(args_[1], members_, &hashes); + engine::Context ctx(srv->storage); + auto s = geo_db.Hash(ctx, args_[1], members_, &hashes); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -197,7 +200,8 @@ class CommandGeoPos : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::map geo_points; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.Pos(args_[1], members_, &geo_points); + engine::Context ctx(srv->storage); + auto s = geo_db.Pos(ctx, args_[1], members_, &geo_points); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -304,7 +308,8 @@ class CommandGeoRadius : public CommandGeoBase { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::vector geo_points; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.Radius(args_[1], longitude_, latitude_, GetRadiusMeters(radius_), count_, sort_, store_key_, + engine::Context ctx(srv->storage); + auto s = geo_db.Radius(ctx, args_[1], longitude_, latitude_, GetRadiusMeters(radius_), count_, sort_, store_key_, store_distance_, GetUnitConversion(), &geo_points); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; @@ -452,8 +457,9 @@ class CommandGeoSearch : public CommandGeoBase { std::vector geo_points; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.Search(args_[1], geo_shape_, origin_point_type_, member_, count_, sort_, false, GetUnitConversion(), - &geo_points); + engine::Context ctx(srv->storage); + auto s = geo_db.Search(ctx, args_[1], geo_shape_, origin_point_type_, member_, count_, sort_, false, + GetUnitConversion(), &geo_points); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; @@ -614,7 +620,8 @@ class CommandGeoSearchStore : public CommandGeoSearch { std::vector geo_points; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.SearchStore(args_[2], geo_shape_, origin_point_type_, member_, count_, sort_, store_key_, + engine::Context ctx(srv->storage); + auto s = geo_db.SearchStore(ctx, args_[2], geo_shape_, origin_point_type_, member_, count_, sort_, store_key_, store_distance_, GetUnitConversion(), &geo_points); if (!s.ok()) { @@ -654,7 +661,8 @@ class CommandGeoRadiusByMember : public CommandGeoRadius { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::vector geo_points; redis::Geo geo_db(srv->storage, conn->GetNamespace()); - auto s = geo_db.RadiusByMember(args_[1], args_[2], GetRadiusMeters(radius_), count_, sort_, store_key_, + engine::Context ctx(srv->storage); + auto s = geo_db.RadiusByMember(ctx, args_[1], args_[2], GetRadiusMeters(radius_), count_, sort_, store_key_, store_distance_, GetUnitConversion(), &geo_points); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; diff --git a/src/commands/cmd_hash.cc b/src/commands/cmd_hash.cc index c0000ccfe06..a3aee46a3db 100644 --- a/src/commands/cmd_hash.cc +++ b/src/commands/cmd_hash.cc @@ -32,7 +32,8 @@ class CommandHGet : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::string value; - auto s = hash_db.Get(args_[1], args_[2], &value); + engine::Context ctx(srv->storage); + auto s = hash_db.Get(ctx, args_[1], args_[2], &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -57,7 +58,8 @@ class CommandHSetNX : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.MSet(args_[1], field_values_, true, &ret); + engine::Context ctx(srv->storage); + auto s = hash_db.MSet(ctx, args_[1], field_values_, true, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -75,7 +77,8 @@ class CommandHStrlen : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::string value; - auto s = hash_db.Get(args_[1], args_[2], &value); + engine::Context ctx(srv->storage); + auto s = hash_db.Get(ctx, args_[1], args_[2], &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -95,7 +98,8 @@ class CommandHDel : public Commander { uint64_t ret = 0; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.Delete(args_[1], fields, &ret); + engine::Context ctx(srv->storage); + auto s = hash_db.Delete(ctx, args_[1], fields, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -110,7 +114,8 @@ class CommandHExists : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::string value; - auto s = hash_db.Get(args_[1], args_[2], &value); + engine::Context ctx(srv->storage); + auto s = hash_db.Get(ctx, args_[1], args_[2], &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -125,7 +130,8 @@ class CommandHLen : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t count = 0; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.Size(args_[1], &count); + engine::Context ctx(srv->storage); + auto s = hash_db.Size(ctx, args_[1], &count); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -150,7 +156,8 @@ class CommandHIncrBy : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t ret = 0; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.IncrBy(args_[1], args_[2], increment_, &ret); + engine::Context ctx(srv->storage); + auto s = hash_db.IncrBy(ctx, args_[1], args_[2], increment_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -177,7 +184,8 @@ class CommandHIncrByFloat : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { double ret = 0; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.IncrByFloat(args_[1], args_[2], increment_, &ret); + engine::Context ctx(srv->storage); + auto s = hash_db.IncrByFloat(ctx, args_[1], args_[2], increment_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -201,7 +209,8 @@ class CommandHMGet : public Commander { std::vector values; std::vector statuses; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.MGet(args_[1], fields, &values, &statuses); + engine::Context ctx(srv->storage); + auto s = hash_db.MGet(ctx, args_[1], fields, &values, &statuses); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -231,7 +240,8 @@ class CommandHMSet : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::Hash hash_db(srv->storage, conn->GetNamespace()); - auto s = hash_db.MSet(args_[1], field_values_, false, &ret); + engine::Context ctx(srv->storage); + auto s = hash_db.MSet(ctx, args_[1], field_values_, false, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -253,7 +263,8 @@ class CommandHKeys : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::vector field_values; - auto s = hash_db.GetAll(args_[1], &field_values, HashFetchType::kOnlyKey); + engine::Context ctx(srv->storage); + auto s = hash_db.GetAll(ctx, args_[1], &field_values, HashFetchType::kOnlyKey); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -274,7 +285,8 @@ class CommandHVals : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::vector field_values; - auto s = hash_db.GetAll(args_[1], &field_values, HashFetchType::kOnlyValue); + engine::Context ctx(srv->storage); + auto s = hash_db.GetAll(ctx, args_[1], &field_values, HashFetchType::kOnlyValue); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -295,7 +307,8 @@ class CommandHGetAll : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::vector field_values; - auto s = hash_db.GetAll(args_[1], &field_values); + engine::Context ctx(srv->storage); + auto s = hash_db.GetAll(ctx, args_[1], &field_values); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -336,7 +349,8 @@ class CommandHRangeByLex : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::vector field_values; - rocksdb::Status s = hash_db.RangeByLex(args_[1], spec_, &field_values); + engine::Context ctx(srv->storage); + rocksdb::Status s = hash_db.RangeByLex(ctx, args_[1], spec_, &field_values); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -362,7 +376,8 @@ class CommandHScan : public CommandSubkeyScanBase { std::vector fields; std::vector values; auto key_name = srv->GetKeyNameFromCursor(cursor_, CursorType::kTypeHash); - auto s = hash_db.Scan(key_, key_name, limit_, prefix_, &fields, &values); + engine::Context ctx(srv->storage); + auto s = hash_db.Scan(ctx, key_, key_name, limit_, prefix_, &fields, &values); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -403,7 +418,8 @@ class CommandHRandField : public Commander { redis::Hash hash_db(srv->storage, conn->GetNamespace()); std::vector field_values; - auto s = hash_db.RandField(args_[1], command_count_, &field_values, + engine::Context ctx(srv->storage); + auto s = hash_db.RandField(ctx, args_[1], command_count_, &field_values, withvalues_ ? HashFetchType::kAll : HashFetchType::kOnlyKey); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; diff --git a/src/commands/cmd_hll.cc b/src/commands/cmd_hll.cc index 328ab45eeb0..2e2c246254b 100644 --- a/src/commands/cmd_hll.cc +++ b/src/commands/cmd_hll.cc @@ -41,7 +41,8 @@ class CommandPfAdd final : public Commander { hashes[i - 2] = redis::HyperLogLog::HllHash(args_[i]); } uint64_t ret{}; - auto s = hll.Add(args_[1], hashes, &ret); + engine::Context ctx(srv->storage); + auto s = hll.Add(ctx, args_[1], hashes, &ret); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -61,11 +62,12 @@ class CommandPfCount final : public Commander { rocksdb::Status s; // The first argument is the command name, so we need to skip it. DCHECK_GE(args_.size(), 2u); + engine::Context ctx(srv->storage); if (args_.size() > 2) { std::vector keys(args_.begin() + 1, args_.end()); - s = hll.CountMultiple(keys, &ret); + s = hll.CountMultiple(ctx, keys, &ret); } else { - s = hll.Count(args_[1], &ret); + s = hll.Count(ctx, args_[1], &ret); } if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; @@ -86,7 +88,8 @@ class CommandPfMerge final : public Commander { redis::HyperLogLog hll(srv->storage, conn->GetNamespace()); DCHECK_GT(args_.size(), 1u); std::vector src_user_keys(args_.begin() + 2, args_.end()); - auto s = hll.Merge(/*dest_user_key=*/args_[1], src_user_keys); + engine::Context ctx(srv->storage); + auto s = hll.Merge(ctx, /*dest_user_key=*/args_[1], src_user_keys); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_json.cc b/src/commands/cmd_json.cc index c861bf60964..571b96074aa 100644 --- a/src/commands/cmd_json.cc +++ b/src/commands/cmd_json.cc @@ -57,8 +57,8 @@ class CommandJsonSet : public Commander { public: Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Json json(srv->storage, conn->GetNamespace()); - - auto s = json.Set(args_[1], args_[2], args_[3]); + engine::Context ctx(srv->storage); + auto s = json.Set(ctx, args_[1], args_[2], args_[3]); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::SimpleString("OK"); @@ -106,7 +106,8 @@ class CommandJsonGet : public Commander { redis::Json json(srv->storage, conn->GetNamespace()); JsonValue result; - auto s = json.Get(args_[1], paths_, &result); + engine::Context ctx(srv->storage); + auto s = json.Get(ctx, args_[1], paths_, &result); if (s.IsNotFound()) { *output = conn->NilString(); return Status::OK(); @@ -131,7 +132,8 @@ class CommandJsonInfo : public Commander { redis::Json json(srv->storage, conn->GetNamespace()); auto storage_format = JsonStorageFormat::JSON; - auto s = json.Info(args_[1], &storage_format); + engine::Context ctx(srv->storage); + auto s = json.Info(ctx, args_[1], &storage_format); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; auto format_str = storage_format == JsonStorageFormat::JSON ? "json" @@ -149,7 +151,8 @@ class CommandJsonArrAppend : public Commander { Optionals results; - auto s = json.ArrAppend(args_[1], args_[2], {args_.begin() + 3, args_.end()}, &results); + engine::Context ctx(srv->storage); + auto s = json.ArrAppend(ctx, args_[1], args_[2], {args_.begin() + 3, args_.end()}, &results); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = OptionalsToString(conn, results); @@ -175,7 +178,8 @@ class CommandJsonArrInsert : public Commander { Optionals results; auto parse_result = ParseInt(args_[3], 10); - auto s = json.ArrInsert(args_[1], args_[2], index_, {args_.begin() + 4, args_.end()}, &results); + engine::Context ctx(srv->storage); + auto s = json.ArrInsert(ctx, args_[1], args_[2], index_, {args_.begin() + 4, args_.end()}, &results); if (s.IsNotFound()) { *output = conn->NilString(); return Status::OK(); @@ -203,7 +207,8 @@ class CommandJsonType : public Commander { } else if (args_.size() > 3) { return {Status::RedisExecErr, "The number of arguments is more than expected"}; } - auto s = json.Type(args_[1], path, &types); + engine::Context ctx(srv->storage); + auto s = json.Type(ctx, args_[1], path, &types); if (!s.ok() && !s.IsNotFound()) return {Status::RedisExecErr, s.ToString()}; if (s.IsNotFound()) { *output = conn->NilString(); @@ -224,7 +229,8 @@ class CommandJsonObjkeys : public Commander { // If path not specified set it to $ std::string path = (args_.size() > 2) ? args_[2] : "$"; - auto s = json.ObjKeys(args_[1], path, &results); + engine::Context ctx(srv->storage); + auto s = json.ObjKeys(ctx, args_[1], path, &results); if (!s.ok() && !s.IsNotFound()) return {Status::RedisExecErr, s.ToString()}; if (s.IsNotFound()) { *output = conn->NilString(); @@ -253,7 +259,8 @@ class CommandJsonClear : public Commander { // If path not specified set it to $ std::string path = (args_.size() > 2) ? args_[2] : "$"; - auto s = json.Clear(args_[1], path, &result); + engine::Context ctx(svr->storage); + auto s = json.Clear(ctx, args_[1], path, &result); if (s.IsNotFound()) { *output = conn->NilString(); @@ -274,7 +281,8 @@ class CommandJsonToggle : public Commander { std::string path = (args_.size() > 2) ? args_[2] : "$"; Optionals results; - auto s = json.Toggle(args_[1], path, &results); + engine::Context ctx(svr->storage); + auto s = json.Toggle(ctx, args_[1], path, &results); if (!s.ok() && !s.IsNotFound()) return {Status::RedisExecErr, s.ToString()}; if (s.IsNotFound()) { *output = conn->NilString(); @@ -299,7 +307,8 @@ class CommandJsonArrLen : public Commander { } Optionals results; - auto s = json.ArrLen(args_[1], path, &results); + engine::Context ctx(svr->storage); + auto s = json.ArrLen(ctx, args_[1], path, &results); if (s.IsNotFound()) { *output = conn->NilString(); return Status::OK(); @@ -320,8 +329,8 @@ class CommandJsonMerge : public Commander { std::string path = args_[2]; std::string value = args_[3]; bool result = false; - - auto s = json.Merge(key, path, value, result); + engine::Context ctx(svr->storage); + auto s = json.Merge(ctx, key, path, value, result); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; @@ -355,8 +364,8 @@ class CommandJsonArrPop : public Commander { redis::Json json(srv->storage, conn->GetNamespace()); Optionals results; - - auto s = json.ArrPop(args_[1], path_, index_, &results); + engine::Context ctx(srv->storage); + auto s = json.ArrPop(ctx, args_[1], path_, index_, &results); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::MultiLen(results.size()); @@ -389,7 +398,8 @@ class CommandJsonObjLen : public Commander { } Optionals results; - auto s = json.ObjLen(args_[1], path, &results); + engine::Context ctx(svr->storage); + auto s = json.ObjLen(ctx, args_[1], path, &results); if (s.IsNotFound()) { if (args_.size() == 2) { *output = conn->NilString(); @@ -420,7 +430,8 @@ class CommandJsonArrTrim : public Commander { Optionals results; - auto s = json.ArrTrim(args_[1], path_, start_, stop_, &results); + engine::Context ctx(srv->storage); + auto s = json.ArrTrim(ctx, args_[1], path_, start_, stop_, &results); if (s.IsNotFound()) { return {Status::RedisExecErr, "could not perform this operation on a key that doesn't exist"}; @@ -460,7 +471,8 @@ class CommanderJsonArrIndex : public Commander { Optionals results; - auto s = json.ArrIndex(args_[1], args_[2], args_[3], start_, end_, &results); + engine::Context ctx(svr->storage); + auto s = json.ArrIndex(ctx, args_[1], args_[2], args_[3], start_, end_, &results); if (s.IsNotFound()) { *output = conn->NilString(); @@ -489,7 +501,8 @@ class CommandJsonDel : public Commander { } else if (args_.size() > 3) { return {Status::RedisExecErr, "The number of arguments is more than expected"}; } - auto s = json.Del(args_[1], path, &result); + engine::Context ctx(svr->storage); + auto s = json.Del(ctx, args_[1], path, &result); if (s.IsNotFound()) { *output = conn->NilString(); return Status::OK(); @@ -506,7 +519,8 @@ class CommandJsonNumIncrBy : public Commander { redis::Json json(svr->storage, conn->GetNamespace()); JsonValue result = JsonValue::FromString("[]").GetValue(); - auto s = json.NumIncrBy(args_[1], args_[2], args_[3], &result); + engine::Context ctx(svr->storage); + auto s = json.NumIncrBy(ctx, args_[1], args_[2], args_[3], &result); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -523,7 +537,8 @@ class CommandJsonNumMultBy : public Commander { redis::Json json(svr->storage, conn->GetNamespace()); JsonValue result = JsonValue::FromString("[]").GetValue(); - auto s = json.NumMultBy(args_[1], args_[2], args_[3], &result); + engine::Context ctx(svr->storage); + auto s = json.NumMultBy(ctx, args_[1], args_[2], args_[3], &result); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -548,7 +563,8 @@ class CommandJsonStrAppend : public Commander { } Optionals results; - auto s = json.StrAppend(args_[1], path, args_[3], &results); + engine::Context ctx(svr->storage); + auto s = json.StrAppend(ctx, args_[1], path, args_[3], &results); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = OptionalsToString(conn, results); @@ -569,7 +585,8 @@ class CommandJsonStrLen : public Commander { } Optionals results; - auto s = json.StrLen(args_[1], path, &results); + engine::Context ctx(svr->storage); + auto s = json.StrLen(ctx, args_[1], path, &results); if (s.IsNotFound()) { if (args_.size() == 2) { *output = conn->NilString(); @@ -598,7 +615,8 @@ class CommandJsonMGet : public Commander { } std::vector json_values; - auto statuses = json.MGet(user_keys, path, json_values); + engine::Context ctx(svr->storage); + auto statuses = json.MGet(ctx, user_keys, path, json_values); std::vector values; values.resize(user_keys.size()); @@ -632,7 +650,8 @@ class CommandJsonMSet : public Commander { values.emplace_back(args_[i * 3 + 3]); } - if (auto s = json.MSet(user_keys, paths, values); !s.ok()) return {Status::RedisExecErr, s.ToString()}; + engine::Context ctx(svr->storage); + if (auto s = json.MSet(ctx, user_keys, paths, values); !s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::SimpleString("OK"); return Status::OK(); @@ -657,7 +676,8 @@ class CommandJsonDebug : public Commander { } std::vector results; - auto s = json.DebugMemory(args_[2], path, &results); + engine::Context ctx(svr->storage); + auto s = json.DebugMemory(ctx, args_[2], path, &results); if (s.IsNotFound()) { if (args_.size() == 3) { @@ -686,7 +706,8 @@ class CommandJsonResp : public Commander { return {Status::RedisExecErr, "The number of arguments is more than expected"}; } std::vector results; - auto s = json.Resp(args_[1], path, &results, conn->GetProtocolVersion()); + engine::Context ctx(svr->storage); + auto s = json.Resp(ctx, args_[1], path, &results, conn->GetProtocolVersion()); if (s.IsNotFound()) { *output = conn->NilString(); return Status::OK(); diff --git a/src/commands/cmd_key.cc b/src/commands/cmd_key.cc index b3095f42cd8..fecf4d55475 100644 --- a/src/commands/cmd_key.cc +++ b/src/commands/cmd_key.cc @@ -35,7 +35,8 @@ class CommandType : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); RedisType type = kRedisNone; - auto s = redis.Type(args_[1], &type); + engine::Context ctx(srv->storage); + auto s = redis.Type(ctx, args_[1], &type); if (s.ok()) { if (type >= RedisTypeNames.size()) return {Status::RedisExecErr, "Invalid type"}; *output = redis::SimpleString(RedisTypeNames[type]); @@ -56,7 +57,8 @@ class CommandMove : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int count = 0; redis::Database redis(srv->storage, conn->GetNamespace()); - rocksdb::Status s = redis.Exists({args_[1]}, &count); + engine::Context ctx(srv->storage); + rocksdb::Status s = redis.Exists(ctx, {args_[1]}, &count); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = count ? redis::Integer(1) : redis::Integer(0); @@ -86,7 +88,8 @@ class CommandMoveX : public Commander { Database::CopyResult res = Database::CopyResult::DONE; std::string ns_key = redis.AppendNamespacePrefix(key); std::string new_ns_key = ComposeNamespaceKey(ns, key, srv->storage->IsSlotIdEncoded()); - auto s = redis.Copy(ns_key, new_ns_key, true, true, &res); + engine::Context ctx(srv->storage); + auto s = redis.Copy(ctx, ns_key, new_ns_key, true, true, &res); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; if (res == Database::CopyResult::DONE) { @@ -104,7 +107,8 @@ class CommandObject : public Commander { if (util::ToLower(args_[1]) == "dump") { redis::Database redis(srv->storage, conn->GetNamespace()); std::vector infos; - auto s = redis.Dump(args_[2], &infos); + engine::Context ctx(srv->storage); + auto s = redis.Dump(ctx, args_[2], &infos); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -125,7 +129,8 @@ class CommandTTL : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); int64_t ttl = 0; - auto s = redis.TTL(args_[1], &ttl); + engine::Context ctx(srv->storage); + auto s = redis.TTL(ctx, args_[1], &ttl); if (s.ok()) { *output = redis::Integer(ttl > 0 ? ttl / 1000 : ttl); return Status::OK(); @@ -140,7 +145,8 @@ class CommandPTTL : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); int64_t ttl = 0; - auto s = redis.TTL(args_[1], &ttl); + engine::Context ctx(srv->storage); + auto s = redis.TTL(ctx, args_[1], &ttl); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(ttl); @@ -159,7 +165,8 @@ class CommandExists : public Commander { int cnt = 0; redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.Exists(keys, &cnt); + engine::Context ctx(srv->storage); + auto s = redis.Exists(ctx, keys, &cnt); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(cnt); @@ -176,7 +183,8 @@ class CommandExpire : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.Expire(args_[1], ttl_ * 1000 + util::GetTimeStampMS()); + engine::Context ctx(srv->storage); + auto s = redis.Expire(ctx, args_[1], ttl_ * 1000 + util::GetTimeStampMS()); if (s.ok()) { *output = redis::Integer(1); } else { @@ -198,7 +206,8 @@ class CommandPExpire : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.Expire(args_[1], seconds_); + engine::Context ctx(srv->storage); + auto s = redis.Expire(ctx, args_[1], seconds_); if (s.ok()) { *output = redis::Integer(1); } else { @@ -226,7 +235,8 @@ class CommandExpireAt : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.Expire(args_[1], timestamp_ * 1000); + engine::Context ctx(srv->storage); + auto s = redis.Expire(ctx, args_[1], timestamp_ * 1000); if (s.ok()) { *output = redis::Integer(1); } else { @@ -254,7 +264,8 @@ class CommandPExpireAt : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.Expire(args_[1], timestamp_); + engine::Context ctx(srv->storage); + auto s = redis.Expire(ctx, args_[1], timestamp_); if (s.ok()) { *output = redis::Integer(1); } else { @@ -272,7 +283,8 @@ class CommandExpireTime : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); uint64_t timestamp = 0; - auto s = redis.GetExpireTime(args_[1], ×tamp); + engine::Context ctx(srv->storage); + auto s = redis.GetExpireTime(ctx, args_[1], ×tamp); if (s.ok()) { *output = timestamp > 0 ? redis::Integer(timestamp / 1000) : redis::Integer(-1); } else if (s.IsNotFound()) { @@ -289,7 +301,8 @@ class CommandPExpireTime : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); uint64_t timestamp = 0; - auto s = redis.GetExpireTime(args_[1], ×tamp); + engine::Context ctx(srv->storage); + auto s = redis.GetExpireTime(ctx, args_[1], ×tamp); if (s.ok()) { *output = timestamp > 0 ? redis::Integer(timestamp) : redis::Integer(-1); } else if (s.IsNotFound()) { @@ -306,7 +319,8 @@ class CommandPersist : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t ttl = 0; redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.TTL(args_[1], &ttl); + engine::Context ctx(srv->storage); + auto s = redis.TTL(ctx, args_[1], &ttl); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; if (ttl == -1 || ttl == -2) { @@ -314,7 +328,7 @@ class CommandPersist : public Commander { return Status::OK(); } - s = redis.Expire(args_[1], 0); + s = redis.Expire(ctx, args_[1], 0); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(1); @@ -333,7 +347,8 @@ class CommandDel : public Commander { uint64_t cnt = 0; redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.MDel(keys, &cnt); + engine::Context ctx(srv->storage); + auto s = redis.MDel(ctx, keys, &cnt); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(cnt); @@ -348,7 +363,8 @@ class CommandRename : public Commander { Database::CopyResult res = Database::CopyResult::DONE; std::string ns_key = redis.AppendNamespacePrefix(args_[1]); std::string new_ns_key = redis.AppendNamespacePrefix(args_[2]); - auto s = redis.Copy(ns_key, new_ns_key, false, true, &res); + engine::Context ctx(srv->storage); + auto s = redis.Copy(ctx, ns_key, new_ns_key, false, true, &res); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; if (res == Database::CopyResult::KEY_NOT_EXIST) return {Status::RedisExecErr, "no such key"}; *output = redis::SimpleString("OK"); @@ -363,7 +379,8 @@ class CommandRenameNX : public Commander { Database::CopyResult res = Database::CopyResult::DONE; std::string ns_key = redis.AppendNamespacePrefix(args_[1]); std::string new_ns_key = redis.AppendNamespacePrefix(args_[2]); - auto s = redis.Copy(ns_key, new_ns_key, true, true, &res); + engine::Context ctx(srv->storage); + auto s = redis.Copy(ctx, ns_key, new_ns_key, true, true, &res); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; switch (res) { case Database::CopyResult::KEY_NOT_EXIST: @@ -405,7 +422,8 @@ class CommandCopy : public Commander { Database::CopyResult res = Database::CopyResult::DONE; std::string ns_key = redis.AppendNamespacePrefix(args_[1]); std::string new_ns_key = redis.AppendNamespacePrefix(args_[2]); - auto s = redis.Copy(ns_key, new_ns_key, !replace_, false, &res); + engine::Context ctx(srv->storage); + auto s = redis.Copy(ctx, ns_key, new_ns_key, !replace_, false, &res); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; switch (res) { case Database::CopyResult::KEY_NOT_EXIST: @@ -474,8 +492,9 @@ class CommandSort : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Database redis(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); RedisType type = kRedisNone; - if (auto s = redis.Type(args_[1], &type); !s.ok()) { + if (auto s = redis.Type(ctx, args_[1], &type); !s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -501,7 +520,7 @@ class CommandSort : public Commander { std::vector> sorted_elems; Database::SortResult res = Database::SortResult::DONE; - if (auto s = redis.Sort(type, args_[1], sort_argument_, &sorted_elems, &res); !s.ok()) { + if (auto s = redis.Sort(ctx, type, args_[1], sort_argument_, &sorted_elems, &res); !s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_list.cc b/src/commands/cmd_list.cc index 44f3b6d3d23..1cc11ec9f39 100644 --- a/src/commands/cmd_list.cc +++ b/src/commands/cmd_list.cc @@ -42,10 +42,11 @@ class CommandPush : public Commander { uint64_t ret = 0; rocksdb::Status s; redis::List list_db(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); if (create_if_missing_) { - s = list_db.Push(args_[1], elems, left_, &ret); + s = list_db.Push(ctx, args_[1], elems, left_, &ret); } else { - s = list_db.PushX(args_[1], elems, left_, &ret); + s = list_db.PushX(ctx, args_[1], elems, left_, &ret); } if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; @@ -111,9 +112,10 @@ class CommandPop : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); if (with_count_) { std::vector elems; - auto s = list_db.PopMulti(args_[1], left_, count_, &elems); + auto s = list_db.PopMulti(ctx, args_[1], left_, count_, &elems); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -125,7 +127,7 @@ class CommandPop : public Commander { } } else { std::string elem; - auto s = list_db.Pop(args_[1], left_, &elem); + auto s = list_db.Pop(ctx, args_[1], left_, &elem); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -197,8 +199,9 @@ class CommandLMPop : public Commander { std::vector elems; std::string chosen_key; + engine::Context ctx(srv->storage); for (auto &key : keys_) { - auto s = list_db.PopMulti(key, left_, count_, &elems); + auto s = list_db.PopMulti(ctx, key, left_, count_, &elems); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -262,8 +265,8 @@ class CommandBPop : public BlockingCommander { Status Execute(Server *srv, Connection *conn, std::string *output) override { srv_ = srv; InitConnection(conn); - - auto s = TryPopFromList(); + engine::Context ctx(srv->storage); + auto s = TryPopFromList(ctx); if (s.ok() || !s.IsNotFound()) { return Status::OK(); // error has already output in TryPopFromList } @@ -283,14 +286,14 @@ class CommandBPop : public BlockingCommander { } } - rocksdb::Status TryPopFromList() { + rocksdb::Status TryPopFromList(engine::Context &ctx) { redis::List list_db(srv_->storage, conn_->GetNamespace()); std::string elem; const std::string *last_key_ptr = nullptr; rocksdb::Status s; for (const auto &key : keys_) { last_key_ptr = &key; - s = list_db.Pop(key, left_, &elem); + s = list_db.Pop(ctx, key, left_, &elem); if (s.ok() || !s.IsNotFound()) { break; } @@ -311,7 +314,8 @@ class CommandBPop : public BlockingCommander { } bool OnBlockingWrite() override { - auto s = TryPopFromList(); + engine::Context ctx(srv_->storage); + auto s = TryPopFromList(ctx); return !s.IsNotFound(); } @@ -382,8 +386,8 @@ class CommandBLMPop : public BlockingCommander { Status Execute(Server *srv, Connection *conn, std::string *output) override { srv_ = srv; InitConnection(conn); - - auto s = ExecuteUnblocked(); + engine::Context ctx(srv->storage); + auto s = ExecuteUnblocked(ctx); if (s.ok() || !s.IsNotFound()) { return Status::OK(); // error has already been output } @@ -391,13 +395,13 @@ class CommandBLMPop : public BlockingCommander { return StartBlocking(timeout_, output); } - rocksdb::Status ExecuteUnblocked() { + rocksdb::Status ExecuteUnblocked(engine::Context &ctx) { redis::List list_db(srv_->storage, conn_->GetNamespace()); std::vector elems; std::string chosen_key; rocksdb::Status s; for (const auto &key : keys_) { - s = list_db.PopMulti(key, left_, count_, &elems); + s = list_db.PopMulti(ctx, key, left_, count_, &elems); if (s.ok() && !elems.empty()) { chosen_key = key; break; @@ -433,7 +437,8 @@ class CommandBLMPop : public BlockingCommander { } bool OnBlockingWrite() override { - auto s = ExecuteUnblocked(); + engine::Context ctx(srv_->storage); + auto s = ExecuteUnblocked(ctx); return !s.IsNotFound(); } @@ -472,7 +477,8 @@ class CommandLRem : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::List list_db(srv->storage, conn->GetNamespace()); - auto s = list_db.Rem(args_[1], count_, args_[3], &ret); + engine::Context ctx(srv->storage); + auto s = list_db.Rem(ctx, args_[1], count_, args_[3], &ret); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -501,7 +507,8 @@ class CommandLInsert : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int ret = 0; redis::List list_db(srv->storage, conn->GetNamespace()); - auto s = list_db.Insert(args_[1], args_[3], args_[4], before_, &ret); + engine::Context ctx(srv->storage); + auto s = list_db.Insert(ctx, args_[1], args_[3], args_[4], before_, &ret); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -531,7 +538,8 @@ class CommandLRange : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); std::vector elems; - auto s = list_db.Range(args_[1], start_, stop_, &elems); + engine::Context ctx(srv->storage); + auto s = list_db.Range(ctx, args_[1], start_, stop_, &elems); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -549,7 +557,9 @@ class CommandLLen : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); uint64_t count = 0; - auto s = list_db.Size(args_[1], &count); + engine::Context ctx(srv->storage); + + auto s = list_db.Size(ctx, args_[1], &count); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -574,7 +584,8 @@ class CommandLIndex : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); std::string elem; - auto s = list_db.Index(args_[1], index_, &elem); + engine::Context ctx(srv->storage); + auto s = list_db.Index(ctx, args_[1], index_, &elem); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -605,7 +616,8 @@ class CommandLSet : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); - auto s = list_db.Set(args_[1], index_, args_[3]); + engine::Context ctx(srv->storage); + auto s = list_db.Set(ctx, args_[1], index_, args_[3]); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -639,7 +651,8 @@ class CommandLTrim : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); - auto s = list_db.Trim(args_[1], start_, stop_); + engine::Context ctx(srv->storage); + auto s = list_db.Trim(ctx, args_[1], start_, stop_); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -658,7 +671,8 @@ class CommandRPopLPUSH : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); std::string elem; - auto s = list_db.LMove(args_[1], args_[2], /*src_left=*/false, /*dst_left=*/true, &elem); + engine::Context ctx(srv->storage); + auto s = list_db.LMove(ctx, args_[1], args_[2], /*src_left=*/false, /*dst_left=*/true, &elem); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -689,7 +703,8 @@ class CommandLMove : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); std::string elem; - auto s = list_db.LMove(args_[1], args_[2], src_left_, dst_left_, &elem); + engine::Context ctx(srv->storage); + auto s = list_db.LMove(ctx, args_[1], args_[2], src_left_, dst_left_, &elem); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -736,7 +751,8 @@ class CommandBLMove : public BlockingCommander { redis::List list_db(srv->storage, conn->GetNamespace()); std::string elem; - auto s = list_db.LMove(args_[1], args_[2], src_left_, dst_left_, &elem); + engine::Context ctx(srv->storage); + auto s = list_db.LMove(ctx, args_[1], args_[2], src_left_, dst_left_, &elem); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -755,7 +771,8 @@ class CommandBLMove : public BlockingCommander { bool OnBlockingWrite() override { redis::List list_db(srv_->storage, conn_->GetNamespace()); std::string elem; - auto s = list_db.LMove(args_[1], args_[2], src_left_, dst_left_, &elem); + engine::Context ctx(srv_->storage); + auto s = list_db.LMove(ctx, args_[1], args_[2], src_left_, dst_left_, &elem); if (!s.ok() && !s.IsNotFound()) { conn_->Reply(redis::Error({Status::NotOK, s.ToString()})); return true; @@ -818,7 +835,8 @@ class CommandLPos : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::List list_db(srv->storage, conn->GetNamespace()); std::vector indexes; - auto s = list_db.Pos(args_[1], args_[2], spec_, &indexes); + engine::Context ctx(srv->storage); + auto s = list_db.Pos(ctx, args_[1], args_[2], spec_, &indexes); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_pubsub.cc b/src/commands/cmd_pubsub.cc index 143cfcdeb68..0d67c49de85 100644 --- a/src/commands/cmd_pubsub.cc +++ b/src/commands/cmd_pubsub.cc @@ -33,8 +33,8 @@ class CommandPublish : public Commander { // Replication relies on WAL seq; increasing the seq on a replica will break the replication process, // hence the compromise solution redis::PubSub pubsub_db(srv->storage); - - auto s = pubsub_db.Publish(args_[1], args_[2]); + engine::Context ctx(srv->storage); + auto s = pubsub_db.Publish(ctx, args_[1], args_[2]); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -52,12 +52,12 @@ class CommandMPublish : public Commander { public: Status Execute(Server *srv, Connection *conn, std::string *output) override { int total_receivers = 0; - + engine::Context ctx(srv->storage); for (size_t i = 2; i < args_.size(); i++) { if (!srv->IsSlave()) { redis::PubSub pubsub_db(srv->storage); - auto s = pubsub_db.Publish(args_[1], args_[i]); + auto s = pubsub_db.Publish(ctx, args_[1], args_[i]); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_search.cc b/src/commands/cmd_search.cc index 1710e673247..1cd42b4bff0 100644 --- a/src/commands/cmd_search.cc +++ b/src/commands/cmd_search.cc @@ -181,8 +181,8 @@ class CommandFTCreate : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { index_info_->ns = conn->GetNamespace(); - - GET_OR_RET(srv->index_mgr.Create(std::move(index_info_))); + engine::Context ctx(srv->storage); + GET_OR_RET(srv->index_mgr.Create(ctx, std::move(index_info_))); output->append(redis::SimpleString("OK")); return Status::OK(); diff --git a/src/commands/cmd_server.cc b/src/commands/cmd_server.cc index c9a11cf7a15..1603f0f1892 100644 --- a/src/commands/cmd_server.cc +++ b/src/commands/cmd_server.cc @@ -18,9 +18,6 @@ * */ -#include -#include - #include "command_parser.h" #include "commander.h" #include "commands/scan_base.h" @@ -120,16 +117,16 @@ class CommandKeys : public Commander { std::string prefix = args_[1]; std::vector keys; redis::Database redis(srv->storage, conn->GetNamespace()); - + engine::Context ctx(srv->storage); rocksdb::Status s; if (prefix == "*") { - s = redis.Keys(std::string(), &keys); + s = redis.Keys(ctx, std::string(), &keys); } else { if (prefix[prefix.size() - 1] != '*') { return {Status::RedisExecErr, "only keys prefix match was supported"}; } - s = redis.Keys(prefix.substr(0, prefix.size() - 1), &keys); + s = redis.Keys(ctx, prefix.substr(0, prefix.size() - 1), &keys); } if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; @@ -149,7 +146,8 @@ class CommandFlushDB : public Commander { } } redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.FlushDB(); + engine::Context ctx(srv->storage); + auto s = redis.FlushDB(ctx); LOG(WARNING) << "DB keys in namespace: " << conn->GetNamespace() << " was flushed, addr: " << conn->GetAddr(); if (s.ok()) { *output = redis::SimpleString("OK"); @@ -175,7 +173,8 @@ class CommandFlushAll : public Commander { } redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.FlushAll(); + engine::Context ctx(srv->storage); + auto s = redis.FlushAll(ctx); if (s.ok()) { LOG(WARNING) << "All DB keys was flushed, addr: " << conn->GetAddr(); *output = redis::SimpleString("OK"); @@ -273,11 +272,12 @@ class CommandDisk : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { RedisType type = kRedisNone; redis::Disk disk_db(srv->storage, conn->GetNamespace()); - auto s = disk_db.Type(args_[2], &type); + engine::Context ctx(srv->storage); + auto s = disk_db.Type(ctx, args_[2], &type); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; uint64_t result = 0; - s = disk_db.GetKeySize(args_[2], type, &result); + s = disk_db.GetKeySize(ctx, args_[2], type, &result); if (!s.ok()) { // Redis returns the Nil string when the key does not exist if (s.IsNotFound()) { @@ -841,7 +841,8 @@ class CommandScan : public CommandScanBase { std::vector keys; std::string end_key; - auto s = redis_db.Scan(key_name, limit_, prefix_, &keys, &end_key, type_); + engine::Context ctx(srv->storage); + auto s = redis_db.Scan(ctx, key_name, limit_, prefix_, &keys, &end_key, type_); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -856,7 +857,8 @@ class CommandRandomKey : public Commander { std::string key; auto cursor = srv->GetLastRandomKeyCursor(); redis::Database redis(srv->storage, conn->GetNamespace()); - auto s = redis.RandomKey(cursor, &key); + engine::Context ctx(srv->storage); + auto s = redis.RandomKey(ctx, cursor, &key); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -871,7 +873,6 @@ class CommandCompact : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::string begin_key, end_key; auto ns = conn->GetNamespace(); - if (ns != kDefaultNamespace) { begin_key = ComposeNamespaceKey(ns, "", false); end_key = util::StringNext(begin_key); @@ -1070,9 +1071,10 @@ class CommandRestore : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { rocksdb::Status db_status; redis::Database redis(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); if (!replace_) { int count = 0; - db_status = redis.Exists({args_[1]}, &count); + db_status = redis.Exists(ctx, {args_[1]}, &count); if (!db_status.ok()) { return {Status::RedisExecErr, db_status.ToString()}; } @@ -1080,7 +1082,7 @@ class CommandRestore : public Commander { return {Status::RedisExecErr, "target key name already exists."}; } } else { - db_status = redis.Del(args_[1]); + db_status = redis.Del(ctx, args_[1]); if (!db_status.ok() && !db_status.IsNotFound()) { return {Status::RedisExecErr, db_status.ToString()}; } @@ -1097,7 +1099,7 @@ class CommandRestore : public Commander { auto stream_ptr = std::make_unique(args_[3]); RDB rdb(srv->storage, conn->GetNamespace(), std::move(stream_ptr)); - auto s = rdb.Restore(args_[1], args_[3], ttl_ms_); + auto s = rdb.Restore(ctx, args_[1], args_[3], ttl_ms_); if (!s.IsOK()) return s; *output = redis::SimpleString("OK"); return Status::OK(); @@ -1140,12 +1142,13 @@ class CommandRdb : public Commander { } redis::Database redis(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); auto stream_ptr = std::make_unique(path_); GET_OR_RET(stream_ptr->Open()); RDB rdb(srv->storage, conn->GetNamespace(), std::move(stream_ptr)); - GET_OR_RET(rdb.LoadRdb(db_index_, overwrite_exist_key_)); + GET_OR_RET(rdb.LoadRdb(ctx, db_index_, overwrite_exist_key_)); *output = redis::SimpleString("OK"); return Status::OK(); @@ -1237,7 +1240,8 @@ class CommandDump : public Commander { std::string &key = args_[1]; redis::Database redis(srv->storage, conn->GetNamespace()); int count = 0; - db_status = redis.Exists({key}, &count); + engine::Context ctx(srv->storage); + db_status = redis.Exists(ctx, {key}, &count); if (!db_status.ok()) { if (db_status.IsNotFound()) { *output = conn->NilString(); @@ -1251,7 +1255,7 @@ class CommandDump : public Commander { } RedisType type = kRedisNone; - db_status = redis.Type(key, &type); + db_status = redis.Type(ctx, key, &type); if (!db_status.ok()) return {Status::RedisExecErr, db_status.ToString()}; std::string result; diff --git a/src/commands/cmd_set.cc b/src/commands/cmd_set.cc index c824a077752..cc66c968fff 100644 --- a/src/commands/cmd_set.cc +++ b/src/commands/cmd_set.cc @@ -38,7 +38,8 @@ class CommandSAdd : public Commander { uint64_t ret = 0; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.Add(args_[1], members, &ret); + engine::Context ctx(srv->storage); + auto s = set_db.Add(ctx, args_[1], members, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -58,7 +59,8 @@ class CommandSRem : public Commander { uint64_t ret = 0; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.Remove(args_[1], members, &ret); + engine::Context ctx(srv->storage); + auto s = set_db.Remove(ctx, args_[1], members, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -73,7 +75,8 @@ class CommandSCard : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Set set_db(srv->storage, conn->GetNamespace()); uint64_t ret = 0; - auto s = set_db.Card(args_[1], &ret); + engine::Context ctx(srv->storage); + auto s = set_db.Card(ctx, args_[1], &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -88,7 +91,8 @@ class CommandSMembers : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Set set_db(srv->storage, conn->GetNamespace()); std::vector members; - auto s = set_db.Members(args_[1], &members); + engine::Context ctx(srv->storage); + auto s = set_db.Members(ctx, args_[1], &members); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -103,7 +107,8 @@ class CommandSIsMember : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Set set_db(srv->storage, conn->GetNamespace()); bool ret = false; - auto s = set_db.IsMember(args_[1], args_[2], &ret); + engine::Context ctx(srv->storage); + auto s = set_db.IsMember(ctx, args_[1], args_[2], &ret); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -123,7 +128,8 @@ class CommandSMIsMember : public Commander { } std::vector exists; - auto s = set_db.MIsMember(args_[1], members, &exists); + engine::Context ctx(srv->storage); + auto s = set_db.MIsMember(ctx, args_[1], members, &exists); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -165,7 +171,8 @@ class CommandSPop : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Set set_db(srv->storage, conn->GetNamespace()); std::vector members; - auto s = set_db.Take(args_[1], &members, count_, true); + engine::Context ctx(srv->storage); + auto s = set_db.Take(ctx, args_[1], &members, count_, true); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -207,7 +214,8 @@ class CommandSRandMember : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Set set_db(srv->storage, conn->GetNamespace()); std::vector members; - auto s = set_db.Take(args_[1], &members, count_, false); + engine::Context ctx(srv->storage); + auto s = set_db.Take(ctx, args_[1], &members, count_, false); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -224,7 +232,8 @@ class CommandSMove : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Set set_db(srv->storage, conn->GetNamespace()); bool ret = false; - auto s = set_db.Move(args_[1], args_[2], args_[3], &ret); + engine::Context ctx(srv->storage); + auto s = set_db.Move(ctx, args_[1], args_[2], args_[3], &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -244,7 +253,8 @@ class CommandSDiff : public Commander { std::vector members; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.Diff(keys, &members); + engine::Context ctx(srv->storage); + auto s = set_db.Diff(ctx, keys, &members); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -264,7 +274,8 @@ class CommandSUnion : public Commander { std::vector members; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.Union(keys, &members); + engine::Context ctx(srv->storage); + auto s = set_db.Union(ctx, keys, &members); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -284,7 +295,8 @@ class CommandSInter : public Commander { std::vector members; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.Inter(keys, &members); + engine::Context ctx(srv->storage); + auto s = set_db.Inter(ctx, keys, &members); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -341,7 +353,8 @@ class CommandSInterCard : public Commander { redis::Set set_db(srv->storage, conn->GetNamespace()); uint64_t ret = 0; - auto s = set_db.InterCard(keys, limit_, &ret); + engine::Context ctx(srv->storage); + auto s = set_db.InterCard(ctx, keys, limit_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -370,7 +383,8 @@ class CommandSDiffStore : public Commander { uint64_t ret = 0; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.DiffStore(args_[1], keys, &ret); + engine::Context ctx(srv->storage); + auto s = set_db.DiffStore(ctx, args_[1], keys, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -390,7 +404,8 @@ class CommandSUnionStore : public Commander { uint64_t ret = 0; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.UnionStore(args_[1], keys, &ret); + engine::Context ctx(srv->storage); + auto s = set_db.UnionStore(ctx, args_[1], keys, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -410,7 +425,8 @@ class CommandSInterStore : public Commander { uint64_t ret = 0; redis::Set set_db(srv->storage, conn->GetNamespace()); - auto s = set_db.InterStore(args_[1], keys, &ret); + engine::Context ctx(srv->storage); + auto s = set_db.InterStore(ctx, args_[1], keys, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -427,7 +443,8 @@ class CommandSScan : public CommandSubkeyScanBase { redis::Set set_db(srv->storage, conn->GetNamespace()); std::vector members; auto key_name = srv->GetKeyNameFromCursor(cursor_, CursorType::kTypeSet); - auto s = set_db.Scan(key_, key_name, limit_, prefix_, &members); + engine::Context ctx(srv->storage); + auto s = set_db.Scan(ctx, key_, key_name, limit_, prefix_, &members); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_sortedint.cc b/src/commands/cmd_sortedint.cc index 8259808a7f3..ae8cea9377d 100644 --- a/src/commands/cmd_sortedint.cc +++ b/src/commands/cmd_sortedint.cc @@ -42,7 +42,8 @@ class CommandSortedintAdd : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Sortedint sortedint_db(srv->storage, conn->GetNamespace()); uint64_t ret = 0; - auto s = sortedint_db.Add(args_[1], ids_, &ret); + engine::Context ctx(srv->storage); + auto s = sortedint_db.Add(ctx, args_[1], ids_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -72,7 +73,8 @@ class CommandSortedintRem : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Sortedint sortedint_db(srv->storage, conn->GetNamespace()); uint64_t ret = 0; - auto s = sortedint_db.Remove(args_[1], ids_, &ret); + engine::Context ctx(srv->storage); + auto s = sortedint_db.Remove(ctx, args_[1], ids_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -90,7 +92,8 @@ class CommandSortedintCard : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Sortedint sortedint_db(srv->storage, conn->GetNamespace()); uint64_t ret = 0; - auto s = sortedint_db.Card(args_[1], &ret); + engine::Context ctx(srv->storage); + auto s = sortedint_db.Card(ctx, args_[1], &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -115,7 +118,8 @@ class CommandSortedintExists : public Commander { } std::vector exists; - auto s = sortedint_db.MExist(args_[1], ids, &exists); + engine::Context ctx(srv->storage); + auto s = sortedint_db.MExist(ctx, args_[1], ids, &exists); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -165,7 +169,8 @@ class CommandSortedintRange : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Sortedint sortedint_db(srv->storage, conn->GetNamespace()); std::vector ids; - auto s = sortedint_db.Range(args_[1], cursor_id_, offset_, limit_, reversed_, &ids); + engine::Context ctx(srv->storage); + auto s = sortedint_db.Range(ctx, args_[1], cursor_id_, offset_, limit_, reversed_, &ids); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -227,7 +232,8 @@ class CommandSortedintRangeByValue : public Commander { std::vector ids; int size = 0; redis::Sortedint sortedint_db(srv->storage, conn->GetNamespace()); - auto s = sortedint_db.RangeByValue(args_[1], spec_, &ids, &size); + engine::Context ctx(srv->storage); + auto s = sortedint_db.RangeByValue(ctx, args_[1], spec_, &ids, &size); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_stream.cc b/src/commands/cmd_stream.cc index 06ba424f379..35ec15cbecd 100644 --- a/src/commands/cmd_stream.cc +++ b/src/commands/cmd_stream.cc @@ -52,7 +52,8 @@ class CommandXAck : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); uint64_t acknowledged = 0; - auto s = stream_db.DeletePelEntries(stream_name_, group_name_, entry_ids_, &acknowledged); + engine::Context ctx(srv->storage); + auto s = stream_db.DeletePelEntries(ctx, stream_name_, group_name_, entry_ids_, &acknowledged); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -179,7 +180,8 @@ class CommandXAdd : public Commander { redis::Stream stream_db(srv->storage, conn->GetNamespace()); StreamEntryID entry_id; - auto s = stream_db.Add(stream_name_, options, name_value_pairs_, &entry_id); + engine::Context ctx(srv->storage); + auto s = stream_db.Add(ctx, stream_name_, options, name_value_pairs_, &entry_id); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -225,7 +227,8 @@ class CommandXDel : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); uint64_t deleted = 0; - auto s = stream_db.DeleteEntries(args_[1], ids_, &deleted); + engine::Context ctx(srv->storage); + auto s = stream_db.DeleteEntries(ctx, args_[1], ids_, &deleted); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -319,7 +322,8 @@ class CommandXClaim : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); StreamClaimResult result; - auto s = stream_db.ClaimPelEntries(stream_name_, group_name_, consumer_name_, min_idle_time_ms_, entry_ids_, + engine::Context ctx(srv->storage); + auto s = stream_db.ClaimPelEntries(ctx, stream_name_, group_name_, consumer_name_, min_idle_time_ms_, entry_ids_, stream_claim_options_, &result); if (!s.ok()) { if (s.IsNotFound()) { @@ -408,7 +412,8 @@ class CommandAutoClaim : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); StreamAutoClaimResult result; - auto s = stream_db.AutoClaim(key_name_, group_name_, consumer_name_, options_, &result); + engine::Context ctx(srv->storage); + auto s = stream_db.AutoClaim(ctx, key_name_, group_name_, consumer_name_, options_, &result); if (!s.ok()) { if (s.IsNotFound()) { return {Status::RedisNoGroup, "No such key '" + key_name_ + "' or consumer group '" + group_name_ + "'"}; @@ -532,8 +537,10 @@ class CommandXGroup : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); + if (subcommand_ == "create") { - auto s = stream_db.CreateGroup(stream_name_, xgroup_create_options_, group_name_); + auto s = stream_db.CreateGroup(ctx, stream_name_, xgroup_create_options_, group_name_); if (!s.ok()) { if (s.IsBusy()) { return {Status::RedisBusyGroup, "consumer group name '" + group_name_ + "' already exists"}; @@ -546,7 +553,7 @@ class CommandXGroup : public Commander { if (subcommand_ == "destroy") { uint64_t delete_cnt = 0; - auto s = stream_db.DestroyGroup(stream_name_, group_name_, &delete_cnt); + auto s = stream_db.DestroyGroup(ctx, stream_name_, group_name_, &delete_cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -560,7 +567,7 @@ class CommandXGroup : public Commander { if (subcommand_ == "createconsumer") { int created_number = 0; - auto s = stream_db.CreateConsumer(stream_name_, group_name_, consumer_name_, &created_number); + auto s = stream_db.CreateConsumer(ctx, stream_name_, group_name_, consumer_name_, &created_number); if (!s.ok()) { if (s.IsNotFound()) { return {Status::RedisNoGroup, "No such consumer group " + group_name_ + " for key name " + stream_name_}; @@ -573,7 +580,7 @@ class CommandXGroup : public Commander { if (subcommand_ == "delconsumer") { uint64_t deleted_pel = 0; - auto s = stream_db.DestroyConsumer(stream_name_, group_name_, consumer_name_, deleted_pel); + auto s = stream_db.DestroyConsumer(ctx, stream_name_, group_name_, consumer_name_, deleted_pel); if (!s.ok()) { if (s.IsNotFound()) { return {Status::RedisNoGroup, "No such consumer group " + group_name_ + " for key name " + stream_name_}; @@ -585,7 +592,7 @@ class CommandXGroup : public Commander { } if (subcommand_ == "setid") { - auto s = stream_db.GroupSetId(stream_name_, group_name_, xgroup_create_options_); + auto s = stream_db.GroupSetId(ctx, stream_name_, group_name_, xgroup_create_options_); if (!s.ok()) { if (s.IsNotFound()) { return {Status::RedisNoGroup, "No such consumer group " + group_name_ + " for key name " + stream_name_}; @@ -633,7 +640,8 @@ class CommandXLen : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); uint64_t len = 0; - auto s = stream_db.Len(args_[1], options_, &len); + engine::Context ctx(srv->storage); + auto s = stream_db.Len(ctx, args_[1], options_, &len); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -700,7 +708,8 @@ class CommandXInfo : public Commander { Status getStreamInfo(Server *srv, Connection *conn, std::string *output) { redis::Stream stream_db(srv->storage, conn->GetNamespace()); redis::StreamInfo info; - auto s = stream_db.GetStreamInfo(args_[2], full_, count_, &info); + engine::Context ctx(srv->storage); + auto s = stream_db.GetStreamInfo(ctx, args_[2], full_, count_, &info); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -757,7 +766,8 @@ class CommandXInfo : public Commander { Status getGroupInfo(Server *srv, Connection *conn, std::string *output) { redis::Stream stream_db(srv->storage, conn->GetNamespace()); std::vector> result_vector; - auto s = stream_db.GetGroupInfo(args_[2], result_vector); + engine::Context ctx(srv->storage); + auto s = stream_db.GetGroupInfo(ctx, args_[2], result_vector); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -797,7 +807,8 @@ class CommandXInfo : public Commander { Status getConsumerInfo(Server *srv, Connection *conn, std::string *output) { redis::Stream stream_db(srv->storage, conn->GetNamespace()); std::vector> result_vector; - auto s = stream_db.GetConsumerInfo(args_[2], args_[3], result_vector); + engine::Context ctx(srv->storage); + auto s = stream_db.GetConsumerInfo(ctx, args_[2], args_[3], result_vector); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; @@ -871,7 +882,8 @@ class CommandXPending : public Commander { options_.stream_name = stream_name_; options_.group_name = group_name_; std::vector ext_results; - auto s = stream_db.GetPendingEntries(options_, results, ext_results); + engine::Context ctx(srv->storage); + auto s = stream_db.GetPendingEntries(ctx, options_, results, ext_results); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -983,7 +995,8 @@ class CommandXRange : public Commander { options.exclude_end = exclude_end_; std::vector result; - auto s = stream_db.Range(stream_name_, options, &result); + engine::Context ctx(srv->storage); + auto s = stream_db.Range(ctx, stream_name_, options, &result); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1076,7 +1089,8 @@ class CommandXRevRange : public Commander { options.exclude_end = exclude_end_; std::vector result; - auto s = stream_db.Range(stream_name_, options, &result); + engine::Context ctx(srv->storage); + auto s = stream_db.Range(ctx, stream_name_, options, &result); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1190,6 +1204,7 @@ class CommandXRead : public Commander, redis::Stream stream_db(srv->storage, conn->GetNamespace()); std::vector results; + engine::Context ctx(srv->storage); for (size_t i = 0; i < streams_.size(); ++i) { if (latest_marks_[i]) { @@ -1206,7 +1221,7 @@ class CommandXRead : public Commander, options.exclude_end = false; std::vector result; - auto s = stream_db.Range(streams_[i], options, &result); + auto s = stream_db.Range(ctx, streams_[i], options, &result); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1222,7 +1237,7 @@ class CommandXRead : public Commander, return Status::OK(); // No blocking in multi-exec } - return BlockingRead(srv, conn, &stream_db); + return BlockingRead(ctx, srv, conn, &stream_db); } if (!block_ && results.empty()) { @@ -1250,7 +1265,7 @@ class CommandXRead : public Commander, return Status::OK(); } - Status BlockingRead(Server *srv, Connection *conn, redis::Stream *stream_db) { + Status BlockingRead(const engine::Context &ctx, Server *srv, Connection *conn, redis::Stream *stream_db) { if (!with_count_) { with_count_ = true; count_ = blocked_default_count_; @@ -1259,7 +1274,8 @@ class CommandXRead : public Commander, for (size_t i = 0; i < streams_.size(); ++i) { if (latest_marks_[i]) { StreamEntryID last_generated_id; - auto s = stream_db->GetLastGeneratedID(streams_[i], &last_generated_id); + engine::Context ctx(srv->storage); + auto s = stream_db->GetLastGeneratedID(ctx, streams_[i], &last_generated_id); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1305,7 +1321,7 @@ class CommandXRead : public Commander, redis::Stream stream_db(srv_->storage, conn_->GetNamespace()); std::vector results; - + engine::Context ctx(srv_->storage); for (size_t i = 0; i < streams_.size(); ++i) { redis::StreamRangeOptions options; options.reverse = false; @@ -1317,7 +1333,7 @@ class CommandXRead : public Commander, options.exclude_end = false; std::vector result; - auto s = stream_db.Range(streams_[i], options, &result); + auto s = stream_db.Range(ctx, streams_[i], options, &result); if (!s.ok() && !s.IsNotFound()) { conn_->Reply(redis::Error({Status::NotOK, s.ToString()})); return; @@ -1490,7 +1506,7 @@ class CommandXReadGroup : public Commander, Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); - + engine::Context ctx(srv->storage); std::vector results; for (size_t i = 0; i < streams_.size(); ++i) { @@ -1504,7 +1520,7 @@ class CommandXReadGroup : public Commander, options.exclude_end = false; std::vector result; - auto s = stream_db.RangeWithPending(streams_[i], options, &result, group_name_, consumer_name_, noack_, + auto s = stream_db.RangeWithPending(ctx, streams_[i], options, &result, group_name_, consumer_name_, noack_, latest_marks_[i]); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; @@ -1597,7 +1613,7 @@ class CommandXReadGroup : public Commander, redis::Stream stream_db(srv_->storage, conn_->GetNamespace()); std::vector results; - + engine::Context ctx(srv_->storage); for (size_t i = 0; i < streams_.size(); ++i) { redis::StreamRangeOptions options; options.reverse = false; @@ -1609,7 +1625,7 @@ class CommandXReadGroup : public Commander, options.exclude_end = false; std::vector result; - auto s = stream_db.RangeWithPending(streams_[i], options, &result, group_name_, consumer_name_, noack_, + auto s = stream_db.RangeWithPending(ctx, streams_[i], options, &result, group_name_, consumer_name_, noack_, latest_marks_[i]); if (!s.ok() && !s.IsNotFound()) { conn_->Reply(redis::Error({Status::NotOK, s.ToString()})); @@ -1766,7 +1782,8 @@ class CommandXTrim : public Commander { options.min_id = min_id_; uint64_t removed = 0; - auto s = stream_db.Trim(args_[1], options, &removed); + engine::Context ctx(srv->storage); + auto s = stream_db.Trim(ctx, args_[1], options, &removed); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1821,7 +1838,8 @@ class CommandXSetId : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::Stream stream_db(srv->storage, conn->GetNamespace()); - auto s = stream_db.SetId(stream_name_, last_id_, entries_added_, max_deleted_id_); + engine::Context ctx(srv->storage); + auto s = stream_db.SetId(ctx, stream_name_, last_id_, entries_added_, max_deleted_id_); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_string.cc b/src/commands/cmd_string.cc index be864f507c1..612fe5e1fc1 100644 --- a/src/commands/cmd_string.cc +++ b/src/commands/cmd_string.cc @@ -41,7 +41,8 @@ class CommandGet : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::string value; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.Get(args_[1], &value); + engine::Context ctx(srv->storage); + auto s = string_db.Get(ctx, args_[1], &value); // The IsInvalidArgument error means the key type maybe a bitmap // which we need to fall back to the bitmap's GetString according // to the `max-bitmap-to-string-mb` configuration. @@ -49,7 +50,7 @@ class CommandGet : public Commander { Config *config = srv->GetConfig(); uint32_t max_btos_size = static_cast(config->max_bitmap_to_string_mb) * MiB; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - s = bitmap_db.GetString(args_[1], max_btos_size, &value); + s = bitmap_db.GetString(ctx, args_[1], max_btos_size, &value); } if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; @@ -79,8 +80,9 @@ class CommandGetEx : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::string value; + engine::Context ctx(srv->storage); redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.GetEx(args_[1], &value, expire_); + auto s = string_db.GetEx(ctx, args_[1], &value, expire_); // The IsInvalidArgument error means the key type maybe a bitmap // which we need to fall back to the bitmap's GetString according @@ -89,9 +91,9 @@ class CommandGetEx : public Commander { Config *config = srv->GetConfig(); uint32_t max_btos_size = static_cast(config->max_bitmap_to_string_mb) * MiB; redis::Bitmap bitmap_db(srv->storage, conn->GetNamespace()); - s = bitmap_db.GetString(args_[1], max_btos_size, &value); + s = bitmap_db.GetString(ctx, args_[1], max_btos_size, &value); if (s.ok() && expire_) { - s = bitmap_db.Expire(args_[1], expire_.value()); + s = bitmap_db.Expire(ctx, args_[1], expire_.value()); } } if (!s.ok() && !s.IsNotFound()) { @@ -111,7 +113,8 @@ class CommandStrlen : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::string value; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.Get(args_[1], &value); + engine::Context ctx(srv->storage); + auto s = string_db.Get(ctx, args_[1], &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -130,7 +133,8 @@ class CommandGetSet : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::String string_db(srv->storage, conn->GetNamespace()); std::optional old_value; - auto s = string_db.GetSet(args_[1], args_[2], old_value); + engine::Context ctx(srv->storage); + auto s = string_db.GetSet(ctx, args_[1], args_[2], old_value); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -149,7 +153,8 @@ class CommandGetDel : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::String string_db(srv->storage, conn->GetNamespace()); std::string value; - auto s = string_db.GetDel(args_[1], &value); + engine::Context ctx(srv->storage); + auto s = string_db.GetDel(ctx, args_[1], &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -180,7 +185,8 @@ class CommandGetRange : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { std::string value; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.Get(args_[1], &value); + engine::Context ctx(srv->storage); + auto s = string_db.Get(ctx, args_[1], &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -227,7 +233,8 @@ class CommandSetRange : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.SetRange(args_[1], offset_, args_[3], &ret); + engine::Context ctx(srv->storage); + auto s = string_db.SetRange(ctx, args_[1], offset_, args_[3], &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -250,7 +257,8 @@ class CommandMGet : public Commander { } std::vector values; // always return OK - auto statuses = string_db.MGet(keys, &values); + engine::Context ctx(srv->storage); + auto statuses = string_db.MGet(ctx, keys, &values); *output = conn->MultiBulkString(values, statuses); return Status::OK(); } @@ -261,7 +269,8 @@ class CommandAppend : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.Append(args_[1], args_[2], &ret); + engine::Context ctx(srv->storage); + auto s = string_db.Append(ctx, args_[1], args_[2], &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -299,7 +308,8 @@ class CommandSet : public Commander { std::optional ret; redis::String string_db(srv->storage, conn->GetNamespace()); - rocksdb::Status s = string_db.Set(args_[1], args_[2], {expire_, set_flag_, get_, keep_ttl_}, ret); + engine::Context ctx(srv->storage); + rocksdb::Status s = string_db.Set(ctx, args_[1], args_[2], {expire_, set_flag_, get_, keep_ttl_}, ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; @@ -345,7 +355,8 @@ class CommandSetEX : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.SetEX(args_[1], args_[3], expire_); + engine::Context ctx(srv->storage); + auto s = string_db.SetEX(ctx, args_[1], args_[3], expire_); *output = redis::SimpleString("OK"); return Status::OK(); } @@ -371,7 +382,8 @@ class CommandPSetEX : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.SetEX(args_[1], args_[3], expire_); + engine::Context ctx(srv->storage); + auto s = string_db.SetEX(ctx, args_[1], args_[3], expire_); *output = redis::SimpleString("OK"); return Status::OK(); } @@ -396,8 +408,8 @@ class CommandMSet : public Commander { for (size_t i = 1; i < args_.size(); i += 2) { kvs.emplace_back(StringPair{args_[i], args_[i + 1]}); } - - auto s = string_db.MSet(kvs, 0); + engine::Context ctx(srv->storage); + auto s = string_db.MSet(ctx, kvs, 0); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -412,7 +424,8 @@ class CommandSetNX : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { bool ret = false; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.SetNX(args_[1], args_[2], 0, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.SetNX(ctx, args_[1], args_[2], 0, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -440,7 +453,8 @@ class CommandMSetNX : public Commander { kvs.emplace_back(StringPair{args_[i], args_[i + 1]}); } - auto s = string_db.MSetNX(kvs, 0, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.MSetNX(ctx, kvs, 0, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -455,7 +469,8 @@ class CommandIncr : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.IncrBy(args_[1], 1, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.IncrBy(ctx, args_[1], 1, &ret); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(ret); @@ -468,7 +483,8 @@ class CommandDecr : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.IncrBy(args_[1], -1, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.IncrBy(ctx, args_[1], -1, &ret); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(ret); @@ -491,7 +507,8 @@ class CommandIncrBy : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.IncrBy(args_[1], increment_, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.IncrBy(ctx, args_[1], increment_, &ret); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(ret); @@ -517,7 +534,8 @@ class CommandIncrByFloat : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { double ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.IncrByFloat(args_[1], increment_, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.IncrByFloat(ctx, args_[1], increment_, &ret); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::BulkString(util::Float2String(ret)); @@ -549,7 +567,8 @@ class CommandDecrBy : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { int64_t ret = 0; redis::String string_db(srv->storage, conn->GetNamespace()); - auto s = string_db.IncrBy(args_[1], -1 * increment_, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.IncrBy(ctx, args_[1], -1 * increment_, &ret); if (!s.ok()) return {Status::RedisExecErr, s.ToString()}; *output = redis::Integer(ret); @@ -578,7 +597,8 @@ class CommandCAS : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::String string_db(srv->storage, conn->GetNamespace()); int ret = 0; - auto s = string_db.CAS(args_[1], args_[2], args_[3], expire_, &ret); + engine::Context ctx(srv->storage); + auto s = string_db.CAS(ctx, args_[1], args_[2], args_[3], expire_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -596,7 +616,8 @@ class CommandCAD : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::String string_db(srv->storage, conn->GetNamespace()); int ret = 0; - auto s = string_db.CAD(args_[1], args_[2], &ret); + engine::Context ctx(srv->storage); + auto s = string_db.CAD(ctx, args_[1], args_[2], &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -649,7 +670,8 @@ class CommandLCS : public Commander { redis::String string_db(srv->storage, conn->GetNamespace()); StringLCSResult rst; - auto s = string_db.LCS(args_[1], args_[2], {type_, min_match_len_}, &rst); + engine::Context ctx(srv->storage); + auto s = string_db.LCS(ctx, args_[1], args_[2], {type_, min_match_len_}, &rst); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/commands/cmd_zset.cc b/src/commands/cmd_zset.cc index e39ddd4fa44..51f1c6e0967 100644 --- a/src/commands/cmd_zset.cc +++ b/src/commands/cmd_zset.cc @@ -72,7 +72,8 @@ class CommandZAdd : public Commander { uint64_t ret = 0; double old_score = member_scores_[0].score; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.Add(args_[1], flags_, &member_scores_, &ret); + engine::Context ctx(srv->storage); + auto s = zset_db.Add(ctx, args_[1], flags_, &member_scores_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -143,7 +144,8 @@ class CommandZCount : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.Count(args_[1], spec_, &ret); + engine::Context ctx(srv->storage); + auto s = zset_db.Count(ctx, args_[1], spec_, &ret); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -161,7 +163,8 @@ class CommandZCard : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t ret = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.Card(args_[1], &ret); + engine::Context ctx(srv->storage); + auto s = zset_db.Card(ctx, args_[1], &ret); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -185,7 +188,8 @@ class CommandZIncrBy : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { double score = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.IncrBy(args_[1], args_[3], incr_, &score); + engine::Context ctx(srv->storage); + auto s = zset_db.IncrBy(ctx, args_[1], args_[3], incr_, &score); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -210,7 +214,8 @@ class CommandZLexCount : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t size = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.RangeByLex(args_[1], spec_, nullptr, &size); + engine::Context ctx(srv->storage); + auto s = zset_db.RangeByLex(ctx, args_[1], spec_, nullptr, &size); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -246,7 +251,8 @@ class CommandZPop : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); std::vector member_scores; - auto s = zset_db.Pop(args_[1], count_, min_, &member_scores); + engine::Context ctx(srv->storage); + auto s = zset_db.Pop(ctx, args_[1], count_, min_, &member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -275,11 +281,12 @@ class CommandZPopMax : public CommandZPop { CommandZPopMax() : CommandZPop(false) {} }; -static rocksdb::Status PopFromMultipleZsets(redis::ZSet *zset_db, const std::vector &keys, bool min, - int count, std::string *user_key, std::vector *member_scores) { +static rocksdb::Status PopFromMultipleZsets(engine::Context &ctx, redis::ZSet *zset_db, + const std::vector &keys, bool min, int count, + std::string *user_key, std::vector *member_scores) { rocksdb::Status s; for (auto &key : keys) { - s = zset_db->Pop(key, count, min, member_scores); + s = zset_db->Pop(ctx, key, count, min, member_scores); if (!s.ok()) { return s; } @@ -319,7 +326,8 @@ class CommandBZPop : public BlockingCommander { std::vector member_scores; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = PopFromMultipleZsets(&zset_db, keys_, min_, 1, &user_key, &member_scores); + engine::Context ctx(srv->storage); + auto s = PopFromMultipleZsets(ctx, &zset_db, keys_, min_, 1, &user_key, &member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -363,7 +371,8 @@ class CommandBZPop : public BlockingCommander { std::vector member_scores; redis::ZSet zset_db(srv_->storage, conn_->GetNamespace()); - auto s = PopFromMultipleZsets(&zset_db, keys_, min_, 1, &user_key, &member_scores); + engine::Context ctx(srv_->storage); + auto s = PopFromMultipleZsets(ctx, &zset_db, keys_, min_, 1, &user_key, &member_scores); if (!s.ok()) { conn_->Reply(redis::Error({Status::NotOK, s.ToString()})); return true; @@ -438,9 +447,10 @@ class CommandZMPop : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); + engine::Context ctx(srv->storage); for (auto &user_key : keys_) { std::vector member_scores; - auto s = zset_db.Pop(user_key, count_, flag_ == ZSET_MIN, &member_scores); + auto s = zset_db.Pop(ctx, user_key, count_, flag_ == ZSET_MIN, &member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -510,7 +520,8 @@ class CommandBZMPop : public BlockingCommander { std::vector member_scores; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = PopFromMultipleZsets(&zset_db, keys_, flag_ == ZSET_MIN, count_, &user_key, &member_scores); + engine::Context ctx(srv->storage); + auto s = PopFromMultipleZsets(ctx, &zset_db, keys_, flag_ == ZSET_MIN, count_, &user_key, &member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -542,7 +553,8 @@ class CommandBZMPop : public BlockingCommander { std::vector member_scores; redis::ZSet zset_db(srv_->storage, conn_->GetNamespace()); - auto s = PopFromMultipleZsets(&zset_db, keys_, flag_ == ZSET_MIN, count_, &user_key, &member_scores); + engine::Context ctx(srv_->storage); + auto s = PopFromMultipleZsets(ctx, &zset_db, keys_, flag_ == ZSET_MIN, count_, &user_key, &member_scores); if (!s.ok()) { conn_->Reply(redis::Error({Status::NotOK, s.ToString()})); return true; @@ -651,16 +663,17 @@ class CommandZRangeStore : public Commander { std::vector member_scores; rocksdb::Status s; + engine::Context ctx(srv->storage); switch (range_type_) { case kZRangeAuto: case kZRangeRank: - s = zset_db.RangeByRank(src_, rank_spec_, &member_scores, nullptr); + s = zset_db.RangeByRank(ctx, src_, rank_spec_, &member_scores, nullptr); break; case kZRangeScore: - s = zset_db.RangeByScore(src_, score_spec_, &member_scores, nullptr); + s = zset_db.RangeByScore(ctx, src_, score_spec_, &member_scores, nullptr); break; case kZRangeLex: - s = zset_db.RangeByLex(src_, lex_spec_, &member_scores, nullptr); + s = zset_db.RangeByLex(ctx, src_, lex_spec_, &member_scores, nullptr); break; } if (!s.ok()) { @@ -668,7 +681,7 @@ class CommandZRangeStore : public Commander { } uint64_t ret = member_scores.size(); - s = zset_db.Overwrite(dst_, member_scores); + s = zset_db.Overwrite(ctx, dst_, member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -787,24 +800,25 @@ class CommandZRangeGeneric : public Commander { std::vector member_scores; rocksdb::Status s; + engine::Context ctx(srv->storage); switch (range_type_) { case kZRangeAuto: case kZRangeRank: - s = zset_db.RangeByRank(key_, rank_spec_, &member_scores, nullptr); + s = zset_db.RangeByRank(ctx, key_, rank_spec_, &member_scores, nullptr); break; case kZRangeScore: if (score_spec_.count == 0) { *output = conn->MultiBulkString({}); return Status::OK(); } - s = zset_db.RangeByScore(key_, score_spec_, &member_scores, nullptr); + s = zset_db.RangeByScore(ctx, key_, score_spec_, &member_scores, nullptr); break; case kZRangeLex: if (lex_spec_.count == 0) { *output = conn->MultiBulkString({}); return Status::OK(); } - s = zset_db.RangeByLex(key_, lex_spec_, &member_scores, nullptr); + s = zset_db.RangeByLex(ctx, key_, lex_spec_, &member_scores, nullptr); break; } if (!s.ok()) { @@ -890,7 +904,8 @@ class CommandZRank : public Commander { int rank = 0; double score = 0.0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.Rank(args_[1], args_[2], reversed_, &rank, &score); + engine::Context ctx(srv->storage); + auto s = zset_db.Rank(ctx, args_[1], args_[2], reversed_, &rank, &score); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -933,7 +948,8 @@ class CommandZRem : public Commander { uint64_t size = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.Remove(args_[1], members, &size); + engine::Context ctx(srv->storage); + auto s = zset_db.Remove(ctx, args_[1], members, &size); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -964,7 +980,8 @@ class CommandZRemRangeByRank : public Commander { uint64_t cnt = 0; spec_.with_deletion = true; - auto s = zset_db.RangeByRank(args_[1], spec_, nullptr, &cnt); + engine::Context ctx(srv->storage); + auto s = zset_db.RangeByRank(ctx, args_[1], spec_, nullptr, &cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -991,7 +1008,8 @@ class CommandZRemRangeByScore : public Commander { uint64_t cnt = 0; spec_.with_deletion = true; - auto s = zset_db.RangeByScore(args_[1], spec_, nullptr, &cnt); + engine::Context ctx(srv->storage); + auto s = zset_db.RangeByScore(ctx, args_[1], spec_, nullptr, &cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1018,7 +1036,8 @@ class CommandZRemRangeByLex : public Commander { uint64_t cnt = 0; spec_.with_deletion = true; - auto s = zset_db.RangeByLex(args_[1], spec_, nullptr, &cnt); + engine::Context ctx(srv->storage); + auto s = zset_db.RangeByLex(ctx, args_[1], spec_, nullptr, &cnt); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1036,7 +1055,8 @@ class CommandZScore : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { double score = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.Score(args_[1], args_[2], &score); + engine::Context ctx(srv->storage); + auto s = zset_db.Score(ctx, args_[1], args_[2], &score); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1059,7 +1079,8 @@ class CommandZMScore : public Commander { } std::map mscores; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.MGet(args_[1], members, &mscores); + engine::Context ctx(srv->storage); + auto s = zset_db.MGet(ctx, args_[1], members, &mscores); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1125,7 +1146,8 @@ class CommandZUnion : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); std::vector member_scores; - auto s = zset_db.Union(keys_weights_, aggregate_method_, &member_scores); + engine::Context ctx(srv->storage); + auto s = zset_db.Union(ctx, keys_weights_, aggregate_method_, &member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1210,7 +1232,8 @@ class CommandZUnionStore : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t size = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.UnionStore(args_[1], keys_weights_, aggregate_method_, &size); + engine::Context ctx(srv->storage); + auto s = zset_db.UnionStore(ctx, args_[1], keys_weights_, aggregate_method_, &size); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1237,7 +1260,8 @@ class CommandZInterStore : public CommandZUnionStore { Status Execute(Server *srv, Connection *conn, std::string *output) override { uint64_t size = 0; redis::ZSet zset_db(srv->storage, conn->GetNamespace()); - auto s = zset_db.InterStore(args_[1], keys_weights_, aggregate_method_, &size); + engine::Context ctx(srv->storage); + auto s = zset_db.InterStore(ctx, args_[1], keys_weights_, aggregate_method_, &size); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1259,7 +1283,8 @@ class CommandZInter : public CommandZUnion { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); std::vector member_scores; - auto s = zset_db.Inter(keys_weights_, aggregate_method_, &member_scores); + engine::Context ctx(srv->storage); + auto s = zset_db.Inter(ctx, keys_weights_, aggregate_method_, &member_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1314,7 +1339,8 @@ class CommandZInterCard : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); uint64_t count = 0; - auto s = zset_db.InterCard(keys_, limit_, &count); + engine::Context ctx(srv->storage); + auto s = zset_db.InterCard(ctx, keys_, limit_, &count); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1342,7 +1368,8 @@ class CommandZScan : public CommandSubkeyScanBase { std::vector members; std::vector scores; auto key_name = srv->GetKeyNameFromCursor(cursor_, CursorType::kTypeZSet); - auto s = zset_db.Scan(key_, key_name, limit_, prefix_, &members, &scores); + engine::Context ctx(srv->storage); + auto s = zset_db.Scan(ctx, key_, key_name, limit_, prefix_, &members, &scores); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1391,7 +1418,8 @@ class CommandZRandMember : public Commander { Status Execute(Server *srv, Connection *conn, std::string *output) override { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); std::vector member_scores; - auto s = zset_db.RandMember(args_[1], count_, &member_scores); + engine::Context ctx(srv->storage); + auto s = zset_db.RandMember(ctx, args_[1], count_, &member_scores); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; @@ -1447,7 +1475,8 @@ class CommandZDiff : public Commander { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); std::vector members_with_scores; - auto s = zset_db.Diff(keys_, &members_with_scores); + engine::Context ctx(srv->storage); + auto s = zset_db.Diff(ctx, keys_, &members_with_scores); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -1494,7 +1523,8 @@ class CommandZDiffStore : public Commander { redis::ZSet zset_db(srv->storage, conn->GetNamespace()); uint64_t stored_count = 0; - auto s = zset_db.DiffStore(args_[1], keys_, &stored_count); + engine::Context ctx(srv->storage); + auto s = zset_db.DiffStore(ctx, args_[1], keys_, &stored_count); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/common/db_util.h b/src/common/db_util.h index d29262f2b33..eea60d011f4 100644 --- a/src/common/db_util.h +++ b/src/common/db_util.h @@ -34,13 +34,12 @@ struct UniqueIterator : std::unique_ptr { using BaseType = std::unique_ptr; explicit UniqueIterator(rocksdb::Iterator* iter) : BaseType(iter) {} - UniqueIterator(engine::Storage* storage, const rocksdb::ReadOptions& options, - rocksdb::ColumnFamilyHandle* column_family) - : BaseType(storage->NewIterator(options, column_family)) {} - UniqueIterator(engine::Storage* storage, const rocksdb::ReadOptions& options, ColumnFamilyID cf) - : BaseType(storage->NewIterator(options, storage->GetCFHandle(cf))) {} - UniqueIterator(engine::Storage* storage, const rocksdb::ReadOptions& options) - : BaseType(storage->NewIterator(options)) {} + UniqueIterator(engine::Context& ctx, const rocksdb::ReadOptions& options, rocksdb::ColumnFamilyHandle* column_family) + : BaseType(ctx.storage->NewIterator(ctx, options, column_family)) {} + UniqueIterator(engine::Context& ctx, const rocksdb::ReadOptions& options, ColumnFamilyID cf) + : BaseType(ctx.storage->NewIterator(ctx, options, ctx.storage->GetCFHandle(cf))) {} + UniqueIterator(engine::Context& ctx, const rocksdb::ReadOptions& options) + : BaseType(ctx.storage->NewIterator(ctx, options)) {} }; namespace details { diff --git a/src/search/executors/filter_executor.h b/src/search/executors/filter_executor.h index 1b1febe842e..e1b23257774 100644 --- a/src/search/executors/filter_executor.h +++ b/src/search/executors/filter_executor.h @@ -77,7 +77,7 @@ struct QueryExprEvaluator { StatusOr Visit(NotExpr *v) const { return !GET_OR_RET(Transform(v->inner.get())); } StatusOr Visit(TagContainExpr *v) const { - auto val = GET_OR_RET(ctx->Retrieve(row, v->field->info)); + auto val = GET_OR_RET(ctx->Retrieve(ctx->db_ctx, row, v->field->info)); CHECK(val.Is()); auto tags = val.Get(); @@ -92,7 +92,7 @@ struct QueryExprEvaluator { } StatusOr Visit(NumericCompareExpr *v) const { - auto l_val = GET_OR_RET(ctx->Retrieve(row, v->field->info)); + auto l_val = GET_OR_RET(ctx->Retrieve(ctx->db_ctx, row, v->field->info)); CHECK(l_val.Is()); auto l = l_val.Get(); @@ -118,7 +118,7 @@ struct QueryExprEvaluator { } StatusOr Visit(VectorRangeExpr *v) const { - auto val = GET_OR_RET(ctx->Retrieve(row, v->field->info)); + auto val = GET_OR_RET(ctx->Retrieve(ctx->db_ctx, row, v->field->info)); CHECK(val.Is()); auto l_values = val.Get(); diff --git a/src/search/executors/full_index_scan_executor.h b/src/search/executors/full_index_scan_executor.h index 3fde9ef5622..36a7fe15961 100644 --- a/src/search/executors/full_index_scan_executor.h +++ b/src/search/executors/full_index_scan_executor.h @@ -30,12 +30,11 @@ namespace kqir { struct FullIndexScanExecutor : ExecutorNode { FullIndexScan *scan; - redis::LatestSnapShot ss; util::UniqueIterator iter{nullptr}; const std::string *prefix_iter; FullIndexScanExecutor(ExecutorContext *ctx, FullIndexScan *scan) - : ExecutorNode(ctx), scan(scan), ss(ctx->storage), prefix_iter(scan->index->info->prefixes.begin()) {} + : ExecutorNode(ctx), scan(scan), prefix_iter(scan->index->info->prefixes.begin()) {} std::string NSKey(const std::string &user_key) { return ComposeNamespaceKey(scan->index->info->ns, user_key, ctx->storage->IsSlotIdEncoded()); @@ -48,9 +47,8 @@ struct FullIndexScanExecutor : ExecutorNode { auto ns_key = NSKey(*prefix_iter); if (!iter) { - rocksdb::ReadOptions read_options = ctx->storage->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); - iter = util::UniqueIterator(ctx->storage, read_options, ctx->storage->GetCFHandle(ColumnFamilyID::Metadata)); + iter = util::UniqueIterator(ctx->db_ctx, ctx->db_ctx.DefaultScanOptions(), + ctx->storage->GetCFHandle(ColumnFamilyID::Metadata)); iter->Seek(ns_key); } diff --git a/src/search/executors/hnsw_vector_field_knn_scan_executor.h b/src/search/executors/hnsw_vector_field_knn_scan_executor.h index 5002fba18ae..7617bcc657c 100644 --- a/src/search/executors/hnsw_vector_field_knn_scan_executor.h +++ b/src/search/executors/hnsw_vector_field_knn_scan_executor.h @@ -37,7 +37,6 @@ namespace kqir { // TODO(Beihao): Add DB context to improve consistency and isolation - see #2332 struct HnswVectorFieldKnnScanExecutor : ExecutorNode { HnswVectorFieldKnnScan *scan; - redis::LatestSnapShot ss; bool initialized = false; IndexInfo *index; @@ -50,7 +49,6 @@ struct HnswVectorFieldKnnScanExecutor : ExecutorNode { HnswVectorFieldKnnScanExecutor(ExecutorContext *ctx, HnswVectorFieldKnnScan *scan) : ExecutorNode(ctx), scan(scan), - ss(ctx->storage), index(scan->field->info->index), search_key(index->ns, index->name, scan->field->name), field_metadata(*(scan->field->info->MetadataAs())), @@ -58,7 +56,7 @@ struct HnswVectorFieldKnnScanExecutor : ExecutorNode { StatusOr Next() override { if (!initialized) { - row_keys = GET_OR_RET(hnsw_index.KnnSearch(scan->vector, scan->k)); + row_keys = GET_OR_RET(hnsw_index.KnnSearch(ctx->db_ctx, scan->vector, scan->k)); row_keys_iter = row_keys.begin(); initialized = true; } diff --git a/src/search/executors/hnsw_vector_field_range_scan_executor.h b/src/search/executors/hnsw_vector_field_range_scan_executor.h index afaf0297a3d..05071bad44b 100644 --- a/src/search/executors/hnsw_vector_field_range_scan_executor.h +++ b/src/search/executors/hnsw_vector_field_range_scan_executor.h @@ -37,7 +37,6 @@ namespace kqir { // TODO(Beihao): Add DB context to improve consistency and isolation - see #2332 struct HnswVectorFieldRangeScanExecutor : ExecutorNode { HnswVectorFieldRangeScan *scan; - redis::LatestSnapShot ss; bool initialized = false; IndexInfo *index; @@ -51,7 +50,6 @@ struct HnswVectorFieldRangeScanExecutor : ExecutorNode { HnswVectorFieldRangeScanExecutor(ExecutorContext *ctx, HnswVectorFieldRangeScan *scan) : ExecutorNode(ctx), scan(scan), - ss(ctx->storage), index(scan->field->info->index), search_key(index->ns, index->name, scan->field->name), field_metadata(*(scan->field->info->MetadataAs())), @@ -59,7 +57,7 @@ struct HnswVectorFieldRangeScanExecutor : ExecutorNode { StatusOr Next() override { if (!initialized) { - row_keys = GET_OR_RET(hnsw_index.KnnSearch(scan->vector, field_metadata.ef_runtime)); + row_keys = GET_OR_RET(hnsw_index.KnnSearch(ctx->db_ctx, scan->vector, field_metadata.ef_runtime)); row_keys_iter = row_keys.begin(); initialized = true; } @@ -67,7 +65,7 @@ struct HnswVectorFieldRangeScanExecutor : ExecutorNode { auto effective_range = scan->range * (1 + field_metadata.epsilon); if (row_keys_iter == row_keys.end() || row_keys_iter->first > abs(effective_range) || row_keys_iter->first < -abs(effective_range)) { - row_keys = GET_OR_RET(hnsw_index.ExpandSearchScope(scan->vector, std::move(row_keys), visited)); + row_keys = GET_OR_RET(hnsw_index.ExpandSearchScope(ctx->db_ctx, scan->vector, std::move(row_keys), visited)); if (row_keys.empty()) return end; row_keys_iter = row_keys.begin(); } diff --git a/src/search/executors/numeric_field_scan_executor.h b/src/search/executors/numeric_field_scan_executor.h index 5c997df0fc1..3139fa5c220 100644 --- a/src/search/executors/numeric_field_scan_executor.h +++ b/src/search/executors/numeric_field_scan_executor.h @@ -35,7 +35,6 @@ namespace kqir { struct NumericFieldScanExecutor : ExecutorNode { NumericFieldScan *scan; - redis::LatestSnapShot ss; util::UniqueIterator iter{nullptr}; IndexInfo *index; @@ -44,7 +43,6 @@ struct NumericFieldScanExecutor : ExecutorNode { NumericFieldScanExecutor(ExecutorContext *ctx, NumericFieldScan *scan) : ExecutorNode(ctx), scan(scan), - ss(ctx->storage), index(scan->field->info->index), search_key(index->ns, index->name, scan->field->name) {} @@ -77,10 +75,8 @@ struct NumericFieldScanExecutor : ExecutorNode { StatusOr Next() override { if (!iter) { - rocksdb::ReadOptions read_options = ctx->storage->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); - - iter = util::UniqueIterator(ctx->storage, read_options, ctx->storage->GetCFHandle(ColumnFamilyID::Search)); + iter = util::UniqueIterator(ctx->db_ctx, ctx->db_ctx.DefaultScanOptions(), + ctx->storage->GetCFHandle(ColumnFamilyID::Search)); if (scan->order == SortByClause::ASC) { iter->Seek(IndexKey(scan->range.l)); } else { diff --git a/src/search/executors/projection_executor.h b/src/search/executors/projection_executor.h index fe167334500..5bca9ac0725 100644 --- a/src/search/executors/projection_executor.h +++ b/src/search/executors/projection_executor.h @@ -28,7 +28,6 @@ namespace kqir { struct ProjectionExecutor : ExecutorNode { Projection *proj; - ProjectionExecutor(ExecutorContext *ctx, Projection *proj) : ExecutorNode(ctx), proj(proj) {} StatusOr Next() override { @@ -39,13 +38,13 @@ struct ProjectionExecutor : ExecutorNode { auto &row = std::get(v); if (proj->select->fields.empty()) { for (const auto &field : row.index->fields) { - GET_OR_RET(ctx->Retrieve(row, &field.second)); + GET_OR_RET(ctx->Retrieve(ctx->db_ctx, row, &field.second)); } } else { std::map res; for (const auto &field : proj->select->fields) { - auto r = GET_OR_RET(ctx->Retrieve(row, field->info)); + auto r = GET_OR_RET(ctx->Retrieve(ctx->db_ctx, row, field->info)); res.emplace(field->info, std::move(r)); } diff --git a/src/search/executors/tag_field_scan_executor.h b/src/search/executors/tag_field_scan_executor.h index 946db767432..dbbe536131c 100644 --- a/src/search/executors/tag_field_scan_executor.h +++ b/src/search/executors/tag_field_scan_executor.h @@ -35,7 +35,6 @@ namespace kqir { struct TagFieldScanExecutor : ExecutorNode { TagFieldScan *scan; - redis::LatestSnapShot ss; util::UniqueIterator iter{nullptr}; IndexInfo *index; @@ -45,7 +44,6 @@ struct TagFieldScanExecutor : ExecutorNode { TagFieldScanExecutor(ExecutorContext *ctx, TagFieldScan *scan) : ExecutorNode(ctx), scan(scan), - ss(ctx->storage), index(scan->field->info->index), index_key(redis::SearchKey(index->ns, index->name, scan->field->name).ConstructTagFieldData(scan->tag, {})), case_sensitive(scan->field->info->MetadataAs()->case_sensitive) {} @@ -78,10 +76,8 @@ struct TagFieldScanExecutor : ExecutorNode { StatusOr Next() override { if (!iter) { - rocksdb::ReadOptions read_options = ctx->storage->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); - - iter = util::UniqueIterator(ctx->storage, read_options, ctx->storage->GetCFHandle(ColumnFamilyID::Search)); + iter = util::UniqueIterator(ctx->db_ctx, ctx->db_ctx.DefaultScanOptions(), + ctx->storage->GetCFHandle(ColumnFamilyID::Search)); iter->Seek(index_key); } diff --git a/src/search/executors/topn_sort_executor.h b/src/search/executors/topn_sort_executor.h index 163b1bc7f3c..27c94d242bf 100644 --- a/src/search/executors/topn_sort_executor.h +++ b/src/search/executors/topn_sort_executor.h @@ -57,7 +57,7 @@ struct TopNSortExecutor : ExecutorNode { auto &row = std::get(v); auto get_order = [this](RowType &row) -> StatusOr { - auto order_val = GET_OR_RET(ctx->Retrieve(row, sort->order->field->info)); + auto order_val = GET_OR_RET(ctx->Retrieve(ctx->db_ctx, row, sort->order->field->info)); CHECK(order_val.Is()); return order_val.Get(); }; diff --git a/src/search/hnsw_indexer.cc b/src/search/hnsw_indexer.cc index 3618ad89bfc..4af11b10b8a 100644 --- a/src/search/hnsw_indexer.cc +++ b/src/search/hnsw_indexer.cc @@ -36,10 +36,11 @@ namespace redis { HnswNode::HnswNode(NodeKey key, uint16_t level) : key(std::move(key)), level(level) {} -StatusOr HnswNode::DecodeMetadata(const SearchKey& search_key, engine::Storage* storage) const { +StatusOr HnswNode::DecodeMetadata(engine::Context& ctx, const SearchKey& search_key) const { auto node_index_key = search_key.ConstructHnswNode(level, key); rocksdb::PinnableSlice value; - auto s = storage->Get(rocksdb::ReadOptions(), storage->GetCFHandle(ColumnFamilyID::Search), node_index_key, &value); + auto s = ctx.storage->Get(ctx, ctx.GetReadOptions(), ctx.storage->GetCFHandle(ColumnFamilyID::Search), node_index_key, + &value); if (!s.ok()) return {Status::NotOK, s.ToString()}; HnswNodeFieldMetadata metadata; @@ -55,10 +56,10 @@ void HnswNode::PutMetadata(HnswNodeFieldMetadata* node_meta, const SearchKey& se batch->Put(storage->GetCFHandle(ColumnFamilyID::Search), search_key.ConstructHnswNode(level, key), updated_metadata); } -void HnswNode::DecodeNeighbours(const SearchKey& search_key, engine::Storage* storage) { +void HnswNode::DecodeNeighbours(engine::Context& ctx, const SearchKey& search_key) { neighbours.clear(); auto edge_prefix = search_key.ConstructHnswEdgeWithSingleEnd(level, key); - util::UniqueIterator iter(storage, storage->DefaultScanOptions(), ColumnFamilyID::Search); + util::UniqueIterator iter(ctx, ctx.DefaultScanOptions(), ColumnFamilyID::Search); for (iter->Seek(edge_prefix); iter->Valid(); iter->Next()) { if (!iter->key().starts_with(edge_prefix)) { break; @@ -71,28 +72,28 @@ void HnswNode::DecodeNeighbours(const SearchKey& search_key, engine::Storage* st } } -Status HnswNode::AddNeighbour(const NodeKey& neighbour_key, const SearchKey& search_key, engine::Storage* storage, +Status HnswNode::AddNeighbour(engine::Context& ctx, const NodeKey& neighbour_key, const SearchKey& search_key, rocksdb::WriteBatchBase* batch) const { auto edge_index_key = search_key.ConstructHnswEdge(level, key, neighbour_key); - batch->Put(storage->GetCFHandle(ColumnFamilyID::Search), edge_index_key, Slice()); + batch->Put(ctx.storage->GetCFHandle(ColumnFamilyID::Search), edge_index_key, Slice()); - HnswNodeFieldMetadata node_metadata = GET_OR_RET(DecodeMetadata(search_key, storage)); + HnswNodeFieldMetadata node_metadata = GET_OR_RET(DecodeMetadata(ctx, search_key)); node_metadata.num_neighbours++; - PutMetadata(&node_metadata, search_key, storage, batch); + PutMetadata(&node_metadata, search_key, ctx.storage, batch); return Status::OK(); } -Status HnswNode::RemoveNeighbour(const NodeKey& neighbour_key, const SearchKey& search_key, engine::Storage* storage, +Status HnswNode::RemoveNeighbour(engine::Context& ctx, const NodeKey& neighbour_key, const SearchKey& search_key, rocksdb::WriteBatchBase* batch) const { auto edge_index_key = search_key.ConstructHnswEdge(level, key, neighbour_key); - auto s = batch->Delete(storage->GetCFHandle(ColumnFamilyID::Search), edge_index_key); + auto s = batch->Delete(ctx.storage->GetCFHandle(ColumnFamilyID::Search), edge_index_key); if (!s.ok()) { return {Status::NotOK, fmt::format("failed to delete edge, {}", s.ToString())}; } - HnswNodeFieldMetadata node_metadata = GET_OR_RET(DecodeMetadata(search_key, storage)); + HnswNodeFieldMetadata node_metadata = GET_OR_RET(DecodeMetadata(ctx, search_key)); node_metadata.num_neighbours--; - PutMetadata(&node_metadata, search_key, storage, batch); + PutMetadata(&node_metadata, search_key, ctx.storage, batch); return Status::OK(); } @@ -183,9 +184,9 @@ uint16_t HnswIndex::RandomizeLayer() { return static_cast(std::floor(layer_val)); } -StatusOr HnswIndex::DefaultEntryPoint(uint16_t level) const { +StatusOr HnswIndex::DefaultEntryPoint(engine::Context& ctx, uint16_t level) const { auto prefix = search_key.ConstructHnswLevelNodePrefix(level); - util::UniqueIterator it(storage, storage->DefaultScanOptions(), ColumnFamilyID::Search); + util::UniqueIterator it(ctx, ctx.DefaultScanOptions(), ColumnFamilyID::Search); it->Seek(prefix); Slice node_key; @@ -201,16 +202,16 @@ StatusOr HnswIndex::DefaultEntryPoint(uint16_t level) const return {Status::NotFound, fmt::format("No node found in layer {}", level)}; } -StatusOr> HnswIndex::DecodeNodesToVectorItems(const std::vector& node_keys, +StatusOr> HnswIndex::DecodeNodesToVectorItems(engine::Context& ctx, + const std::vector& node_keys, uint16_t level, const SearchKey& search_key, - engine::Storage* storage, const HnswVectorFieldMetadata* metadata) { std::vector vector_items; vector_items.reserve(node_keys.size()); for (const auto& neighbour_key : node_keys) { HnswNode neighbour_node(neighbour_key, level); - auto neighbour_metadata_status = neighbour_node.DecodeMetadata(search_key, storage); + auto neighbour_metadata_status = neighbour_node.DecodeMetadata(ctx, search_key); if (!neighbour_metadata_status.IsOK()) { continue; // Skip this neighbour if metadata can't be decoded } @@ -276,7 +277,7 @@ StatusOr> HnswIndex::SelectNeighbors(const VectorItem& v } StatusOr> HnswIndex::SearchLayerInternal( - uint16_t level, const VectorItem& target_vector, uint32_t ef_runtime, + engine::Context& ctx, uint16_t level, const VectorItem& target_vector, uint32_t ef_runtime, const std::vector& entry_points) const { std::vector result; std::unordered_set visited; @@ -285,7 +286,7 @@ StatusOr> HnswIndex::SearchLayerInternal( for (const auto& entry_point_key : entry_points) { HnswNode entry_node = HnswNode(entry_point_key, level); - auto entry_node_metadata = GET_OR_RET(entry_node.DecodeMetadata(search_key, storage)); + auto entry_node_metadata = GET_OR_RET(entry_node.DecodeMetadata(ctx, search_key)); VectorItem entry_point_vector; GET_OR_RET( @@ -305,7 +306,7 @@ StatusOr> HnswIndex::SearchLayerInternal( } auto current_node = HnswNode(current_vector.key, level); - current_node.DecodeNeighbours(search_key, storage); + current_node.DecodeNeighbours(ctx, search_key); for (const auto& neighbour_key : current_node.neighbours) { if (visited.find(neighbour_key) != visited.end()) { @@ -314,7 +315,7 @@ StatusOr> HnswIndex::SearchLayerInternal( visited.insert(neighbour_key); auto neighbour_node = HnswNode(neighbour_key, level); - auto neighbour_node_metadata = GET_OR_RET(neighbour_node.DecodeMetadata(search_key, storage)); + auto neighbour_node_metadata = GET_OR_RET(neighbour_node.DecodeMetadata(ctx, search_key)); VectorItem neighbour_node_vector; GET_OR_RET(VectorItem::Create(neighbour_key, std::move(neighbour_node_metadata.vector), metadata, @@ -339,18 +340,19 @@ StatusOr> HnswIndex::SearchLayerInternal( return result; } -StatusOr> HnswIndex::SearchLayer(uint16_t level, const VectorItem& target_vector, - uint32_t ef_runtime, +StatusOr> HnswIndex::SearchLayer(engine::Context& ctx, uint16_t level, + const VectorItem& target_vector, uint32_t ef_runtime, const std::vector& entry_points) const { std::vector result; - auto result_with_distance = GET_OR_RET(SearchLayerInternal(level, target_vector, ef_runtime, entry_points)); + auto result_with_distance = GET_OR_RET(SearchLayerInternal(ctx, level, target_vector, ef_runtime, entry_points)); for (auto& [_, vector_item] : result_with_distance) { result.push_back(std::move(vector_item)); } return result; } -Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::NumericArray& vector, +Status HnswIndex::InsertVectorEntryInternal(engine::Context& ctx, std::string_view key, + const kqir::NumericArray& vector, ObserverOrUniquePtr& batch, uint16_t target_level) const { auto cf_handle = storage->GetCFHandle(ColumnFamilyID::Search); @@ -361,16 +363,17 @@ Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::Nu if (metadata->num_levels != 0) { auto level = metadata->num_levels - 1; - auto default_entry_node = GET_OR_RET(DefaultEntryPoint(level)); + auto default_entry_node = GET_OR_RET(DefaultEntryPoint(ctx, level)); std::vector entry_points{default_entry_node}; for (; level > target_level; level--) { - nearest_vec_items = GET_OR_RET(SearchLayer(level, inserted_vector_item, metadata->ef_runtime, entry_points)); + nearest_vec_items = GET_OR_RET(SearchLayer(ctx, level, inserted_vector_item, metadata->ef_runtime, entry_points)); entry_points = {nearest_vec_items[0].key}; } for (; level >= 0; level--) { - nearest_vec_items = GET_OR_RET(SearchLayer(level, inserted_vector_item, metadata->ef_construction, entry_points)); + nearest_vec_items = + GET_OR_RET(SearchLayer(ctx, level, inserted_vector_item, metadata->ef_construction, entry_points)); auto candidate_vec_items = GET_OR_RET(SelectNeighbors(inserted_vector_item, nearest_vec_items, level)); auto node = HnswNode(std::string(key), level); auto m_max = level == 0 ? 2 * metadata->m : metadata->m; @@ -395,7 +398,7 @@ Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::Nu for (const auto& candidate_vec : candidate_vec_items) { auto candidate_node = HnswNode(candidate_vec.key, level); - auto candidate_node_metadata = GET_OR_RET(candidate_node.DecodeMetadata(search_key, storage)); + auto candidate_node_metadata = GET_OR_RET(candidate_node.DecodeMetadata(ctx, search_key)); uint16_t candidate_node_num_neighbours = candidate_node_metadata.num_neighbours; if (has_room_for_more_edges(candidate_node_num_neighbours) || @@ -406,9 +409,9 @@ Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::Nu } // Re-evaluate the neighbours for the candidate node - candidate_node.DecodeNeighbours(search_key, storage); + candidate_node.DecodeNeighbours(ctx, search_key); auto candidate_node_neighbour_vec_items = - GET_OR_RET(DecodeNodesToVectorItems(candidate_node.neighbours, level, search_key, storage, metadata)); + GET_OR_RET(DecodeNodesToVectorItems(ctx, candidate_node.neighbours, level, search_key, metadata)); candidate_node_neighbour_vec_items.push_back(inserted_vector_item); auto sorted_neighbours_by_distance = GET_OR_RET(SelectNeighbors(candidate_vec, candidate_node_neighbour_vec_items, level)); @@ -448,7 +451,7 @@ Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::Nu for (const auto& node_edges : deleted_edges_map) { auto& current_node_key = node_edges.first; auto current_node = HnswNode(current_node_key, level); - auto current_node_metadata = GET_OR_RET(current_node.DecodeMetadata(search_key, storage)); + auto current_node_metadata = GET_OR_RET(current_node.DecodeMetadata(ctx, search_key)); auto new_num_neighbours = current_node_metadata.num_neighbours - node_edges.second.size(); if (connected_edges_set.count(current_node_key) != 0) { new_num_neighbours++; @@ -460,7 +463,7 @@ Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::Nu for (const auto& current_node_key : connected_edges_set) { auto current_node = HnswNode(current_node_key, level); - HnswNodeFieldMetadata current_node_metadata = GET_OR_RET(current_node.DecodeMetadata(search_key, storage)); + HnswNodeFieldMetadata current_node_metadata = GET_OR_RET(current_node.DecodeMetadata(ctx, search_key)); current_node_metadata.num_neighbours++; current_node.PutMetadata(¤t_node_metadata, search_key, storage, batch.Get()); } @@ -492,17 +495,18 @@ Status HnswIndex::InsertVectorEntryInternal(std::string_view key, const kqir::Nu return Status::OK(); } -Status HnswIndex::InsertVectorEntry(std::string_view key, const kqir::NumericArray& vector, +Status HnswIndex::InsertVectorEntry(engine::Context& ctx, std::string_view key, const kqir::NumericArray& vector, ObserverOrUniquePtr& batch) { auto target_level = RandomizeLayer(); - return InsertVectorEntryInternal(key, vector, batch, target_level); + return InsertVectorEntryInternal(ctx, key, vector, batch, target_level); } -Status HnswIndex::DeleteVectorEntry(std::string_view key, ObserverOrUniquePtr& batch) const { +Status HnswIndex::DeleteVectorEntry(engine::Context& ctx, std::string_view key, + ObserverOrUniquePtr& batch) const { std::string node_key(key); for (uint16_t level = 0; level < metadata->num_levels; level++) { auto node = HnswNode(node_key, level); - auto node_metadata_status = node.DecodeMetadata(search_key, storage); + auto node_metadata_status = node.DecodeMetadata(ctx, search_key); if (!node_metadata_status.IsOK()) { break; } @@ -514,11 +518,11 @@ Status HnswIndex::DeleteVectorEntry(std::string_view key, ObserverOrUniquePtr bool { auto prefix = search_key.ConstructHnswLevelNodePrefix(level); - util::UniqueIterator it(storage, storage->DefaultScanOptions(), ColumnFamilyID::Search); + util::UniqueIterator it(ctx, ctx.DefaultScanOptions(), ColumnFamilyID::Search); it->Seek(prefix); Slice node_key; @@ -560,7 +564,8 @@ Status HnswIndex::DeleteVectorEntry(std::string_view key, ObserverOrUniquePtr> HnswIndex::KnnSearch(const kqir::NumericArray& query_vector, uint32_t k) const { +StatusOr> HnswIndex::KnnSearch(engine::Context& ctx, + const kqir::NumericArray& query_vector, uint32_t k) const { VectorItem query_vector_item; GET_OR_RET(VectorItem::Create({}, query_vector, metadata, &query_vector_item)); @@ -569,17 +574,18 @@ StatusOr> HnswIndex::KnnSearch(const kqir::NumericA } auto level = metadata->num_levels - 1; - auto default_entry_node = GET_OR_RET(DefaultEntryPoint(level)); + auto default_entry_node = GET_OR_RET(DefaultEntryPoint(ctx, level)); std::vector entry_points{default_entry_node}; std::vector nearest_vec_items; for (; level > 0; level--) { - nearest_vec_items = GET_OR_RET(SearchLayer(level, query_vector_item, metadata->ef_runtime, entry_points)); + nearest_vec_items = GET_OR_RET(SearchLayer(ctx, level, query_vector_item, metadata->ef_runtime, entry_points)); entry_points = {nearest_vec_items[0].key}; } uint32_t effective_ef = std::max(metadata->ef_runtime, k); // Ensure ef_runtime is at least k - auto nearest_vec_with_distance = GET_OR_RET(SearchLayerInternal(0, query_vector_item, effective_ef, entry_points)); + auto nearest_vec_with_distance = + GET_OR_RET(SearchLayerInternal(ctx, 0, query_vector_item, effective_ef, entry_points)); uint32_t result_length = std::min(k, static_cast(nearest_vec_with_distance.size())); std::vector nearest_neighbours; @@ -590,7 +596,8 @@ StatusOr> HnswIndex::KnnSearch(const kqir::NumericA return nearest_neighbours; } -StatusOr> HnswIndex::ExpandSearchScope(const kqir::NumericArray& query_vector, +StatusOr> HnswIndex::ExpandSearchScope(engine::Context& ctx, + const kqir::NumericArray& query_vector, std::vector&& initial_keys, std::unordered_set& visited) const { constexpr uint16_t level = 0; @@ -603,7 +610,7 @@ StatusOr> HnswIndex::ExpandSearchScope(const kqir:: initial_keys.erase(initial_keys.begin()); auto current_node = HnswNode(current_key, level); - current_node.DecodeNeighbours(search_key, storage); + current_node.DecodeNeighbours(ctx, search_key); for (const auto& neighbour_key : current_node.neighbours) { if (visited.find(neighbour_key) != visited.end()) { @@ -612,7 +619,7 @@ StatusOr> HnswIndex::ExpandSearchScope(const kqir:: visited.insert(neighbour_key); auto neighbour_node = HnswNode(neighbour_key, level); - auto neighbour_node_metadata = GET_OR_RET(neighbour_node.DecodeMetadata(search_key, storage)); + auto neighbour_node_metadata = GET_OR_RET(neighbour_node.DecodeMetadata(ctx, search_key)); VectorItem neighbour_node_vector; GET_OR_RET(VectorItem::Create(neighbour_key, std::move(neighbour_node_metadata.vector), metadata, diff --git a/src/search/hnsw_indexer.h b/src/search/hnsw_indexer.h index 72072039c7b..28bf2381bde 100644 --- a/src/search/hnsw_indexer.h +++ b/src/search/hnsw_indexer.h @@ -41,15 +41,15 @@ struct HnswNode { HnswNode(NodeKey key, uint16_t level); - StatusOr DecodeMetadata(const SearchKey& search_key, engine::Storage* storage) const; + StatusOr DecodeMetadata(engine::Context& ctx, const SearchKey& search_key) const; void PutMetadata(HnswNodeFieldMetadata* node_meta, const SearchKey& search_key, engine::Storage* storage, rocksdb::WriteBatchBase* batch) const; - void DecodeNeighbours(const SearchKey& search_key, engine::Storage* storage); + void DecodeNeighbours(engine::Context& ctx, const SearchKey& search_key); // For testing purpose - Status AddNeighbour(const NodeKey& neighbour_key, const SearchKey& search_key, engine::Storage* storage, + Status AddNeighbour(engine::Context& ctx, const NodeKey& neighbour_key, const SearchKey& search_key, rocksdb::WriteBatchBase* batch) const; - Status RemoveNeighbour(const NodeKey& neighbour_key, const SearchKey& search_key, engine::Storage* storage, + Status RemoveNeighbour(engine::Context& ctx, const NodeKey& neighbour_key, const SearchKey& search_key, rocksdb::WriteBatchBase* batch) const; friend struct HnswIndex; }; @@ -94,12 +94,12 @@ struct HnswIndex { HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* vector, engine::Storage* storage); - static StatusOr> DecodeNodesToVectorItems(const std::vector& node_key, + static StatusOr> DecodeNodesToVectorItems(engine::Context& ctx, + const std::vector& node_key, uint16_t level, const SearchKey& search_key, - engine::Storage* storage, const HnswVectorFieldMetadata* metadata); uint16_t RandomizeLayer(); - StatusOr DefaultEntryPoint(uint16_t level) const; + StatusOr DefaultEntryPoint(engine::Context& ctx, uint16_t level) const; Status AddEdge(const NodeKey& node_key1, const NodeKey& node_key2, uint16_t layer, ObserverOrUniquePtr& batch) const; Status RemoveEdge(const NodeKey& node_key1, const NodeKey& node_key2, uint16_t layer, @@ -107,20 +107,23 @@ struct HnswIndex { StatusOr> SelectNeighbors(const VectorItem& vec, const std::vector& vectors, uint16_t layer) const; - StatusOr> SearchLayerInternal(uint16_t level, const VectorItem& target_vector, + StatusOr> SearchLayerInternal(engine::Context& ctx, uint16_t level, + const VectorItem& target_vector, uint32_t ef_runtime, const std::vector& entry_points) const; - StatusOr> SearchLayer(uint16_t level, const VectorItem& target_vector, uint32_t ef_runtime, - const std::vector& entry_points) const; - Status InsertVectorEntryInternal(std::string_view key, const kqir::NumericArray& vector, + StatusOr> SearchLayer(engine::Context& ctx, uint16_t level, const VectorItem& target_vector, + uint32_t ef_runtime, const std::vector& entry_points) const; + Status InsertVectorEntryInternal(engine::Context& ctx, std::string_view key, const kqir::NumericArray& vector, ObserverOrUniquePtr& batch, uint16_t layer) const; - Status InsertVectorEntry(std::string_view key, const kqir::NumericArray& vector, + Status InsertVectorEntry(engine::Context& ctx, std::string_view key, const kqir::NumericArray& vector, ObserverOrUniquePtr& batch); - Status DeleteVectorEntry(std::string_view key, ObserverOrUniquePtr& batch) const; - StatusOr> KnnSearch(const kqir::NumericArray& query_vector, uint32_t k) const; - StatusOr> ExpandSearchScope(const kqir::NumericArray& query_vector, + Status DeleteVectorEntry(engine::Context& ctx, std::string_view key, + ObserverOrUniquePtr& batch) const; + StatusOr> KnnSearch(engine::Context& ctx, const kqir::NumericArray& query_vector, + uint32_t k) const; + StatusOr> ExpandSearchScope(engine::Context& ctx, const kqir::NumericArray& query_vector, std::vector&& initial_keys, std::unordered_set& visited) const; }; -} // namespace redis +} // namespace redis \ No newline at end of file diff --git a/src/search/index_manager.h b/src/search/index_manager.h index 0f90961f52c..4d5fd033128 100644 --- a/src/search/index_manager.h +++ b/src/search/index_manager.h @@ -47,8 +47,8 @@ struct IndexManager { if (storage->GetConfig()->cluster_enabled) { return Status::OK(); } - - util::UniqueIterator iter(storage, storage->DefaultScanOptions(), ColumnFamilyID::Search); + auto no_txn_ctx = engine::Context::NoTransactionContext(storage); + util::UniqueIterator iter(no_txn_ctx, no_txn_ctx.DefaultScanOptions(), ColumnFamilyID::Search); auto begin = SearchKey{ns, ""}.ConstructIndexMeta(); for (iter->Seek(begin); iter->Valid(); iter->Next()) { @@ -75,8 +75,9 @@ struct IndexManager { auto index_key = SearchKey(ns, index_name.ToStringView()); std::string prefix_value; - if (auto s = storage->Get(storage->DefaultMultiGetOptions(), storage->GetCFHandle(ColumnFamilyID::Search), - index_key.ConstructIndexPrefixes(), &prefix_value); + if (auto s = storage->Get(no_txn_ctx, no_txn_ctx.DefaultMultiGetOptions(), + storage->GetCFHandle(ColumnFamilyID::Search), index_key.ConstructIndexPrefixes(), + &prefix_value); !s.ok()) { return {Status::NotOK, fmt::format("fail to find index prefixes for index {}: {}", index_name, s.ToString())}; } @@ -90,7 +91,7 @@ struct IndexManager { auto info = std::make_unique(index_name.ToString(), metadata, ns); info->prefixes = prefixes; - util::UniqueIterator field_iter(storage, storage->DefaultScanOptions(), ColumnFamilyID::Search); + util::UniqueIterator field_iter(no_txn_ctx, no_txn_ctx.DefaultScanOptions(), ColumnFamilyID::Search); auto field_begin = index_key.ConstructFieldMeta(); for (field_iter->Seek(field_begin); field_iter->Valid(); field_iter->Next()) { @@ -136,7 +137,7 @@ struct IndexManager { return Status::OK(); } - Status Create(std::unique_ptr info) { + Status Create(engine::Context &ctx, std::unique_ptr info) { if (storage->GetConfig()->cluster_enabled) { return {Status::NotOK, "currently index cannot work in cluster mode"}; } @@ -167,7 +168,7 @@ struct IndexManager { batch->Put(cf, field_key.ConstructFieldMeta(), field_val); } - if (auto s = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); !s.ok()) { + if (auto s = storage->Write(ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); !s.ok()) { return {Status::NotOK, fmt::format("failed to write index metadata: {}", s.ToString())}; } @@ -176,7 +177,7 @@ struct IndexManager { index_map.Insert(std::move(info)); for (auto updater : indexer->updater_list) { - GET_OR_RET(updater.Build()); + GET_OR_RET(updater.Build(ctx)); } return Status::OK(); @@ -241,7 +242,8 @@ struct IndexManager { end = index_key.ConstructAllFieldDataEnd(); batch->DeleteRange(cf, begin, end); - if (auto s = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); !s.ok()) { + auto no_txn_ctx = engine::Context::NoTransactionContext(storage); + if (auto s = storage->Write(no_txn_ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); !s.ok()) { return {Status::NotOK, fmt::format("failed to delete index metadata and data: {}", s.ToString())}; } diff --git a/src/search/indexer.cc b/src/search/indexer.cc index 576de07343a..79a614374aa 100644 --- a/src/search/indexer.cc +++ b/src/search/indexer.cc @@ -37,11 +37,13 @@ namespace redis { StatusOr FieldValueRetriever::Create(IndexOnDataType type, std::string_view key, engine::Storage *storage, const std::string &ns) { + engine::Context ctx(storage); if (type == IndexOnDataType::HASH) { Hash db(storage, ns); std::string ns_key = db.AppendNamespacePrefix(key); HashMetadata metadata(false); - auto s = db.GetMetadata(Database::GetOptions{}, ns_key, &metadata); + + auto s = db.GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return {Status::NotOK, s.ToString()}; return FieldValueRetriever(db, metadata, key); } else if (type == IndexOnDataType::JSON) { @@ -49,7 +51,7 @@ StatusOr FieldValueRetriever::Create(IndexOnDataType type, std::string ns_key = db.AppendNamespacePrefix(key); JsonMetadata metadata(false); JsonValue value; - auto s = db.read(ns_key, &metadata, &value); + auto s = db.read(ctx, ns_key, &metadata, &value); if (!s.ok()) return {Status::NotOK, s.ToString()}; return FieldValueRetriever(value); } else { @@ -121,17 +123,14 @@ StatusOr FieldValueRetriever::ParseFromHash(const std::string &valu } } -StatusOr FieldValueRetriever::Retrieve(std::string_view field, const redis::IndexFieldMetadata *type) { +StatusOr FieldValueRetriever::Retrieve(engine::Context &ctx, std::string_view field, + const redis::IndexFieldMetadata *type) { if (std::holds_alternative(db)) { auto &[hash, metadata, key] = std::get(db); std::string ns_key = hash.AppendNamespacePrefix(key); - - LatestSnapShot ss(hash.storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string sub_key = InternalKey(ns_key, field, metadata.version, hash.storage_->IsSlotIdEncoded()).Encode(); std::string value; - auto s = hash.storage_->Get(read_options, sub_key, &value); + auto s = hash.storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (s.IsNotFound()) return {Status::NotFound, s.ToString()}; if (!s.ok()) return {Status::NotOK, s.ToString()}; @@ -151,12 +150,12 @@ StatusOr FieldValueRetriever::Retrieve(std::string_view field, cons } } -StatusOr IndexUpdater::Record(std::string_view key) const { +StatusOr IndexUpdater::Record(engine::Context &ctx, std::string_view key) const { const auto &ns = info->ns; Database db(indexer->storage, ns); RedisType type = kRedisNone; - auto s = db.Type(key, &type); + auto s = db.Type(ctx, key, &type); if (!s.ok()) return {Status::NotOK, s.ToString()}; // key not exist @@ -175,7 +174,7 @@ StatusOr IndexUpdater::Record(std::string_view key) c continue; } - auto s = retriever.Retrieve(field, i.metadata.get()); + auto s = retriever.Retrieve(ctx, field, i.metadata.get()); if (s.Is()) continue; if (!s) return s; @@ -185,8 +184,9 @@ StatusOr IndexUpdater::Record(std::string_view key) c return values; } -Status IndexUpdater::UpdateTagIndex(std::string_view key, const kqir::Value &original, const kqir::Value ¤t, - const SearchKey &search_key, const TagFieldMetadata *tag) const { +Status IndexUpdater::UpdateTagIndex(engine::Context &ctx, std::string_view key, const kqir::Value &original, + const kqir::Value ¤t, const SearchKey &search_key, + const TagFieldMetadata *tag) const { CHECK(original.IsNull() || original.Is()); CHECK(current.IsNull() || current.Is()); auto original_tags = original.IsNull() ? std::vector() : original.Get(); @@ -235,13 +235,14 @@ Status IndexUpdater::UpdateTagIndex(std::string_view key, const kqir::Value &ori batch->Put(cf_handle, index_key, Slice()); } - auto s = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); + auto s = storage->Write(ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); if (!s.ok()) return {Status::NotOK, s.ToString()}; return Status::OK(); } -Status IndexUpdater::UpdateNumericIndex(std::string_view key, const kqir::Value &original, const kqir::Value ¤t, - const SearchKey &search_key, const NumericFieldMetadata *num) const { +Status IndexUpdater::UpdateNumericIndex(engine::Context &ctx, std::string_view key, const kqir::Value &original, + const kqir::Value ¤t, const SearchKey &search_key, + const NumericFieldMetadata *num) const { CHECK(original.IsNull() || original.Is()); CHECK(current.IsNull() || current.Is()); @@ -260,13 +261,12 @@ Status IndexUpdater::UpdateNumericIndex(std::string_view key, const kqir::Value batch->Put(cf_handle, index_key, Slice()); } - - auto s = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); + auto s = storage->Write(ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); if (!s.ok()) return {Status::NotOK, s.ToString()}; return Status::OK(); } -Status IndexUpdater::UpdateHnswVectorIndex(std::string_view key, const kqir::Value &original, +Status IndexUpdater::UpdateHnswVectorIndex(engine::Context &ctx, std::string_view key, const kqir::Value &original, const kqir::Value ¤t, const SearchKey &search_key, HnswVectorFieldMetadata *vector) const { CHECK(original.IsNull() || original.Is()); @@ -277,23 +277,23 @@ Status IndexUpdater::UpdateHnswVectorIndex(std::string_view key, const kqir::Val if (!original.IsNull()) { auto batch = storage->GetWriteBatchBase(); - GET_OR_RET(hnsw.DeleteVectorEntry(key, batch)); - auto s = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); + GET_OR_RET(hnsw.DeleteVectorEntry(ctx, key, batch)); + auto s = storage->Write(ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); if (!s.ok()) return {Status::NotOK, s.ToString()}; } if (!current.IsNull()) { auto batch = storage->GetWriteBatchBase(); - GET_OR_RET(hnsw.InsertVectorEntry(key, current.Get(), batch)); - auto s = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); + GET_OR_RET(hnsw.InsertVectorEntry(ctx, key, current.Get(), batch)); + auto s = storage->Write(ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); if (!s.ok()) return {Status::NotOK, s.ToString()}; } return Status::OK(); } -Status IndexUpdater::UpdateIndex(const std::string &field, std::string_view key, const kqir::Value &original, - const kqir::Value ¤t) const { +Status IndexUpdater::UpdateIndex(engine::Context &ctx, const std::string &field, std::string_view key, + const kqir::Value &original, const kqir::Value ¤t) const { if (original == current) { // the value of this field is unchanged, no need to update return Status::OK(); @@ -307,11 +307,11 @@ Status IndexUpdater::UpdateIndex(const std::string &field, std::string_view key, auto *metadata = iter->second.metadata.get(); SearchKey search_key(info->ns, info->name, field); if (auto tag = dynamic_cast(metadata)) { - GET_OR_RET(UpdateTagIndex(key, original, current, search_key, tag)); + GET_OR_RET(UpdateTagIndex(ctx, key, original, current, search_key, tag)); } else if (auto numeric [[maybe_unused]] = dynamic_cast(metadata)) { - GET_OR_RET(UpdateNumericIndex(key, original, current, search_key, numeric)); + GET_OR_RET(UpdateNumericIndex(ctx, key, original, current, search_key, numeric)); } else if (auto vector = dynamic_cast(metadata)) { - GET_OR_RET(UpdateHnswVectorIndex(key, original, current, search_key, vector)); + GET_OR_RET(UpdateHnswVectorIndex(ctx, key, original, current, search_key, vector)); } else { return {Status::NotOK, "Unexpected field type"}; } @@ -319,8 +319,8 @@ Status IndexUpdater::UpdateIndex(const std::string &field, std::string_view key, return Status::OK(); } -Status IndexUpdater::Update(const FieldValues &original, std::string_view key) const { - auto current = GET_OR_RET(Record(key)); +Status IndexUpdater::Update(engine::Context &ctx, const FieldValues &original, std::string_view key) const { + auto current = GET_OR_RET(Record(ctx, key)); for (const auto &[field, i] : info->fields) { if (i.metadata->noindex) { @@ -336,15 +336,15 @@ Status IndexUpdater::Update(const FieldValues &original, std::string_view key) c current_val = it->second; } - GET_OR_RET(UpdateIndex(field, key, original_val, current_val)); + GET_OR_RET(UpdateIndex(ctx, field, key, original_val, current_val)); } return Status::OK(); } -Status IndexUpdater::Build() const { +Status IndexUpdater::Build(engine::Context &ctx) const { auto storage = indexer->storage; - util::UniqueIterator iter(storage, storage->DefaultScanOptions(), ColumnFamilyID::Metadata); + util::UniqueIterator iter(ctx, ctx.DefaultScanOptions(), ColumnFamilyID::Metadata); for (const auto &prefix : info->prefixes) { auto ns_key = ComposeNamespaceKey(info->ns, prefix, storage->IsSlotIdEncoded()); @@ -355,7 +355,7 @@ Status IndexUpdater::Build() const { auto [_, key] = ExtractNamespaceKey(iter->key(), storage->IsSlotIdEncoded()); - auto s = Update({}, key.ToStringView()); + auto s = Update(ctx, {}, key.ToStringView()); if (s.Is()) continue; if (!s.OK()) return s; } @@ -390,7 +390,8 @@ void GlobalIndexer::Remove(const kqir::IndexInfo *index) { updater_list.end()); } -StatusOr GlobalIndexer::Record(std::string_view key, const std::string &ns) { +StatusOr GlobalIndexer::Record(engine::Context &ctx, std::string_view key, + const std::string &ns) { if (updater_list.empty()) { return Status::NoPrefixMatched; } @@ -398,14 +399,14 @@ StatusOr GlobalIndexer::Record(std::string_view key auto iter = prefix_map.longest_prefix(ComposeNamespaceKey(ns, key, false)); if (iter != prefix_map.end()) { auto updater = iter.value(); - return RecordResult{updater, std::string(key.begin(), key.end()), GET_OR_RET(updater.Record(key))}; + return RecordResult{updater, std::string(key.begin(), key.end()), GET_OR_RET(updater.Record(ctx, key))}; } return {Status::NoPrefixMatched}; } -Status GlobalIndexer::Update(const RecordResult &original) { - return original.updater.Update(original.fields, original.key); +Status GlobalIndexer::Update(engine::Context &ctx, const RecordResult &original) { + return original.updater.Update(ctx, original.fields, original.key); } } // namespace redis diff --git a/src/search/indexer.h b/src/search/indexer.h index e5e0aa4fb50..20819a2f279 100644 --- a/src/search/indexer.h +++ b/src/search/indexer.h @@ -64,7 +64,7 @@ struct FieldValueRetriever { explicit FieldValueRetriever(JsonValue json) : db(std::in_place_type, std::move(json)) {} - StatusOr Retrieve(std::string_view field, const redis::IndexFieldMetadata *type); + StatusOr Retrieve(engine::Context &ctx, std::string_view field, const redis::IndexFieldMetadata *type); static StatusOr ParseFromJson(const jsoncons::json &value, const redis::IndexFieldMetadata *type); static StatusOr ParseFromHash(const std::string &value, const redis::IndexFieldMetadata *type); @@ -78,19 +78,21 @@ struct IndexUpdater { explicit IndexUpdater(const kqir::IndexInfo *info) : info(info) {} - StatusOr Record(std::string_view key) const; - Status UpdateIndex(const std::string &field, std::string_view key, const kqir::Value &original, + StatusOr Record(engine::Context &ctx, std::string_view key) const; + Status UpdateIndex(engine::Context &ctx, const std::string &field, std::string_view key, const kqir::Value &original, const kqir::Value ¤t) const; - Status Update(const FieldValues &original, std::string_view key) const; - - Status Build() const; - - Status UpdateTagIndex(std::string_view key, const kqir::Value &original, const kqir::Value ¤t, - const SearchKey &search_key, const TagFieldMetadata *tag) const; - Status UpdateNumericIndex(std::string_view key, const kqir::Value &original, const kqir::Value ¤t, - const SearchKey &search_key, const NumericFieldMetadata *num) const; - Status UpdateHnswVectorIndex(std::string_view key, const kqir::Value &original, const kqir::Value ¤t, - const SearchKey &search_key, HnswVectorFieldMetadata *vector) const; + Status Update(engine::Context &ctx, const FieldValues &original, std::string_view key) const; + + Status Build(engine::Context &ctx) const; + + Status UpdateTagIndex(engine::Context &ctx, std::string_view key, const kqir::Value &original, + const kqir::Value ¤t, const SearchKey &search_key, const TagFieldMetadata *tag) const; + Status UpdateNumericIndex(engine::Context &ctx, std::string_view key, const kqir::Value &original, + const kqir::Value ¤t, const SearchKey &search_key, + const NumericFieldMetadata *num) const; + Status UpdateHnswVectorIndex(engine::Context &ctx, std::string_view key, const kqir::Value &original, + const kqir::Value ¤t, const SearchKey &search_key, + HnswVectorFieldMetadata *vector) const; }; struct GlobalIndexer { @@ -111,8 +113,8 @@ struct GlobalIndexer { void Add(IndexUpdater updater); void Remove(const kqir::IndexInfo *index); - StatusOr Record(std::string_view key, const std::string &ns); - static Status Update(const RecordResult &original); + StatusOr Record(engine::Context &ctx, std::string_view key, const std::string &ns); + static Status Update(engine::Context &ctx, const RecordResult &original); }; } // namespace redis diff --git a/src/search/plan_executor.cc b/src/search/plan_executor.cc index 59fcd416420..1682fa5ca16 100644 --- a/src/search/plan_executor.cc +++ b/src/search/plan_executor.cc @@ -150,17 +150,19 @@ struct ExecutorContextVisitor { } // namespace details -ExecutorContext::ExecutorContext(PlanOperator *op) : root(op) { +ExecutorContext::ExecutorContext(PlanOperator *op) : root(op), db_ctx(engine::Context::NoTransactionContext(nullptr)) { details::ExecutorContextVisitor visitor{this}; visitor.Transform(root); } -ExecutorContext::ExecutorContext(PlanOperator *op, engine::Storage *storage) : root(op), storage(storage) { +ExecutorContext::ExecutorContext(PlanOperator *op, engine::Storage *storage) + : root(op), storage(storage), db_ctx(storage) { details::ExecutorContextVisitor visitor{this}; visitor.Transform(root); } -auto ExecutorContext::Retrieve(RowType &row, const FieldInfo *field) -> StatusOr { // NOLINT +auto ExecutorContext::Retrieve(engine::Context &ctx, RowType &row, const FieldInfo *field) const + -> StatusOr { // NOLINT if (auto iter = row.fields.find(field); iter != row.fields.end()) { return iter->second; } @@ -168,7 +170,7 @@ auto ExecutorContext::Retrieve(RowType &row, const FieldInfo *field) -> StatusOr auto retriever = GET_OR_RET( redis::FieldValueRetriever::Create(field->index->metadata.on_data_type, row.key, storage, field->index->ns)); - auto s = retriever.Retrieve(field->name, field->metadata.get()); + auto s = retriever.Retrieve(ctx, field->name, field->metadata.get()); if (!s) return s; row.fields.emplace(field, *s); diff --git a/src/search/plan_executor.h b/src/search/plan_executor.h index 0ead68701d2..58245c62d28 100644 --- a/src/search/plan_executor.h +++ b/src/search/plan_executor.h @@ -77,6 +77,7 @@ struct ExecutorContext { std::map> nodes; PlanOperator *root; engine::Storage *storage; + engine::Context db_ctx; using Result = ExecutorNode::Result; using RowType = ExecutorNode::RowType; @@ -97,7 +98,7 @@ struct ExecutorContext { ExecutorNode *Get(const std::unique_ptr &op) { return Get(op.get()); } StatusOr Next() { return Get(root)->Next(); } - StatusOr Retrieve(RowType &row, const FieldInfo *field); + StatusOr Retrieve(engine::Context &ctx, RowType &row, const FieldInfo *field) const; }; } // namespace kqir diff --git a/src/server/namespace.cc b/src/server/namespace.cc index 31b169ed200..e10c08dc29b 100644 --- a/src/server/namespace.cc +++ b/src/server/namespace.cc @@ -53,7 +53,8 @@ bool Namespace::IsAllowModify() const { Status Namespace::loadFromDB(std::map* db_tokens) const { std::string value; - auto s = storage_->Get(rocksdb::ReadOptions(), cf_, kNamespaceDBKey, &value); + engine::Context ctx(storage_); + auto s = storage_->Get(ctx, ctx.GetReadOptions(), cf_, kNamespaceDBKey, &value); if (!s.ok()) { if (s.IsNotFound()) return Status::OK(); return {Status::NotOK, s.ToString()}; @@ -219,5 +220,6 @@ Status Namespace::Rewrite(const std::map& tokens) cons for (const auto& iter : tokens) { json[iter.first] = iter.second; } - return storage_->WriteToPropagateCF(kNamespaceDBKey, json.to_string()); + engine::Context ctx(storage_); + return storage_->WriteToPropagateCF(ctx, kNamespaceDBKey, json.to_string()); } diff --git a/src/server/redis_connection.cc b/src/server/redis_connection.cc index 5db4c0ee563..09f53b8b3cd 100644 --- a/src/server/redis_connection.cc +++ b/src/server/redis_connection.cc @@ -497,6 +497,7 @@ void Connection::ExecuteCommands(std::deque *to_process_cmds) { continue; } + auto no_txn_ctx = engine::Context::NoTransactionContext(srv_->storage); // TODO: transaction support for index recording std::vector index_records; if (!srv_->index_mgr.index_map.empty() && IsCmdForIndexing(attributes) && !config->cluster_enabled) { @@ -504,7 +505,7 @@ void Connection::ExecuteCommands(std::deque *to_process_cmds) { [&, this](const std::vector &args, const CommandKeyRange &key_range) { key_range.ForEachKey( [&, this](const std::string &key) { - auto res = srv_->indexer.Record(key, ns_); + auto res = srv_->indexer.Record(no_txn_ctx, key, ns_); if (res.IsOK()) { index_records.push_back(*res); } else if (!res.Is() && !res.Is()) { @@ -521,7 +522,7 @@ void Connection::ExecuteCommands(std::deque *to_process_cmds) { // TODO: transaction support for index updating for (const auto &record : index_records) { - auto s = GlobalIndexer::Update(record); + auto s = GlobalIndexer::Update(no_txn_ctx, record); if (!s.IsOK() && !s.Is()) { LOG(WARNING) << "index updating failed for key: " << record.key; } diff --git a/src/server/server.cc b/src/server/server.cc index 7e4c4f2dafa..3381ffbc7ed 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -150,7 +150,8 @@ Status Server::Start() { if (!s.IsOK()) return s; } else { // Generate new replication id if not a replica - s = storage->ShiftReplId(); + engine::Context ctx(storage); + s = storage->ShiftReplId(ctx); if (!s.IsOK()) { return s.Prefixed("failed to shift replication id"); } @@ -308,7 +309,8 @@ Status Server::RemoveMaster() { replication_thread_->Stop(); replication_thread_ = nullptr; } - return storage->ShiftReplId(); + engine::Context ctx(storage); + return storage->ShiftReplId(ctx); } return Status::OK(); } @@ -1447,7 +1449,8 @@ Status Server::AsyncScanDBSize(const std::string &ns) { redis::Database db(storage, ns); KeyNumStats stats; - auto s = db.GetKeyNumStats("", &stats); + engine::Context ctx(storage); + auto s = db.GetKeyNumStats(ctx, "", &stats); if (!s.ok()) { LOG(ERROR) << "failed to retrieve key num stats: " << s.ToString(); } @@ -1700,7 +1703,8 @@ Status Server::ScriptExists(const std::string &sha) { Status Server::ScriptGet(const std::string &sha, std::string *body) const { std::string func_name = engine::kLuaFuncSHAPrefix + sha; auto cf = storage->GetCFHandle(ColumnFamilyID::Propagate); - auto s = storage->Get(rocksdb::ReadOptions(), cf, func_name, body); + engine::Context ctx(storage); + auto s = storage->Get(ctx, ctx.GetReadOptions(), cf, func_name, body); if (!s.ok()) { return {s.IsNotFound() ? Status::NotFound : Status::NotOK, s.ToString()}; } @@ -1709,13 +1713,15 @@ Status Server::ScriptGet(const std::string &sha, std::string *body) const { Status Server::ScriptSet(const std::string &sha, const std::string &body) const { std::string func_name = engine::kLuaFuncSHAPrefix + sha; - return storage->WriteToPropagateCF(func_name, body); + engine::Context ctx(storage); + return storage->WriteToPropagateCF(ctx, func_name, body); } Status Server::FunctionGetCode(const std::string &lib, std::string *code) const { std::string func_name = engine::kLuaLibCodePrefix + lib; auto cf = storage->GetCFHandle(ColumnFamilyID::Propagate); - auto s = storage->Get(rocksdb::ReadOptions(), cf, func_name, code); + engine::Context ctx(storage); + auto s = storage->Get(ctx, ctx.GetReadOptions(), cf, func_name, code); if (!s.ok()) { return {s.IsNotFound() ? Status::NotFound : Status::NotOK, s.ToString()}; } @@ -1725,7 +1731,8 @@ Status Server::FunctionGetCode(const std::string &lib, std::string *code) const Status Server::FunctionGetLib(const std::string &func, std::string *lib) const { std::string func_name = engine::kLuaFuncLibPrefix + func; auto cf = storage->GetCFHandle(ColumnFamilyID::Propagate); - auto s = storage->Get(rocksdb::ReadOptions(), cf, func_name, lib); + engine::Context ctx(storage); + auto s = storage->Get(ctx, ctx.GetReadOptions(), cf, func_name, lib); if (!s.ok()) { return {s.IsNotFound() ? Status::NotFound : Status::NotOK, s.ToString()}; } @@ -1734,12 +1741,14 @@ Status Server::FunctionGetLib(const std::string &func, std::string *lib) const { Status Server::FunctionSetCode(const std::string &lib, const std::string &code) const { std::string func_name = engine::kLuaLibCodePrefix + lib; - return storage->WriteToPropagateCF(func_name, code); + engine::Context ctx(storage); + return storage->WriteToPropagateCF(ctx, func_name, code); } Status Server::FunctionSetLib(const std::string &func, const std::string &lib) const { std::string func_name = engine::kLuaFuncLibPrefix + func; - return storage->WriteToPropagateCF(func_name, lib); + engine::Context ctx(storage); + return storage->WriteToPropagateCF(ctx, func_name, lib); } void Server::ScriptReset() { @@ -1749,7 +1758,8 @@ void Server::ScriptReset() { Status Server::ScriptFlush() { auto cf = storage->GetCFHandle(ColumnFamilyID::Propagate); - auto s = storage->FlushScripts(storage->DefaultWriteOptions(), cf); + engine::Context ctx(storage); + auto s = storage->FlushScripts(ctx, storage->DefaultWriteOptions(), cf); if (!s.ok()) return {Status::NotOK, s.ToString()}; ScriptReset(); return Status::OK(); @@ -1765,7 +1775,8 @@ Status Server::Propagate(const std::string &channel, const std::vectorWriteToPropagateCF(channel, value); + engine::Context ctx(storage); + return storage->WriteToPropagateCF(ctx, channel, value); } Status Server::ExecPropagateScriptCommand(const std::vector &tokens) { diff --git a/src/stats/disk_stats.cc b/src/stats/disk_stats.cc index 8c7f98ddfa2..330a8a7778d 100644 --- a/src/stats/disk_stats.cc +++ b/src/stats/disk_stats.cc @@ -44,26 +44,26 @@ rocksdb::Status Disk::GetApproximateSizes(const Metadata &metadata, const Slice return rocksdb::Status::OK(); } -rocksdb::Status Disk::GetKeySize(const Slice &user_key, RedisType type, uint64_t *key_size) { +rocksdb::Status Disk::GetKeySize(engine::Context &ctx, const Slice &user_key, RedisType type, uint64_t *key_size) { *key_size = 0; std::string ns_key = AppendNamespacePrefix(user_key); switch (type) { case RedisType::kRedisString: return GetStringSize(ns_key, key_size); case RedisType::kRedisHash: - return GetHashSize(ns_key, key_size); + return GetHashSize(ctx, ns_key, key_size); case RedisType::kRedisBitmap: - return GetBitmapSize(ns_key, key_size); + return GetBitmapSize(ctx, ns_key, key_size); case RedisType::kRedisList: - return GetListSize(ns_key, key_size); + return GetListSize(ctx, ns_key, key_size); case RedisType::kRedisSet: - return GetSetSize(ns_key, key_size); + return GetSetSize(ctx, ns_key, key_size); case RedisType::kRedisSortedint: - return GetSortedintSize(ns_key, key_size); + return GetSortedintSize(ctx, ns_key, key_size); case RedisType::kRedisZSet: - return GetZsetSize(ns_key, key_size); + return GetZsetSize(ctx, ns_key, key_size); case RedisType::kRedisStream: - return GetStreamSize(ns_key, key_size); + return GetStreamSize(ctx, ns_key, key_size); default: return rocksdb::Status::NotFound("Not found ", user_key); } @@ -75,32 +75,32 @@ rocksdb::Status Disk::GetStringSize(const Slice &ns_key, uint64_t *key_size) { return storage_->GetDB()->GetApproximateSizes(option_, metadata_cf_handle_, &key_range, 1, key_size); } -rocksdb::Status Disk::GetHashSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetHashSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { HashMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisHash}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisHash}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; return GetApproximateSizes(metadata, ns_key, storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), key_size); } -rocksdb::Status Disk::GetSetSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetSetSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { SetMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisSet}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisSet}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; return GetApproximateSizes(metadata, ns_key, storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), key_size); } -rocksdb::Status Disk::GetListSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetListSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { ListMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisList}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisList}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string buf; PutFixed64(&buf, metadata.head); return GetApproximateSizes(metadata, ns_key, storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), key_size, buf); } -rocksdb::Status Disk::GetZsetSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetZsetSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { ZSetMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisZSet}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisZSet}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string score_bytes; PutDouble(&score_bytes, kMinScore); @@ -110,17 +110,17 @@ rocksdb::Status Disk::GetZsetSize(const Slice &ns_key, uint64_t *key_size) { return GetApproximateSizes(metadata, ns_key, storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), key_size); } -rocksdb::Status Disk::GetBitmapSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetBitmapSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { BitmapMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisBitmap}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisBitmap}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; return GetApproximateSizes(metadata, ns_key, storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), key_size, std::to_string(0), std::to_string(0)); } -rocksdb::Status Disk::GetSortedintSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetSortedintSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { SortedintMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisSortedint}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisSortedint}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string start_buf; PutFixed64(&start_buf, 0); @@ -128,9 +128,9 @@ rocksdb::Status Disk::GetSortedintSize(const Slice &ns_key, uint64_t *key_size) start_buf, start_buf); } -rocksdb::Status Disk::GetStreamSize(const Slice &ns_key, uint64_t *key_size) { +rocksdb::Status Disk::GetStreamSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size) { StreamMetadata metadata(false); - rocksdb::Status s = Database::GetMetadata(Database::GetOptions{}, {kRedisStream}, ns_key, &metadata); + rocksdb::Status s = Database::GetMetadata(ctx, {kRedisStream}, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; return GetApproximateSizes(metadata, ns_key, storage_->GetCFHandle(ColumnFamilyID::Stream), key_size); } diff --git a/src/stats/disk_stats.h b/src/stats/disk_stats.h index c11776ed0f8..d5733c2fd40 100644 --- a/src/stats/disk_stats.h +++ b/src/stats/disk_stats.h @@ -37,14 +37,14 @@ class Disk : public Database { rocksdb::ColumnFamilyHandle *column_family, uint64_t *key_size, Slice subkeyleft = Slice(), Slice subkeyright = Slice()); rocksdb::Status GetStringSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetHashSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetSetSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetListSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetZsetSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetBitmapSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetSortedintSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetStreamSize(const Slice &ns_key, uint64_t *key_size); - rocksdb::Status GetKeySize(const Slice &user_key, RedisType type, uint64_t *key_size); + rocksdb::Status GetHashSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetSetSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetListSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetZsetSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetBitmapSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetSortedintSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetStreamSize(engine::Context &ctx, const Slice &ns_key, uint64_t *key_size); + rocksdb::Status GetKeySize(engine::Context &ctx, const Slice &user_key, RedisType type, uint64_t *key_size); private: rocksdb::SizeApproximationOptions option_; diff --git a/src/storage/batch_indexer.h b/src/storage/batch_indexer.h new file mode 100644 index 00000000000..ceba8bed908 --- /dev/null +++ b/src/storage/batch_indexer.h @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include "storage.h" + +// WriteBatchIndexer traverses the operations in WriteBatch and appends to the specified WriteBatchWithIndex +class WriteBatchIndexer : public rocksdb::WriteBatch::Handler { + public: + explicit WriteBatchIndexer(engine::Storage* storage, rocksdb::WriteBatchWithIndex* dest_batch, + const rocksdb::Snapshot* snapshot) + : storage_(storage), dest_batch_(dest_batch), snapshot_(snapshot) { + DCHECK_NOTNULL(storage); + DCHECK_NOTNULL(dest_batch); + DCHECK_NOTNULL(snapshot); + } + explicit WriteBatchIndexer(engine::Context& ctx) : WriteBatchIndexer(ctx.storage, ctx.batch.get(), ctx.snapshot) {} + rocksdb::Status PutCF(uint32_t column_family_id, const rocksdb::Slice& key, const rocksdb::Slice& value) override { + return dest_batch_->Put(storage_->GetCFHandle(static_cast(column_family_id)), key, value); + } + + void Put(const rocksdb::Slice& key, const rocksdb::Slice& value) override { dest_batch_->Put(key, value); } + + rocksdb::Status DeleteCF(uint32_t column_family_id, const rocksdb::Slice& key) override { + return dest_batch_->Delete(storage_->GetCFHandle(static_cast(column_family_id)), key); + } + + void Delete(const rocksdb::Slice& key) override { dest_batch_->Delete(key); } + + rocksdb::Status SingleDeleteCF(uint32_t column_family_id, const rocksdb::Slice& key) override { + return dest_batch_->SingleDelete(storage_->GetCFHandle(static_cast(column_family_id)), key); + } + + void SingleDelete(const rocksdb::Slice& key) override { dest_batch_->SingleDelete(key); } + + rocksdb::Status DeleteRangeCF(uint32_t column_family_id, const rocksdb::Slice& begin_key, + const rocksdb::Slice& end_key) override { + rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); + read_options.iterate_lower_bound = &begin_key; + read_options.iterate_upper_bound = &end_key; + read_options.snapshot = snapshot_; + + auto cf_handle = storage_->GetCFHandle(static_cast(column_family_id)); + + auto iter = storage_->GetDB()->NewIterator(read_options, cf_handle); + std::unique_ptr it(dest_batch_->NewIteratorWithBase(cf_handle, iter, &read_options)); + for (it->Seek(begin_key); it->Valid() && it->key().compare(end_key) < 0; it->Next()) { + auto s = dest_batch_->Delete(cf_handle, it->key()); + if (!s.ok()) { + return s; + } + } + return rocksdb::Status::OK(); + } + + rocksdb::Status MergeCF(uint32_t column_family_id, const rocksdb::Slice& key, const rocksdb::Slice& value) override { + return dest_batch_->Merge(storage_->GetCFHandle(static_cast(column_family_id)), key, value); + } + + void Merge(const rocksdb::Slice& key, const rocksdb::Slice& value) override { dest_batch_->Merge(key, value); } + + void LogData(const rocksdb::Slice& blob) override { dest_batch_->PutLogData(blob); } + + private: + engine::Storage* storage_; + rocksdb::WriteBatchWithIndex* dest_batch_; + const rocksdb::Snapshot* snapshot_; +}; diff --git a/src/storage/iterator.cc b/src/storage/iterator.cc index e368c6792c0..e360ffe0c2d 100644 --- a/src/storage/iterator.cc +++ b/src/storage/iterator.cc @@ -25,12 +25,13 @@ #include "db_util.h" namespace engine { -DBIterator::DBIterator(Storage *storage, rocksdb::ReadOptions read_options, int slot) - : storage_(storage), +DBIterator::DBIterator(engine::Context &ctx, rocksdb::ReadOptions read_options, int slot) + : storage_(ctx.storage), read_options_(std::move(read_options)), + ctx_(&ctx), slot_(slot), metadata_cf_handle_(storage_->GetCFHandle(ColumnFamilyID::Metadata)) { - metadata_iter_ = util::UniqueIterator(storage_->NewIterator(read_options_, metadata_cf_handle_)); + metadata_iter_ = util::UniqueIterator(storage_->NewIterator(ctx, read_options_, metadata_cf_handle_)); } void DBIterator::Next() { @@ -110,18 +111,19 @@ std::unique_ptr DBIterator::GetSubKeyIterator() const { return nullptr; } - auto prefix = InternalKey(Key(), "", metadata_.version, storage_->IsSlotIdEncoded()).Encode(); - return std::make_unique(storage_, read_options_, type, std::move(prefix)); + auto prefix = InternalKey(Key(), "", metadata_.version, ctx_->storage->IsSlotIdEncoded()).Encode(); + return std::make_unique(*ctx_, read_options_, type, std::move(prefix)); } -SubKeyIterator::SubKeyIterator(Storage *storage, rocksdb::ReadOptions read_options, RedisType type, std::string prefix) - : storage_(storage), read_options_(std::move(read_options)), type_(type), prefix_(std::move(prefix)) { +SubKeyIterator::SubKeyIterator(engine::Context &ctx, rocksdb::ReadOptions read_options, RedisType type, + std::string prefix) + : storage_(ctx.storage), read_options_(std::move(read_options)), type_(type), prefix_(std::move(prefix)) { if (type_ == kRedisStream) { cf_handle_ = storage_->GetCFHandle(ColumnFamilyID::Stream); } else { cf_handle_ = storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey); } - iter_ = util::UniqueIterator(storage_->NewIterator(read_options_, cf_handle_)); + iter_ = util::UniqueIterator(storage_->NewIterator(ctx, read_options_, cf_handle_)); } void SubKeyIterator::Next() { diff --git a/src/storage/iterator.h b/src/storage/iterator.h index 34f96f6fff1..4468f7ebd11 100644 --- a/src/storage/iterator.h +++ b/src/storage/iterator.h @@ -29,7 +29,7 @@ namespace engine { class SubKeyIterator { public: - explicit SubKeyIterator(Storage *storage, rocksdb::ReadOptions read_options, RedisType type, std::string prefix); + explicit SubKeyIterator(engine::Context &ctx, rocksdb::ReadOptions read_options, RedisType type, std::string prefix); ~SubKeyIterator() = default; bool Valid() const; void Seek(); @@ -53,7 +53,7 @@ class SubKeyIterator { class DBIterator { public: - explicit DBIterator(Storage *storage, rocksdb::ReadOptions read_options, int slot = -1); + explicit DBIterator(engine::Context &ctx, rocksdb::ReadOptions read_options, int slot = -1); ~DBIterator() = default; bool Valid() const; @@ -73,6 +73,7 @@ class DBIterator { Storage *storage_; rocksdb::ReadOptions read_options_; + Context *ctx_; int slot_ = -1; Metadata metadata_ = Metadata(kRedisNone, false); diff --git a/src/storage/rdb.cc b/src/storage/rdb.cc index 31c56f00159..2d684f10ab6 100644 --- a/src/storage/rdb.cc +++ b/src/storage/rdb.cc @@ -383,7 +383,7 @@ StatusOr> RDB::LoadZSetWithZipList() { return zset; } -Status RDB::Restore(const std::string &key, std::string_view payload, uint64_t ttl_ms) { +Status RDB::Restore(engine::Context &ctx, const std::string &key, std::string_view payload, uint64_t ttl_ms) { rocksdb::Status db_status; // Check the checksum of the payload @@ -393,7 +393,7 @@ Status RDB::Restore(const std::string &key, std::string_view payload, uint64_t t auto value = GET_OR_RET(loadRdbObject(type, key)); - return saveRdbObject(type, key, value, ttl_ms); // NOLINT + return saveRdbObject(ctx, type, key, value, ttl_ms); // NOLINT } StatusOr RDB::loadRdbType() { @@ -454,7 +454,8 @@ StatusOr RDB::loadRdbObject(int type, const std::string &key) { return {Status::RedisParseErr, fmt::format("unsupported type: {}", type)}; } -Status RDB::saveRdbObject(int type, const std::string &key, const RedisObjValue &obj, uint64_t ttl_ms) { +Status RDB::saveRdbObject(engine::Context &ctx, int type, const std::string &key, const RedisObjValue &obj, + uint64_t ttl_ms) { rocksdb::Status db_status; if (type == RDBTypeString) { const auto &value = std::get(obj); @@ -463,7 +464,7 @@ Status RDB::saveRdbObject(int type, const std::string &key, const RedisObjValue if (ttl_ms > 0) { expire_ms = ttl_ms + util::GetTimeStampMS(); } - db_status = string_db.SetEX(key, value, expire_ms); + db_status = string_db.SetEX(ctx, key, value, expire_ms); } else if (type == RDBTypeSet || type == RDBTypeSetIntSet || type == RDBTypeSetListPack) { const auto &members = std::get>(obj); redis::Set set_db(storage_, ns_); @@ -473,12 +474,12 @@ Status RDB::saveRdbObject(int type, const std::string &key, const RedisObjValue for (const auto &member : members) { insert_members.emplace_back(member); } - db_status = set_db.Add(key, insert_members, &count); + db_status = set_db.Add(ctx, key, insert_members, &count); } else if (type == RDBTypeZSet || type == RDBTypeZSet2 || type == RDBTypeZSetListPack || type == RDBTypeZSetZipList) { const auto &member_scores = std::get>(obj); redis::ZSet zset_db(storage_, ns_); uint64_t count = 0; - db_status = zset_db.Add(key, ZAddFlags(0), const_cast *>(&member_scores), &count); + db_status = zset_db.Add(ctx, key, ZAddFlags(0), const_cast *>(&member_scores), &count); } else if (type == RDBTypeHash || type == RDBTypeHashListPack || type == RDBTypeHashZipList || type == RDBTypeHashZipMap) { const auto &entries = std::get>(obj); @@ -489,7 +490,7 @@ Status RDB::saveRdbObject(int type, const std::string &key, const RedisObjValue } redis::Hash hash_db(storage_, ns_); uint64_t count = 0; - db_status = hash_db.MSet(key, filed_values, false /*nx*/, &count); + db_status = hash_db.MSet(ctx, key, filed_values, false /*nx*/, &count); } else if (type == RDBTypeList || type == RDBTypeListZipList || type == RDBTypeListQuickList || type == RDBTypeListQuickList2) { const auto &elements = std::get>(obj); @@ -501,7 +502,7 @@ Status RDB::saveRdbObject(int type, const std::string &key, const RedisObjValue } redis::List list_db(storage_, ns_); uint64_t list_size = 0; - db_status = list_db.Push(key, insert_elements, false, &list_size); + db_status = list_db.Push(ctx, key, insert_elements, false, &list_size); } } else { return {Status::RedisExecErr, fmt::format("unsupported save type: {}", type)}; @@ -512,7 +513,7 @@ Status RDB::saveRdbObject(int type, const std::string &key, const RedisObjValue // String type will use the SETEX, so just only set the ttl for other types if (ttl_ms > 0 && type != RDBTypeString) { redis::Database db(storage_, ns_); - db_status = db.Expire(key, ttl_ms + util::GetTimeStampMS()); + db_status = db.Expire(ctx, key, ttl_ms + util::GetTimeStampMS()); } return db_status.ok() ? Status::OK() : Status{Status::RedisExecErr, db_status.ToString()}; } @@ -551,7 +552,7 @@ bool RDB::isEmptyRedisObject(const RedisObjValue &value) { } // Load RDB file: copy from redis/src/rdb.c:branch 7.0, 76b9c13d. -Status RDB::LoadRdb(uint32_t db_index, bool overwrite_exist_key) { +Status RDB::LoadRdb(engine::Context &ctx, uint32_t db_index, bool overwrite_exist_key) { char buf[1024] = {0}; GET_OR_RET(LogWhenError(stream_->Read(buf, 9))); buf[9] = '\0'; @@ -644,7 +645,7 @@ Status RDB::LoadRdb(uint32_t db_index, bool overwrite_exist_key) { if (!overwrite_exist_key) { // only load not exist key redis::Database redis(storage_, ns_); - auto s = redis.KeyExist(key); + auto s = redis.KeyExist(ctx, key); if (!s.IsNotFound()) { skip_exist_keys++; // skip it even it's not okay if (!s.ok()) { @@ -654,7 +655,7 @@ Status RDB::LoadRdb(uint32_t db_index, bool overwrite_exist_key) { } } - auto ret = saveRdbObject(type, key, value, expire_time_ms); + auto ret = saveRdbObject(ctx, type, key, value, expire_time_ms); if (!ret.IsOK()) { LOG(WARNING) << "save rdb object key " << key << " failed: " << ret.Msg(); } else { @@ -735,10 +736,11 @@ Status RDB::SaveObjectType(const RedisType type) { } Status RDB::SaveObject(const std::string &key, const RedisType type) { + engine::Context ctx(storage_); if (type == kRedisString) { std::string value; redis::String string_db(storage_, ns_); - auto s = string_db.Get(key, &value); + auto s = string_db.Get(ctx, key, &value); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -746,7 +748,7 @@ Status RDB::SaveObject(const std::string &key, const RedisType type) { } else if (type == kRedisList) { std::vector elems; redis::List list_db(storage_, ns_); - auto s = list_db.Range(key, 0, -1, &elems); + auto s = list_db.Range(ctx, key, 0, -1, &elems); if (!s.ok() && !s.IsNotFound()) { return {Status::RedisExecErr, s.ToString()}; } @@ -754,7 +756,7 @@ Status RDB::SaveObject(const std::string &key, const RedisType type) { } else if (type == kRedisSet) { redis::Set set_db(storage_, ns_); std::vector members; - auto s = set_db.Members(key, &members); + auto s = set_db.Members(ctx, key, &members); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -763,7 +765,7 @@ Status RDB::SaveObject(const std::string &key, const RedisType type) { redis::ZSet zset_db(storage_, ns_); std::vector member_scores; RangeScoreSpec spec; - auto s = zset_db.RangeByScore(key, spec, &member_scores, nullptr); + auto s = zset_db.RangeByScore(ctx, key, spec, &member_scores, nullptr); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } @@ -773,7 +775,7 @@ Status RDB::SaveObject(const std::string &key, const RedisType type) { } else if (type == kRedisHash) { redis::Hash hash_db(storage_, ns_); std::vector field_values; - auto s = hash_db.GetAll(key, &field_values); + auto s = hash_db.GetAll(ctx, key, &field_values); if (!s.ok()) { return {Status::RedisExecErr, s.ToString()}; } diff --git a/src/storage/rdb.h b/src/storage/rdb.h index 3a08df84a40..4f8b95dbca7 100644 --- a/src/storage/rdb.h +++ b/src/storage/rdb.h @@ -78,7 +78,7 @@ class RDB { Status VerifyPayloadChecksum(const std::string_view &payload); StatusOr LoadObjectType(); - Status Restore(const std::string &key, std::string_view payload, uint64_t ttl_ms); + Status Restore(engine::Context &ctx, const std::string &key, std::string_view payload, uint64_t ttl_ms); // String StatusOr LoadStringObject(); @@ -105,7 +105,7 @@ class RDB { StatusOr> LoadListWithQuickList(int type); // Load rdb - Status LoadRdb(uint32_t db_index, bool overwrite_exist_key = true); + Status LoadRdb(engine::Context &ctx, uint32_t db_index, bool overwrite_exist_key = true); std::unique_ptr &GetStream() { return stream_; } @@ -143,7 +143,8 @@ class RDB { StatusOr loadRdbType(); StatusOr loadRdbObject(int rdbtype, const std::string &key); - Status saveRdbObject(int type, const std::string &key, const RedisObjValue &obj, uint64_t ttl_ms); + Status saveRdbObject(engine::Context &ctx, int type, const std::string &key, const RedisObjValue &obj, + uint64_t ttl_ms); StatusOr loadExpiredTimeSeconds(); StatusOr loadExpiredTimeMilliseconds(int rdb_version); diff --git a/src/storage/redis_db.cc b/src/storage/redis_db.cc index b8c46458103..9502b70ce92 100644 --- a/src/storage/redis_db.cc +++ b/src/storage/redis_db.cc @@ -90,34 +90,31 @@ rocksdb::Status Database::ParseMetadata(RedisTypes types, Slice *bytes, Metadata return s; } -rocksdb::Status Database::GetMetadata(GetOptions options, RedisTypes types, const Slice &ns_key, Metadata *metadata) { +rocksdb::Status Database::GetMetadata(engine::Context &ctx, RedisTypes types, const Slice &ns_key, Metadata *metadata) { std::string raw_value; Slice rest; - return GetMetadata(options, types, ns_key, &raw_value, metadata, &rest); + return GetMetadata(ctx, types, ns_key, &raw_value, metadata, &rest); } -rocksdb::Status Database::GetMetadata(GetOptions options, RedisTypes types, const Slice &ns_key, std::string *raw_value, - Metadata *metadata, Slice *rest) { - auto s = GetRawMetadata(options, ns_key, raw_value); +rocksdb::Status Database::GetMetadata(engine::Context &ctx, RedisTypes types, const Slice &ns_key, + std::string *raw_value, Metadata *metadata, Slice *rest) { + auto s = GetRawMetadata(ctx, ns_key, raw_value); *rest = *raw_value; if (!s.ok()) return s; return ParseMetadata(types, rest, metadata); } -rocksdb::Status Database::GetRawMetadata(GetOptions options, const Slice &ns_key, std::string *bytes) { - rocksdb::ReadOptions opts; - // If options.snapshot == nullptr, we can avoid allocating a snapshot here. - opts.snapshot = options.snapshot; - return storage_->Get(opts, metadata_cf_handle_, ns_key, bytes); +rocksdb::Status Database::GetRawMetadata(engine::Context &ctx, const Slice &ns_key, std::string *bytes) { + return storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, ns_key, bytes); } -rocksdb::Status Database::Expire(const Slice &user_key, uint64_t timestamp) { +rocksdb::Status Database::Expire(engine::Context &ctx, const Slice &user_key, uint64_t timestamp) { std::string ns_key = AppendNamespacePrefix(user_key); std::string value; Metadata metadata(kRedisNone, false); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = storage_->Get(rocksdb::ReadOptions(), metadata_cf_handle_, ns_key, &value); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, ns_key, &value); if (!s.ok()) return s; s = metadata.Decode(value); @@ -140,16 +137,16 @@ rocksdb::Status Database::Expire(const Slice &user_key, uint64_t timestamp) { WriteBatchLogData log_data(kRedisNone, {std::to_string(kRedisCmdExpire)}); batch->PutLogData(log_data.Encode()); batch->Put(metadata_cf_handle_, ns_key, value); - s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); return s; } -rocksdb::Status Database::Del(const Slice &user_key) { +rocksdb::Status Database::Del(engine::Context &ctx, const Slice &user_key) { std::string ns_key = AppendNamespacePrefix(user_key); std::string value; LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = storage_->Get(rocksdb::ReadOptions(), metadata_cf_handle_, ns_key, &value); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, ns_key, &value); if (!s.ok()) return s; Metadata metadata(kRedisNone, false); s = metadata.Decode(value); @@ -157,10 +154,10 @@ rocksdb::Status Database::Del(const Slice &user_key) { if (metadata.Expired()) { return rocksdb::Status::NotFound(kErrMsgKeyExpired); } - return storage_->Delete(storage_->DefaultWriteOptions(), metadata_cf_handle_, ns_key); + return storage_->Delete(ctx, storage_->DefaultWriteOptions(), metadata_cf_handle_, ns_key); } -rocksdb::Status Database::MDel(const std::vector &keys, uint64_t *deleted_cnt) { +rocksdb::Status Database::MDel(engine::Context &ctx, const std::vector &keys, uint64_t *deleted_cnt) { *deleted_cnt = 0; std::vector lock_keys; @@ -181,13 +178,10 @@ rocksdb::Status Database::MDel(const std::vector &keys, uint64_t *deleted slice_keys.emplace_back(ns_key); } - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions(); - read_options.snapshot = ss.GetSnapShot(); std::vector statuses(slice_keys.size()); std::vector pin_values(slice_keys.size()); - storage_->MultiGet(read_options, metadata_cf_handle_, slice_keys.size(), slice_keys.data(), pin_values.data(), - statuses.data()); + storage_->MultiGet(ctx, ctx.GetReadOptions(), metadata_cf_handle_, slice_keys.size(), slice_keys.data(), + pin_values.data(), statuses.data()); for (size_t i = 0; i < slice_keys.size(); i++) { if (!statuses[i].ok() && !statuses[i].IsNotFound()) return statuses[i]; @@ -206,27 +200,24 @@ rocksdb::Status Database::MDel(const std::vector &keys, uint64_t *deleted if (*deleted_cnt == 0) return rocksdb::Status::OK(); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Database::Exists(const std::vector &keys, int *ret) { +rocksdb::Status Database::Exists(engine::Context &ctx, const std::vector &keys, int *ret) { std::vector ns_keys; ns_keys.reserve(keys.size()); for (const auto &key : keys) { ns_keys.emplace_back(AppendNamespacePrefix(key)); } - return existsInternal(ns_keys, ret); + return existsInternal(ctx, ns_keys, ret); } -rocksdb::Status Database::TTL(const Slice &user_key, int64_t *ttl) { +rocksdb::Status Database::TTL(engine::Context &ctx, const Slice &user_key, int64_t *ttl) { std::string ns_key = AppendNamespacePrefix(user_key); *ttl = -2; // ttl is -2 when the key does not exist or expired - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string value; - rocksdb::Status s = storage_->Get(read_options, metadata_cf_handle_, ns_key, &value); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, ns_key, &value); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; Metadata metadata(kRedisNone, false); @@ -237,21 +228,22 @@ rocksdb::Status Database::TTL(const Slice &user_key, int64_t *ttl) { return rocksdb::Status::OK(); } -rocksdb::Status Database::GetExpireTime(const Slice &user_key, uint64_t *timestamp) { +rocksdb::Status Database::GetExpireTime(engine::Context &ctx, const Slice &user_key, uint64_t *timestamp) { std::string ns_key = AppendNamespacePrefix(user_key); Metadata metadata(kRedisNone, false); - auto s = GetMetadata(GetOptions{}, RedisTypes::All(), ns_key, &metadata); + auto s = GetMetadata(ctx, RedisTypes::All(), ns_key, &metadata); if (!s.ok()) return s; *timestamp = metadata.expire; return rocksdb::Status::OK(); } -rocksdb::Status Database::GetKeyNumStats(const std::string &prefix, KeyNumStats *stats) { - return Keys(prefix, nullptr, stats); +rocksdb::Status Database::GetKeyNumStats(engine::Context &ctx, const std::string &prefix, KeyNumStats *stats) { + return Keys(ctx, prefix, nullptr, stats); } -rocksdb::Status Database::Keys(const std::string &prefix, std::vector *keys, KeyNumStats *stats) { +rocksdb::Status Database::Keys(engine::Context &ctx, const std::string &prefix, std::vector *keys, + KeyNumStats *stats) { uint16_t slot_id = 0; std::string ns_prefix; if (namespace_ != kDefaultNamespace || keys != nullptr) { @@ -267,10 +259,7 @@ rocksdb::Status Database::Keys(const std::string &prefix, std::vectorDefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); - auto iter = util::UniqueIterator(storage_, read_options, metadata_cf_handle_); + auto iter = util::UniqueIterator(ctx, ctx.GetReadOptions(), metadata_cf_handle_); while (true) { ns_prefix.empty() ? iter->SeekToFirst() : iter->Seek(ns_prefix); @@ -319,18 +308,16 @@ rocksdb::Status Database::Keys(const std::string &prefix, std::vector *keys, std::string *end_cursor, RedisType type) { +rocksdb::Status Database::Scan(engine::Context &ctx, const std::string &cursor, uint64_t limit, + const std::string &prefix, std::vector *keys, std::string *end_cursor, + RedisType type) { end_cursor->clear(); uint64_t cnt = 0; uint16_t slot_start = 0; std::string ns_prefix; std::string user_key; - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); - auto iter = util::UniqueIterator(storage_, read_options, metadata_cf_handle_); + auto iter = util::UniqueIterator(ctx, ctx.GetReadOptions(), metadata_cf_handle_); std::string ns_cursor = AppendNamespacePrefix(cursor); if (storage_->IsSlotIdEncoded()) { @@ -418,18 +405,18 @@ rocksdb::Status Database::Scan(const std::string &cursor, uint64_t limit, const return rocksdb::Status::OK(); } -rocksdb::Status Database::RandomKey(const std::string &cursor, std::string *key) { +rocksdb::Status Database::RandomKey(engine::Context &ctx, const std::string &cursor, std::string *key) { key->clear(); std::string end_cursor; std::vector keys; - auto s = Scan(cursor, RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor); + auto s = Scan(ctx, cursor, RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor); if (!s.ok()) { return s; } if (keys.empty() && !cursor.empty()) { // if reach the end, restart from beginning - s = Scan("", RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor); + s = Scan(ctx, "", RANDOM_KEY_SCAN_LIMIT, "", &keys, &end_cursor); if (!s.ok()) { return s; } @@ -441,18 +428,15 @@ rocksdb::Status Database::RandomKey(const std::string &cursor, std::string *key) return rocksdb::Status::OK(); } -rocksdb::Status Database::FlushDB() { +rocksdb::Status Database::FlushDB(engine::Context &ctx) { auto begin_key = ComposeNamespaceKey(namespace_, "", false); auto end_key = util::StringNext(begin_key); - return storage_->DeleteRange(begin_key, end_key); + return storage_->DeleteRange(ctx, begin_key, end_key); } -rocksdb::Status Database::FlushAll() { - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); - auto iter = util::UniqueIterator(storage_, read_options, metadata_cf_handle_); +rocksdb::Status Database::FlushAll(engine::Context &ctx) { + auto iter = util::UniqueIterator(ctx, ctx.GetReadOptions(), metadata_cf_handle_); iter->SeekToFirst(); if (!iter->Valid()) { return rocksdb::Status::OK(); @@ -463,19 +447,16 @@ rocksdb::Status Database::FlushAll() { return rocksdb::Status::OK(); } auto last_key = util::StringNext(iter->key().ToString()); - return storage_->DeleteRange(first_key, last_key); + return storage_->DeleteRange(ctx, first_key, last_key); } -rocksdb::Status Database::Dump(const Slice &user_key, std::vector *infos) { +rocksdb::Status Database::Dump(engine::Context &ctx, const Slice &user_key, std::vector *infos) { infos->clear(); std::string ns_key = AppendNamespacePrefix(user_key); - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string value; - rocksdb::Status s = storage_->Get(read_options, metadata_cf_handle_, ns_key, &value); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, ns_key, &value); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; Metadata metadata(kRedisNone, false); @@ -509,7 +490,7 @@ rocksdb::Status Database::Dump(const Slice &user_key, std::vector * if (metadata.Type() == kRedisList) { ListMetadata list_metadata(false); - s = GetMetadata(GetOptions{}, {kRedisList}, ns_key, &list_metadata); + s = GetMetadata(ctx, {kRedisList}, ns_key, &list_metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; infos->emplace_back("head"); infos->emplace_back(std::to_string(list_metadata.head)); @@ -520,29 +501,30 @@ rocksdb::Status Database::Dump(const Slice &user_key, std::vector * return rocksdb::Status::OK(); } -rocksdb::Status Database::Type(const Slice &key, RedisType *type) { +rocksdb::Status Database::Type(engine::Context &ctx, const Slice &key, RedisType *type) { std::string ns_key = AppendNamespacePrefix(key); - return typeInternal(ns_key, type); + return typeInternal(ctx, ns_key, type); } std::string Database::AppendNamespacePrefix(const Slice &user_key) { return ComposeNamespaceKey(namespace_, user_key, storage_->IsSlotIdEncoded()); } -rocksdb::Status Database::ClearKeysOfSlotRange(const rocksdb::Slice &ns, const SlotRange &slot_range) { +rocksdb::Status Database::ClearKeysOfSlotRange(engine::Context &ctx, const rocksdb::Slice &ns, + const SlotRange &slot_range) { if (!storage_->IsSlotIdEncoded()) { return rocksdb::Status::Aborted("It is not in cluster mode"); } std::string prefix = ComposeSlotKeyPrefix(ns, slot_range.start); std::string prefix_end = ComposeSlotKeyPrefix(ns, slot_range.end + 1); - return storage_->DeleteRange(prefix, prefix_end); + return storage_->DeleteRange(ctx, prefix, prefix_end); } -rocksdb::Status Database::KeyExist(const std::string &key) { +rocksdb::Status Database::KeyExist(engine::Context &ctx, const std::string &key) { int cnt = 0; std::vector keys{key}; - auto s = Exists(keys, &cnt); + auto s = Exists(ctx, keys, &cnt); if (!s.ok()) { return s; } @@ -552,18 +534,16 @@ rocksdb::Status Database::KeyExist(const std::string &key) { return rocksdb::Status::OK(); } -rocksdb::Status SubKeyScanner::Scan(RedisType type, const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &subkey_prefix, std::vector *keys, - std::vector *values) { +rocksdb::Status SubKeyScanner::Scan(engine::Context &ctx, RedisType type, const Slice &user_key, + const std::string &cursor, uint64_t limit, const std::string &subkey_prefix, + std::vector *keys, std::vector *values) { uint64_t cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); Metadata metadata(type, false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, {type}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, {type}, ns_key, &metadata); if (!s.ok()) return s; - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, ctx.DefaultScanOptions()); std::string match_prefix_key = InternalKey(ns_key, subkey_prefix, metadata.version, storage_->IsSlotIdEncoded()).Encode(); @@ -620,16 +600,12 @@ Status WriteBatchLogData::Decode(const rocksdb::Slice &blob) { return Status::OK(); } -rocksdb::Status Database::existsInternal(const std::vector &keys, int *ret) { +rocksdb::Status Database::existsInternal(engine::Context &ctx, const std::vector &keys, int *ret) { *ret = 0; - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); - rocksdb::Status s; std::string value; for (const auto &key : keys) { - s = storage_->Get(read_options, metadata_cf_handle_, key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, key, &value); if (!s.ok() && !s.IsNotFound()) return s; if (s.ok()) { Metadata metadata(kRedisNone, false); @@ -641,13 +617,10 @@ rocksdb::Status Database::existsInternal(const std::vector &keys, i return rocksdb::Status::OK(); } -rocksdb::Status Database::typeInternal(const Slice &key, RedisType *type) { +rocksdb::Status Database::typeInternal(engine::Context &ctx, const Slice &key, RedisType *type) { *type = kRedisNone; - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string value; - rocksdb::Status s = storage_->Get(read_options, metadata_cf_handle_, key, &value); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), metadata_cf_handle_, key, &value); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; Metadata metadata(kRedisNone, false); @@ -661,13 +634,13 @@ rocksdb::Status Database::typeInternal(const Slice &key, RedisType *type) { return rocksdb::Status::OK(); } -rocksdb::Status Database::Copy(const std::string &key, const std::string &new_key, bool nx, bool delete_old, - CopyResult *res) { +rocksdb::Status Database::Copy(engine::Context &ctx, const std::string &key, const std::string &new_key, bool nx, + bool delete_old, CopyResult *res) { std::vector lock_keys = {key, new_key}; MultiLockGuard guard(storage_->GetLockManager(), lock_keys); RedisType type = kRedisNone; - auto s = typeInternal(key, &type); + auto s = typeInternal(ctx, key, &type); if (!s.ok()) return s; if (type == kRedisNone) { *res = CopyResult::KEY_NOT_EXIST; @@ -676,7 +649,7 @@ rocksdb::Status Database::Copy(const std::string &key, const std::string &new_ke if (nx) { int exist = 0; - if (s = existsInternal({new_key}, &exist), !s.ok()) return s; + if (s = existsInternal(ctx, {new_key}, &exist), !s.ok()) return s; if (exist > 0) { *res = CopyResult::KEY_ALREADY_EXIST; return rocksdb::Status::OK(); @@ -691,7 +664,7 @@ rocksdb::Status Database::Copy(const std::string &key, const std::string &new_ke WriteBatchLogData log_data(type); batch->PutLogData(log_data.Encode()); - engine::DBIterator iter(storage_, rocksdb::ReadOptions()); + engine::DBIterator iter(ctx, ctx.GetReadOptions()); iter.Seek(key); if (delete_old) { @@ -725,10 +698,11 @@ rocksdb::Status Database::Copy(const std::string &key, const std::string &new_ke } } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -std::optional Database::lookupKeyByPattern(const std::string &pattern, const std::string &subst) { +std::optional Database::lookupKeyByPattern(engine::Context &ctx, const std::string &pattern, + const std::string &subst) { if (pattern == "#") { return subst; } @@ -752,31 +726,31 @@ std::optional Database::lookupKeyByPattern(const std::string &patte RedisType type = RedisType::kRedisNone; if (!field.empty()) { auto hash_db = redis::Hash(storage_, namespace_); - if (auto s = hash_db.Type(key, &type); !s.ok() || type != RedisType::kRedisHash) { + if (auto s = hash_db.Type(ctx, key, &type); !s.ok() || type != RedisType::kRedisHash) { return std::nullopt; } - if (auto s = hash_db.Get(key, field, &value); !s.ok()) { + if (auto s = hash_db.Get(ctx, key, field, &value); !s.ok()) { return std::nullopt; } } else { auto string_db = redis::String(storage_, namespace_); - if (auto s = string_db.Type(key, &type); !s.ok() || type != RedisType::kRedisString) { + if (auto s = string_db.Type(ctx, key, &type); !s.ok() || type != RedisType::kRedisString) { return std::nullopt; } - if (auto s = string_db.Get(key, &value); !s.ok()) { + if (auto s = string_db.Get(ctx, key, &value); !s.ok()) { return std::nullopt; } } return value; } -rocksdb::Status Database::Sort(RedisType type, const std::string &key, const SortArgument &args, +rocksdb::Status Database::Sort(engine::Context &ctx, RedisType type, const std::string &key, const SortArgument &args, std::vector> *elems, SortResult *res) { // Obtain the length of the object to sort. const std::string ns_key = AppendNamespacePrefix(key); Metadata metadata(type, false); - auto s = GetMetadata(GetOptions{}, {type}, ns_key, &metadata); + auto s = GetMetadata(ctx, {type}, ns_key, &metadata); if (!s.ok()) return s; if (metadata.size > SORT_LENGTH_LIMIT) { @@ -798,20 +772,20 @@ rocksdb::Status Database::Sort(RedisType type, const std::string &key, const Sor if (args.dontsort) { if (args.desc) { - s = list_db.Range(key, -count - offset, -1 - offset, &str_vec); + s = list_db.Range(ctx, key, -count - offset, -1 - offset, &str_vec); if (!s.ok()) return s; std::reverse(str_vec.begin(), str_vec.end()); } else { - s = list_db.Range(key, offset, offset + count - 1, &str_vec); + s = list_db.Range(ctx, key, offset, offset + count - 1, &str_vec); if (!s.ok()) return s; } } else { - s = list_db.Range(key, 0, -1, &str_vec); + s = list_db.Range(ctx, key, 0, -1, &str_vec); if (!s.ok()) return s; } } else if (type == RedisType::kRedisSet) { auto set_db = redis::Set(storage_, namespace_); - s = set_db.Members(key, &str_vec); + s = set_db.Members(ctx, key, &str_vec); if (!s.ok()) return s; if (args.dontsort) { @@ -827,14 +801,14 @@ rocksdb::Status Database::Sort(RedisType type, const std::string &key, const Sor spec.start = offset; spec.stop = offset + count - 1; spec.reversed = args.desc; - s = zset_db.RangeByRank(key, spec, &member_scores, nullptr); + s = zset_db.RangeByRank(ctx, key, spec, &member_scores, nullptr); if (!s.ok()) return s; for (auto &member_score : member_scores) { str_vec.emplace_back(std::move(member_score.member)); } } else { - s = zset_db.GetAllMemberScores(key, &member_scores); + s = zset_db.GetAllMemberScores(ctx, key, &member_scores); if (!s.ok()) return s; for (auto &member_score : member_scores) { @@ -857,7 +831,7 @@ rocksdb::Status Database::Sort(RedisType type, const std::string &key, const Sor for (size_t i = 0; i < sort_vec.size(); ++i) { std::string byval; if (!args.sortby.empty()) { - auto lookup = lookupKeyByPattern(args.sortby, str_vec[i]); + auto lookup = lookupKeyByPattern(ctx, args.sortby, str_vec[i]); if (!lookup.has_value()) continue; byval = std::move(lookup.value()); } else { @@ -893,7 +867,7 @@ rocksdb::Status Database::Sort(RedisType type, const std::string &key, const Sor elems->emplace_back(elem.obj); } for (const std::string &pattern : args.getpatterns) { - std::optional val = lookupKeyByPattern(pattern, elem.obj); + std::optional val = lookupKeyByPattern(ctx, pattern, elem.obj); if (val.has_value()) { elems->emplace_back(val.value()); } else { @@ -909,10 +883,12 @@ rocksdb::Status Database::Sort(RedisType type, const std::string &key, const Sor store_elems.emplace_back(e.value_or("")); } redis::List list_db(storage_, namespace_); - s = list_db.Trim(args.storekey, -1, 0); + s = list_db.Trim(ctx, args.storekey, -1, 0); + if (!s.ok()) return s; uint64_t new_size = 0; - s = list_db.Push(args.storekey, std::vector(store_elems.cbegin(), store_elems.cend()), false, &new_size); + s = list_db.Push(ctx, args.storekey, std::vector(store_elems.cbegin(), store_elems.cend()), false, + &new_size); if (!s.ok()) return s; } diff --git a/src/storage/redis_db.h b/src/storage/redis_db.h index 289d2a2aa3b..7111fed1099 100644 --- a/src/storage/redis_db.h +++ b/src/storage/redis_db.h @@ -74,15 +74,6 @@ class Database { public: static constexpr uint64_t RANDOM_KEY_SCAN_LIMIT = 60; - struct GetOptions { - // If snapshot is not nullptr, read from the specified snapshot, - // otherwise read from the "latest" snapshot. - const rocksdb::Snapshot *snapshot = nullptr; - - GetOptions() = default; - explicit GetOptions(const rocksdb::Snapshot *ss) : snapshot(ss) {} - }; - explicit Database(engine::Storage *storage, std::string ns = ""); /// Parsing metadata with type of `types` from bytes, the metadata is a base class of all metadata. /// When parsing, the bytes will be consumed. @@ -94,7 +85,7 @@ class Database { /// \param types The candidate types of the metadata. /// \param ns_key The key with namespace of the metadata. /// \param metadata The output metadata. - [[nodiscard]] rocksdb::Status GetMetadata(GetOptions options, RedisTypes types, const Slice &ns_key, + [[nodiscard]] rocksdb::Status GetMetadata(engine::Context &ctx, RedisTypes types, const Slice &ns_key, Metadata *metadata); /// GetMetadata is a helper function to get metadata from the database. It will read the "raw metadata" /// from underlying storage, and then parse the raw metadata to the specified metadata type. @@ -108,7 +99,7 @@ class Database { /// \param raw_value Holding the raw metadata. /// \param metadata The output metadata. /// \param rest The rest of the bytes after parsing the metadata. - [[nodiscard]] rocksdb::Status GetMetadata(GetOptions options, RedisTypes types, const Slice &ns_key, + [[nodiscard]] rocksdb::Status GetMetadata(engine::Context &ctx, RedisTypes types, const Slice &ns_key, std::string *raw_value, Metadata *metadata, Slice *rest); /// GetRawMetadata is a helper function to get the "raw metadata" from the database without parsing /// it to the specified metadata type. @@ -116,32 +107,33 @@ class Database { /// \param options The read options, including whether uses a snapshot during reading the metadata. /// \param ns_key The key with namespace of the metadata. /// \param bytes The output raw metadata. - [[nodiscard]] rocksdb::Status GetRawMetadata(GetOptions options, const Slice &ns_key, std::string *bytes); - [[nodiscard]] rocksdb::Status Expire(const Slice &user_key, uint64_t timestamp); - [[nodiscard]] rocksdb::Status Del(const Slice &user_key); - [[nodiscard]] rocksdb::Status MDel(const std::vector &keys, uint64_t *deleted_cnt); - [[nodiscard]] rocksdb::Status Exists(const std::vector &keys, int *ret); - [[nodiscard]] rocksdb::Status TTL(const Slice &user_key, int64_t *ttl); - [[nodiscard]] rocksdb::Status GetExpireTime(const Slice &user_key, uint64_t *timestamp); - [[nodiscard]] rocksdb::Status Type(const Slice &key, RedisType *type); - [[nodiscard]] rocksdb::Status Dump(const Slice &user_key, std::vector *infos); - [[nodiscard]] rocksdb::Status FlushDB(); - [[nodiscard]] rocksdb::Status FlushAll(); - [[nodiscard]] rocksdb::Status GetKeyNumStats(const std::string &prefix, KeyNumStats *stats); - [[nodiscard]] rocksdb::Status Keys(const std::string &prefix, std::vector *keys = nullptr, - KeyNumStats *stats = nullptr); - [[nodiscard]] rocksdb::Status Scan(const std::string &cursor, uint64_t limit, const std::string &prefix, - std::vector *keys, std::string *end_cursor = nullptr, - RedisType type = kRedisNone); - [[nodiscard]] rocksdb::Status RandomKey(const std::string &cursor, std::string *key); + [[nodiscard]] rocksdb::Status GetRawMetadata(engine::Context &ctx, const Slice &ns_key, std::string *bytes); + [[nodiscard]] rocksdb::Status Expire(engine::Context &ctx, const Slice &user_key, uint64_t timestamp); + [[nodiscard]] rocksdb::Status Del(engine::Context &ctx, const Slice &user_key); + [[nodiscard]] rocksdb::Status MDel(engine::Context &ctx, const std::vector &keys, uint64_t *deleted_cnt); + [[nodiscard]] rocksdb::Status Exists(engine::Context &ctx, const std::vector &keys, int *ret); + [[nodiscard]] rocksdb::Status TTL(engine::Context &ctx, const Slice &user_key, int64_t *ttl); + [[nodiscard]] rocksdb::Status GetExpireTime(engine::Context &ctx, const Slice &user_key, uint64_t *timestamp); + [[nodiscard]] rocksdb::Status Type(engine::Context &ctx, const Slice &key, RedisType *type); + [[nodiscard]] rocksdb::Status Dump(engine::Context &ctx, const Slice &user_key, std::vector *infos); + [[nodiscard]] rocksdb::Status FlushDB(engine::Context &ctx); + [[nodiscard]] rocksdb::Status FlushAll(engine::Context &ctx); + [[nodiscard]] rocksdb::Status GetKeyNumStats(engine::Context &ctx, const std::string &prefix, KeyNumStats *stats); + [[nodiscard]] rocksdb::Status Keys(engine::Context &ctx, const std::string &prefix, + std::vector *keys = nullptr, KeyNumStats *stats = nullptr); + [[nodiscard]] rocksdb::Status Scan(engine::Context &ctx, const std::string &cursor, uint64_t limit, + const std::string &prefix, std::vector *keys, + std::string *end_cursor = nullptr, RedisType type = kRedisNone); + [[nodiscard]] rocksdb::Status RandomKey(engine::Context &ctx, const std::string &cursor, std::string *key); std::string AppendNamespacePrefix(const Slice &user_key); - [[nodiscard]] rocksdb::Status ClearKeysOfSlotRange(const rocksdb::Slice &ns, const SlotRange &slot_range); - [[nodiscard]] rocksdb::Status KeyExist(const std::string &key); + [[nodiscard]] rocksdb::Status ClearKeysOfSlotRange(engine::Context &ctx, const rocksdb::Slice &ns, + const SlotRange &slot_range); + [[nodiscard]] rocksdb::Status KeyExist(engine::Context &ctx, const std::string &key); // Copy to (already an internal key) enum class CopyResult { KEY_NOT_EXIST, KEY_ALREADY_EXIST, DONE }; - [[nodiscard]] rocksdb::Status Copy(const std::string &key, const std::string &new_key, bool nx, bool delete_old, - CopyResult *res); + [[nodiscard]] rocksdb::Status Copy(engine::Context &ctx, const std::string &key, const std::string &new_key, bool nx, + bool delete_old, CopyResult *res); enum class SortResult { UNKNOWN_TYPE, DOUBLE_CONVERT_ERROR, LIMIT_EXCEEDED, DONE }; /// Sort sorts keys of the specified type according to SortArgument /// @@ -151,20 +143,19 @@ class Database { /// \param elems contain the sorted results /// \param res represents the sorted result type. /// When status is not ok, `res` should not been checked, otherwise it should be checked whether `res` is `DONE` - [[nodiscard]] rocksdb::Status Sort(RedisType type, const std::string &key, const SortArgument &args, - std::vector> *elems, SortResult *res); + [[nodiscard]] rocksdb::Status Sort(engine::Context &ctx, RedisType type, const std::string &key, + const SortArgument &args, std::vector> *elems, + SortResult *res); protected: engine::Storage *storage_; rocksdb::ColumnFamilyHandle *metadata_cf_handle_; std::string namespace_; - friend class LatestSnapShot; - private: // Already internal keys - [[nodiscard]] rocksdb::Status existsInternal(const std::vector &keys, int *ret); - [[nodiscard]] rocksdb::Status typeInternal(const Slice &key, RedisType *type); + [[nodiscard]] rocksdb::Status existsInternal(engine::Context &ctx, const std::vector &keys, int *ret); + [[nodiscard]] rocksdb::Status typeInternal(engine::Context &ctx, const Slice &key, RedisType *type); /// lookupKeyByPattern is a helper function of `Sort` to support `GET` and `BY` fields. /// @@ -179,27 +170,15 @@ class Database { /// 3) If 'pattern' equals "#", the function simply returns 'subst' itself so /// that the SORT command can be used like: SORT key GET # to retrieve /// the Set/List elements directly. - std::optional lookupKeyByPattern(const std::string &pattern, const std::string &subst); -}; -class LatestSnapShot { - public: - explicit LatestSnapShot(engine::Storage *storage) : storage_(storage), snapshot_(storage_->GetDB()->GetSnapshot()) {} - ~LatestSnapShot() { storage_->GetDB()->ReleaseSnapshot(snapshot_); } - const rocksdb::Snapshot *GetSnapShot() const { return snapshot_; } - - LatestSnapShot(const LatestSnapShot &) = delete; - LatestSnapShot &operator=(const LatestSnapShot &) = delete; - - private: - engine::Storage *storage_ = nullptr; - const rocksdb::Snapshot *snapshot_ = nullptr; + std::optional lookupKeyByPattern(engine::Context &ctx, const std::string &pattern, + const std::string &subst); }; class SubKeyScanner : public redis::Database { public: explicit SubKeyScanner(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Scan(RedisType type, const Slice &user_key, const std::string &cursor, uint64_t limit, - const std::string &subkey_prefix, std::vector *keys, + rocksdb::Status Scan(engine::Context &ctx, RedisType type, const Slice &user_key, const std::string &cursor, + uint64_t limit, const std::string &subkey_prefix, std::vector *keys, std::vector *values = nullptr); }; diff --git a/src/storage/redis_pubsub.cc b/src/storage/redis_pubsub.cc index 6ca153b70be..3c016ee0b68 100644 --- a/src/storage/redis_pubsub.cc +++ b/src/storage/redis_pubsub.cc @@ -22,13 +22,13 @@ namespace redis { -rocksdb::Status PubSub::Publish(const Slice &channel, const Slice &value) { +rocksdb::Status PubSub::Publish(engine::Context &ctx, const Slice &channel, const Slice &value) { if (storage_->GetConfig()->IsSlave()) { return rocksdb::Status::NotSupported("can't publish to db in slave mode"); } auto batch = storage_->GetWriteBatchBase(); batch->Put(pubsub_cf_handle_, channel, value); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } } // namespace redis diff --git a/src/storage/redis_pubsub.h b/src/storage/redis_pubsub.h index d6e3d392f40..72f7f8cb107 100644 --- a/src/storage/redis_pubsub.h +++ b/src/storage/redis_pubsub.h @@ -31,7 +31,7 @@ class PubSub : public Database { public: explicit PubSub(engine::Storage *storage) : Database(storage), pubsub_cf_handle_(storage->GetCFHandle(ColumnFamilyID::PubSub)) {} - rocksdb::Status Publish(const Slice &channel, const Slice &value); + rocksdb::Status Publish(engine::Context &ctx, const Slice &channel, const Slice &value); private: rocksdb::ColumnFamilyHandle *pubsub_cf_handle_; diff --git a/src/storage/scripting.cc b/src/storage/scripting.cc index bfe1016ee70..33f133d9836 100644 --- a/src/storage/scripting.cc +++ b/src/storage/scripting.cc @@ -300,8 +300,8 @@ Status FunctionLoad(redis::Connection *conn, const std::string &script, bool nee if (!replace) { return {Status::NotOK, "library already exists, please specify REPLACE to force load"}; } - - auto s = FunctionDelete(srv, libname); + engine::Context ctx(srv->storage); + auto s = FunctionDelete(ctx, srv, libname); if (!s) return s; } @@ -444,14 +444,13 @@ Status FunctionList(Server *srv, const redis::Connection *conn, const std::strin std::string end_key = start_key; end_key.back()++; - rocksdb::ReadOptions read_options = srv->storage->DefaultScanOptions(); - redis::LatestSnapShot ss(srv->storage); - read_options.snapshot = ss.GetSnapShot(); + engine::Context ctx(srv->storage); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(end_key); read_options.iterate_upper_bound = &upper_bound; auto *cf = srv->storage->GetCFHandle(ColumnFamilyID::Propagate); - auto iter = util::UniqueIterator(srv->storage, read_options, cf); + auto iter = util::UniqueIterator(ctx, read_options, cf); std::vector> result; for (iter->Seek(start_key); iter->Valid(); iter->Next()) { Slice lib = iter->key(); @@ -484,14 +483,13 @@ Status FunctionListFunc(Server *srv, const redis::Connection *conn, const std::s std::string end_key = start_key; end_key.back()++; - rocksdb::ReadOptions read_options = srv->storage->DefaultScanOptions(); - redis::LatestSnapShot ss(srv->storage); - read_options.snapshot = ss.GetSnapShot(); + engine::Context ctx(srv->storage); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(end_key); read_options.iterate_upper_bound = &upper_bound; auto *cf = srv->storage->GetCFHandle(ColumnFamilyID::Propagate); - auto iter = util::UniqueIterator(srv->storage, read_options, cf); + auto iter = util::UniqueIterator(ctx, read_options, cf); std::vector> result; for (iter->Seek(start_key); iter->Valid(); iter->Next()) { Slice func = iter->key(); @@ -556,7 +554,7 @@ Status FunctionListLib(Server *srv, const redis::Connection *conn, const std::st return Status::OK(); } -Status FunctionDelete(Server *srv, const std::string &name) { +Status FunctionDelete(engine::Context &ctx, Server *srv, const std::string &name) { auto lua = srv->Lua(); lua_getglobal(lua, REDIS_FUNCTION_LIBRARIES); @@ -581,7 +579,7 @@ Status FunctionDelete(Server *srv, const std::string &name) { lua_setglobal(lua, (REDIS_LUA_REGISTER_FUNC_PREFIX + func).c_str()); lua_pushnil(lua); lua_setglobal(lua, (REDIS_LUA_REGISTER_FUNC_FLAGS_PREFIX + func).c_str()); - auto _ = storage->Delete(rocksdb::WriteOptions(), cf, engine::kLuaFuncLibPrefix + func); + auto _ = storage->Delete(ctx, rocksdb::WriteOptions(), cf, engine::kLuaFuncLibPrefix + func); lua_pop(lua, 1); } @@ -590,7 +588,7 @@ Status FunctionDelete(Server *srv, const std::string &name) { lua_setfield(lua, -2, name.c_str()); lua_pop(lua, 1); - auto s = storage->Delete(rocksdb::WriteOptions(), cf, engine::kLuaLibCodePrefix + name); + auto s = storage->Delete(ctx, rocksdb::WriteOptions(), cf, engine::kLuaLibCodePrefix + name); if (!s.ok()) return {Status::NotOK, s.ToString()}; return Status::OK(); diff --git a/src/storage/scripting.h b/src/storage/scripting.h index 6cfa31f066b..9aa4044ba3c 100644 --- a/src/storage/scripting.h +++ b/src/storage/scripting.h @@ -27,6 +27,10 @@ #include "server/redis_connection.h" #include "status.h" +namespace engine { +struct Context; +} + inline constexpr const char REDIS_LUA_FUNC_SHA_PREFIX[] = "f_"; inline constexpr const char REDIS_LUA_FUNC_SHA_FLAGS[] = "f_{}_flags_"; inline constexpr const char REDIS_LUA_REGISTER_FUNC_PREFIX[] = "__redis_registered_"; @@ -74,7 +78,7 @@ Status FunctionList(Server *srv, const redis::Connection *conn, const std::strin std::string *output); Status FunctionListFunc(Server *srv, const redis::Connection *conn, const std::string &funcname, std::string *output); Status FunctionListLib(Server *srv, const redis::Connection *conn, const std::string &libname, std::string *output); -Status FunctionDelete(Server *srv, const std::string &name); +Status FunctionDelete(engine::Context &ctx, Server *srv, const std::string &name); bool FunctionIsLibExist(redis::Connection *conn, const std::string &libname, bool need_check_storage = true, bool read_only = false); diff --git a/src/storage/storage.cc b/src/storage/storage.cc index c6f456a4737..dae8f326dfc 100644 --- a/src/storage/storage.cc +++ b/src/storage/storage.cc @@ -45,6 +45,7 @@ #include "rocksdb/cache.h" #include "rocksdb_crc32c.h" #include "server/server.h" +#include "storage/batch_indexer.h" #include "table_properties_collector.h" #include "time_util.h" #include "unique_fd.h" @@ -587,15 +588,23 @@ Status Storage::GetWALIter(rocksdb::SequenceNumber seq, std::unique_ptrGetLatestSequenceNumber(); } -rocksdb::Status Storage::Get(const rocksdb::ReadOptions &options, const rocksdb::Slice &key, std::string *value) { - return Get(options, db_->DefaultColumnFamily(), key, value); +rocksdb::Status Storage::Get(engine::Context &ctx, const rocksdb::ReadOptions &options, const rocksdb::Slice &key, + std::string *value) { + return Get(ctx, options, db_->DefaultColumnFamily(), key, value); } -rocksdb::Status Storage::Get(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, - const rocksdb::Slice &key, std::string *value) { +rocksdb::Status Storage::Get(engine::Context &ctx, const rocksdb::ReadOptions &options, + rocksdb::ColumnFamilyHandle *column_family, const rocksdb::Slice &key, + std::string *value) { + if (ctx.is_txn_mode) { + DCHECK_NOTNULL(options.snapshot); + DCHECK_EQ(ctx.snapshot->GetSequenceNumber(), options.snapshot->GetSequenceNumber()); + } rocksdb::Status s; if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) { s = txn_write_batch_->GetFromBatchAndDB(db_.get(), options, column_family, key, value); + } else if (ctx.batch && ctx.is_txn_mode) { + s = ctx.batch->GetFromBatchAndDB(db_.get(), options, column_family, key, value); } else { s = db_->Get(options, column_family, key, value); } @@ -604,16 +613,23 @@ rocksdb::Status Storage::Get(const rocksdb::ReadOptions &options, rocksdb::Colum return s; } -rocksdb::Status Storage::Get(const rocksdb::ReadOptions &options, const rocksdb::Slice &key, +rocksdb::Status Storage::Get(engine::Context &ctx, const rocksdb::ReadOptions &options, const rocksdb::Slice &key, rocksdb::PinnableSlice *value) { - return Get(options, db_->DefaultColumnFamily(), key, value); + return Get(ctx, options, db_->DefaultColumnFamily(), key, value); } -rocksdb::Status Storage::Get(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, - const rocksdb::Slice &key, rocksdb::PinnableSlice *value) { +rocksdb::Status Storage::Get(engine::Context &ctx, const rocksdb::ReadOptions &options, + rocksdb::ColumnFamilyHandle *column_family, const rocksdb::Slice &key, + rocksdb::PinnableSlice *value) { + if (ctx.is_txn_mode) { + DCHECK_NOTNULL(options.snapshot); + DCHECK_EQ(ctx.snapshot->GetSequenceNumber(), options.snapshot->GetSequenceNumber()); + } rocksdb::Status s; if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) { s = txn_write_batch_->GetFromBatchAndDB(db_.get(), options, column_family, key, value); + } else if (ctx.is_txn_mode && ctx.batch) { + s = ctx.batch->GetFromBatchAndDB(db_.get(), options, column_family, key, value); } else { s = db_->Get(options, column_family, key, value); } @@ -622,8 +638,8 @@ rocksdb::Status Storage::Get(const rocksdb::ReadOptions &options, rocksdb::Colum return s; } -rocksdb::Iterator *Storage::NewIterator(const rocksdb::ReadOptions &options) { - return NewIterator(options, db_->DefaultColumnFamily()); +rocksdb::Iterator *Storage::NewIterator(engine::Context &ctx, const rocksdb::ReadOptions &options) { + return NewIterator(ctx, options, db_->DefaultColumnFamily()); } void Storage::recordKeyspaceStat(const rocksdb::ColumnFamilyHandle *column_family, const rocksdb::Status &s) { @@ -636,21 +652,33 @@ void Storage::recordKeyspaceStat(const rocksdb::ColumnFamilyHandle *column_famil } } -rocksdb::Iterator *Storage::NewIterator(const rocksdb::ReadOptions &options, +rocksdb::Iterator *Storage::NewIterator(engine::Context &ctx, const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family) { + if (ctx.is_txn_mode) { + DCHECK_NOTNULL(options.snapshot); + DCHECK_EQ(ctx.snapshot->GetSequenceNumber(), options.snapshot->GetSequenceNumber()); + } auto iter = db_->NewIterator(options, column_family); if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) { return txn_write_batch_->NewIteratorWithBase(column_family, iter, &options); + } else if (ctx.is_txn_mode && ctx.batch && ctx.batch->GetWriteBatch()->Count() > 0) { + return ctx.batch->NewIteratorWithBase(column_family, iter, &options); } return iter; } -void Storage::MultiGet(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, - const size_t num_keys, const rocksdb::Slice *keys, rocksdb::PinnableSlice *values, - rocksdb::Status *statuses) { +void Storage::MultiGet(engine::Context &ctx, const rocksdb::ReadOptions &options, + rocksdb::ColumnFamilyHandle *column_family, const size_t num_keys, const rocksdb::Slice *keys, + rocksdb::PinnableSlice *values, rocksdb::Status *statuses) { + if (ctx.is_txn_mode) { + DCHECK_NOTNULL(options.snapshot); + DCHECK_EQ(ctx.snapshot->GetSequenceNumber(), options.snapshot->GetSequenceNumber()); + } if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) { txn_write_batch_->MultiGetFromBatchAndDB(db_.get(), options, column_family, num_keys, keys, values, statuses, false); + } else if (ctx.is_txn_mode && ctx.batch) { + ctx.batch->MultiGetFromBatchAndDB(db_.get(), options, column_family, num_keys, keys, values, statuses, false); } else { db_->MultiGet(options, column_family, num_keys, keys, values, statuses, false); } @@ -660,46 +688,58 @@ void Storage::MultiGet(const rocksdb::ReadOptions &options, rocksdb::ColumnFamil } } -rocksdb::Status Storage::Write(const rocksdb::WriteOptions &options, rocksdb::WriteBatch *updates) { +rocksdb::Status Storage::Write(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::WriteBatch *updates) { if (is_txn_mode_) { // The batch won't be flushed until the transaction was committed or rollback return rocksdb::Status::OK(); } - return writeToDB(options, updates); + return writeToDB(ctx, options, updates); } -rocksdb::Status Storage::writeToDB(const rocksdb::WriteOptions &options, rocksdb::WriteBatch *updates) { +rocksdb::Status Storage::writeToDB(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::WriteBatch *updates) { // Put replication id logdata at the end of write batch if (replid_.length() == kReplIdLength) { updates->PutLogData(ServerLogData(kReplIdLog, replid_).Encode()); } + if (ctx.is_txn_mode) { + if (ctx.batch == nullptr) { + ctx.batch = std::make_unique(); + } + WriteBatchIndexer handle(ctx); + auto s = updates->Iterate(&handle); + if (!s.ok()) return s; + } + return db_->Write(options, updates); } -rocksdb::Status Storage::Delete(const rocksdb::WriteOptions &options, rocksdb::ColumnFamilyHandle *cf_handle, - const rocksdb::Slice &key) { +rocksdb::Status Storage::Delete(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::ColumnFamilyHandle *cf_handle, const rocksdb::Slice &key) { auto batch = GetWriteBatchBase(); batch->Delete(cf_handle, key); - return Write(options, batch->GetWriteBatch()); + return Write(ctx, options, batch->GetWriteBatch()); } -rocksdb::Status Storage::DeleteRange(const rocksdb::WriteOptions &options, rocksdb::ColumnFamilyHandle *cf_handle, - Slice begin, Slice end) { +rocksdb::Status Storage::DeleteRange(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::ColumnFamilyHandle *cf_handle, Slice begin, Slice end) { auto batch = GetWriteBatchBase(); auto s = batch->DeleteRange(cf_handle, begin, end); if (!s.ok()) { return s; } - return Write(options, batch->GetWriteBatch()); + return Write(ctx, options, batch->GetWriteBatch()); } -rocksdb::Status Storage::DeleteRange(Slice begin, Slice end) { - return DeleteRange(default_write_opts_, GetCFHandle(ColumnFamilyID::Metadata), begin, end); +rocksdb::Status Storage::DeleteRange(engine::Context &ctx, Slice begin, Slice end) { + return DeleteRange(ctx, default_write_opts_, GetCFHandle(ColumnFamilyID::Metadata), begin, end); } -rocksdb::Status Storage::FlushScripts(const rocksdb::WriteOptions &options, rocksdb::ColumnFamilyHandle *cf_handle) { +rocksdb::Status Storage::FlushScripts(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::ColumnFamilyHandle *cf_handle) { std::string begin_key = kLuaFuncSHAPrefix, end_key = begin_key; // we need to increase one here since the DeleteRange api // didn't contain the end key. @@ -711,7 +751,7 @@ rocksdb::Status Storage::FlushScripts(const rocksdb::WriteOptions &options, rock return s; } - return Write(options, batch->GetWriteBatch()); + return Write(ctx, options, batch->GetWriteBatch()); } Status Storage::ReplicaApplyWriteBatch(std::string &&raw_batch) { @@ -832,8 +872,8 @@ Status Storage::CommitTxn() { if (!is_txn_mode_) { return Status{Status::NotOK, "cannot commit while not in transaction mode"}; } - - auto s = writeToDB(default_write_opts_, txn_write_batch_->GetWriteBatch()); + engine::Context ctx(this); + auto s = writeToDB(ctx, default_write_opts_, txn_write_batch_->GetWriteBatch()); is_txn_mode_ = false; txn_write_batch_ = nullptr; @@ -850,21 +890,21 @@ ObserverOrUniquePtr Storage::GetWriteBatchBase() { return ObserverOrUniquePtr(new rocksdb::WriteBatch(), ObserverOrUnique::Unique); } -Status Storage::WriteToPropagateCF(const std::string &key, const std::string &value) { +Status Storage::WriteToPropagateCF(engine::Context &ctx, const std::string &key, const std::string &value) { if (config_->IsSlave()) { return {Status::NotOK, "cannot write to propagate column family in slave mode"}; } auto batch = GetWriteBatchBase(); auto cf = GetCFHandle(ColumnFamilyID::Propagate); batch->Put(cf, key, value); - auto s = Write(default_write_opts_, batch->GetWriteBatch()); + auto s = Write(ctx, default_write_opts_, batch->GetWriteBatch()); if (!s.ok()) { return {Status::NotOK, s.ToString()}; } return Status::OK(); } -Status Storage::ShiftReplId() { +Status Storage::ShiftReplId(engine::Context &ctx) { static constexpr std::string_view charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Do nothing if rsid psync is not enabled @@ -882,7 +922,7 @@ Status Storage::ShiftReplId() { LOG(INFO) << "[replication] New replication id: " << replid_; // Write new replication id into db engine - return WriteToPropagateCF(kReplicationIdKey, replid_); + return WriteToPropagateCF(ctx, kReplicationIdKey, replid_); } std::string Storage::GetReplIdFromWalBySeq(rocksdb::SequenceNumber seq) { @@ -1224,4 +1264,33 @@ bool Storage::ReplDataManager::FileExists(Storage *storage, const std::string &d return crc == tmp_crc; } +[[nodiscard]] rocksdb::ReadOptions Context::GetReadOptions() const { + rocksdb::ReadOptions read_options; + if (is_txn_mode) read_options.snapshot = snapshot; + return read_options; +} + +[[nodiscard]] rocksdb::ReadOptions Context::DefaultScanOptions() const { + rocksdb::ReadOptions read_options = storage->DefaultScanOptions(); + if (is_txn_mode) read_options.snapshot = snapshot; + return read_options; +} + +[[nodiscard]] rocksdb::ReadOptions Context::DefaultMultiGetOptions() const { + rocksdb::ReadOptions read_options = storage->DefaultMultiGetOptions(); + if (is_txn_mode) read_options.snapshot = snapshot; + return read_options; +} + +void Context::RefreshLatestSnapshot() { + auto guard = storage->WriteLockGuard(); + if (snapshot) { + storage->GetDB()->ReleaseSnapshot(snapshot); + } + snapshot = storage->GetDB()->GetSnapshot(); + if (batch) { + batch->Clear(); + } +} + } // namespace engine diff --git a/src/storage/storage.h b/src/storage/storage.h index df992848098..9c63582d6ab 100644 --- a/src/storage/storage.h +++ b/src/storage/storage.h @@ -197,6 +197,8 @@ class ColumnFamilyConfigs { }; }; +struct Context; + class Storage { public: explicit Storage(Config *config); @@ -225,32 +227,37 @@ class Storage { Status ApplyWriteBatch(const rocksdb::WriteOptions &options, std::string &&raw_batch); rocksdb::SequenceNumber LatestSeqNumber(); - [[nodiscard]] rocksdb::Status Get(const rocksdb::ReadOptions &options, const rocksdb::Slice &key, std::string *value); - [[nodiscard]] rocksdb::Status Get(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, + [[nodiscard]] rocksdb::Status Get(engine::Context &ctx, const rocksdb::ReadOptions &options, const rocksdb::Slice &key, std::string *value); - [[nodiscard]] rocksdb::Status Get(const rocksdb::ReadOptions &options, const rocksdb::Slice &key, - rocksdb::PinnableSlice *value); - [[nodiscard]] rocksdb::Status Get(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, + [[nodiscard]] rocksdb::Status Get(engine::Context &ctx, const rocksdb::ReadOptions &options, + rocksdb::ColumnFamilyHandle *column_family, const rocksdb::Slice &key, + std::string *value); + [[nodiscard]] rocksdb::Status Get(engine::Context &ctx, const rocksdb::ReadOptions &options, const rocksdb::Slice &key, rocksdb::PinnableSlice *value); - void MultiGet(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, size_t num_keys, - const rocksdb::Slice *keys, rocksdb::PinnableSlice *values, rocksdb::Status *statuses); - rocksdb::Iterator *NewIterator(const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family); - rocksdb::Iterator *NewIterator(const rocksdb::ReadOptions &options); - - [[nodiscard]] rocksdb::Status Write(const rocksdb::WriteOptions &options, rocksdb::WriteBatch *updates); + [[nodiscard]] rocksdb::Status Get(engine::Context &ctx, const rocksdb::ReadOptions &options, + rocksdb::ColumnFamilyHandle *column_family, const rocksdb::Slice &key, + rocksdb::PinnableSlice *value); + void MultiGet(engine::Context &ctx, const rocksdb::ReadOptions &options, rocksdb::ColumnFamilyHandle *column_family, + size_t num_keys, const rocksdb::Slice *keys, rocksdb::PinnableSlice *values, rocksdb::Status *statuses); + rocksdb::Iterator *NewIterator(engine::Context &ctx, const rocksdb::ReadOptions &options, + rocksdb::ColumnFamilyHandle *column_family); + rocksdb::Iterator *NewIterator(engine::Context &ctx, const rocksdb::ReadOptions &options); + + [[nodiscard]] rocksdb::Status Write(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::WriteBatch *updates); const rocksdb::WriteOptions &DefaultWriteOptions() { return default_write_opts_; } rocksdb::ReadOptions DefaultScanOptions() const; rocksdb::ReadOptions DefaultMultiGetOptions() const; - [[nodiscard]] rocksdb::Status Delete(const rocksdb::WriteOptions &options, rocksdb::ColumnFamilyHandle *cf_handle, - const rocksdb::Slice &key); - [[nodiscard]] rocksdb::Status DeleteRange(const rocksdb::WriteOptions &options, + [[nodiscard]] rocksdb::Status Delete(engine::Context &ctx, const rocksdb::WriteOptions &options, + rocksdb::ColumnFamilyHandle *cf_handle, const rocksdb::Slice &key); + [[nodiscard]] rocksdb::Status DeleteRange(engine::Context &ctx, const rocksdb::WriteOptions &options, rocksdb::ColumnFamilyHandle *cf_handle, Slice begin, Slice end); - [[nodiscard]] rocksdb::Status DeleteRange(Slice begin, Slice end); - [[nodiscard]] rocksdb::Status FlushScripts(const rocksdb::WriteOptions &options, + [[nodiscard]] rocksdb::Status DeleteRange(engine::Context &ctx, Slice begin, Slice end); + [[nodiscard]] rocksdb::Status FlushScripts(engine::Context &ctx, const rocksdb::WriteOptions &options, rocksdb::ColumnFamilyHandle *cf_handle); bool WALHasNewData(rocksdb::SequenceNumber seq) { return seq <= LatestSeqNumber(); } Status InWALBoundary(rocksdb::SequenceNumber seq); - Status WriteToPropagateCF(const std::string &key, const std::string &value); + Status WriteToPropagateCF(engine::Context &ctx, const std::string &key, const std::string &value); [[nodiscard]] rocksdb::Status Compact(rocksdb::ColumnFamilyHandle *cf, const rocksdb::Slice *begin, const rocksdb::Slice *end); @@ -323,7 +330,7 @@ class Storage { void SetDBInRetryableIOError(bool yes_or_no) { db_in_retryable_io_error_ = yes_or_no; } bool IsDBInRetryableIOError() const { return db_in_retryable_io_error_; } - Status ShiftReplId(); + Status ShiftReplId(engine::Context &ctx); std::string GetReplIdFromWalBySeq(rocksdb::SequenceNumber seq); std::string GetReplIdFromDbEngine(); @@ -361,8 +368,78 @@ class Storage { rocksdb::WriteOptions default_write_opts_ = rocksdb::WriteOptions(); - rocksdb::Status writeToDB(const rocksdb::WriteOptions &options, rocksdb::WriteBatch *updates); + rocksdb::Status writeToDB(engine::Context &ctx, const rocksdb::WriteOptions &options, rocksdb::WriteBatch *updates); void recordKeyspaceStat(const rocksdb::ColumnFamilyHandle *column_family, const rocksdb::Status &s); }; +/// Context passes fixed snapshot and batch between APIs +/// +/// Limitations: Performing a large number of writes on the same Context may reduce performance. +/// Please choose to use the same Context or create a new Context based on the actual situation. +/// +/// Context does not provide thread safety guarantees and is generally only passed as a parameter between APIs. +struct Context { + engine::Storage *storage = nullptr; + /// If is_txn_mode is true, snapshot should be specified instead of nullptr when used, + /// and should be consistent with snapshot in ReadOptions to avoid ambiguity. + /// Normally it will be fixed to the latest Snapshot when the Context is constructed. + /// If is_txn_mode is false, the snapshot is nullptr. + const rocksdb::Snapshot *snapshot = nullptr; + std::unique_ptr batch = nullptr; + + /// is_txn_mode is used to determine whether the current Context is in transactional mode, + /// if it is not transactional mode, then Context is equivalent to a Storage + bool is_txn_mode = true; + + /// NoTransactionContext returns a Context with a is_txn_mode of false + static Context NoTransactionContext(engine::Storage *storage) { return Context(storage, false); } + + /// GetReadOptions returns a default ReadOptions, and if is_txn_mode = true, then its snapshot is specified by the + /// Context + [[nodiscard]] rocksdb::ReadOptions GetReadOptions() const; + /// DefaultScanOptions returns a DefaultScanOptions, and if is_txn_mode = true, then its snapshot is specified by the + /// Context. Otherwise it is the same as Storage::DefaultScanOptions + [[nodiscard]] rocksdb::ReadOptions DefaultScanOptions() const; + /// DefaultMultiGetOptions returns a DefaultMultiGetOptions, and if is_txn_mode = true, then its snapshot is specified + /// by the Context. Otherwise it is the same as Storage::DefaultMultiGetOptions + [[nodiscard]] rocksdb::ReadOptions DefaultMultiGetOptions() const; + + void RefreshLatestSnapshot(); + + /// TODO: Change it to defer getting the context, and the snapshot is pinned after the first read operation + explicit Context(engine::Storage *storage) : storage(storage) { + auto guard = storage->ReadLockGuard(); + snapshot = storage->GetDB()->GetSnapshot(); // NOLINT + } + ~Context() { + if (storage) { + auto guard = storage->WriteLockGuard(); + if (storage->GetDB() && snapshot) { + storage->GetDB()->ReleaseSnapshot(snapshot); + } + } + } + Context(const Context &) = delete; + Context &operator=(const Context &) = delete; + Context &operator=(Context &&ctx) noexcept { + if (this != &ctx) { + storage = ctx.storage; + snapshot = ctx.snapshot; + batch = std::move(ctx.batch); + + ctx.storage = nullptr; + ctx.snapshot = nullptr; + } + return *this; + } + Context(Context &&ctx) noexcept : storage(ctx.storage), snapshot(ctx.snapshot), batch(std::move(ctx.batch)) { + ctx.storage = nullptr; + ctx.snapshot = nullptr; + } + + private: + /// It is only used by NonTransactionContext + explicit Context(engine::Storage *storage, bool txn_mode) : storage(storage), is_txn_mode(txn_mode) {} +}; + } // namespace engine diff --git a/src/types/redis_bitmap.cc b/src/types/redis_bitmap.cc index 9d108d3b5b1..c82b8ad4ddc 100644 --- a/src/types/redis_bitmap.cc +++ b/src/types/redis_bitmap.cc @@ -95,23 +95,22 @@ uint32_t SegmentSubKeyIndexForBit(uint32_t bit_offset) { return (bit_offset / kBitmapSegmentBits) * kBitmapSegmentBytes; } -rocksdb::Status Bitmap::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, BitmapMetadata *metadata, +rocksdb::Status Bitmap::GetMetadata(engine::Context &ctx, const Slice &ns_key, BitmapMetadata *metadata, std::string *raw_value) { - auto s = GetRawMetadata(get_options, ns_key, raw_value); + auto s = GetRawMetadata(ctx, ns_key, raw_value); if (!s.ok()) return s; Slice slice = *raw_value; return ParseMetadata({kRedisBitmap, kRedisString}, &slice, metadata); } -rocksdb::Status Bitmap::GetBit(const Slice &user_key, uint32_t bit_offset, bool *bit) { +rocksdb::Status Bitmap::GetBit(engine::Context &ctx, const Slice &user_key, uint32_t bit_offset, bool *bit) { *bit = false; std::string raw_value; std::string ns_key = AppendNamespacePrefix(user_key); BitmapMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata, &raw_value); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata, &raw_value); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; if (metadata.Type() == kRedisString) { @@ -119,13 +118,11 @@ rocksdb::Status Bitmap::GetBit(const Slice &user_key, uint32_t bit_offset, bool return bitmap_string_db.GetBit(raw_value, bit_offset, bit); } - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); rocksdb::PinnableSlice value; std::string sub_key = InternalKey(ns_key, std::to_string(SegmentSubKeyIndexForBit(bit_offset)), metadata.version, storage_->IsSlotIdEncoded()) .Encode(); - s = storage_->Get(read_options, sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); // If s.IsNotFound(), it means all bits in this segment are 0, // so we can return with *bit == false directly. if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; @@ -139,14 +136,14 @@ rocksdb::Status Bitmap::GetBit(const Slice &user_key, uint32_t bit_offset, bool // Use this function after careful estimation, and reserve enough memory // according to the max size of the bitmap string to prevent OOM. -rocksdb::Status Bitmap::GetString(const Slice &user_key, const uint32_t max_btos_size, std::string *value) { +rocksdb::Status Bitmap::GetString(engine::Context &ctx, const Slice &user_key, const uint32_t max_btos_size, + std::string *value) { value->clear(); std::string raw_value; std::string ns_key = AppendNamespacePrefix(user_key); BitmapMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata, &raw_value); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata, &raw_value); if (!s.ok()) return s; if (metadata.size > max_btos_size) { return rocksdb::Status::Aborted(kErrBitmapStringOutOfRange); @@ -155,12 +152,11 @@ rocksdb::Status Bitmap::GetString(const Slice &user_key, const uint32_t max_btos std::string prefix_key = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); Slice prefix_key_slice(prefix_key); read_options.iterate_lower_bound = &prefix_key_slice; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (iter->Seek(prefix_key); iter->Valid() && iter->key().starts_with(prefix_key); iter->Next()) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); auto parse_result = ParseInt(ikey.GetSubKey().ToString(), 10); @@ -183,18 +179,19 @@ rocksdb::Status Bitmap::GetString(const Slice &user_key, const uint32_t max_btos return rocksdb::Status::OK(); } -rocksdb::Status Bitmap::SetBit(const Slice &user_key, uint32_t bit_offset, bool new_bit, bool *old_bit) { +rocksdb::Status Bitmap::SetBit(engine::Context &ctx, const Slice &user_key, uint32_t bit_offset, bool new_bit, + bool *old_bit) { std::string raw_value; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); BitmapMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata, &raw_value); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata, &raw_value); if (!s.ok() && !s.IsNotFound()) return s; if (metadata.Type() == kRedisString) { redis::BitmapString bitmap_string_db(storage_, namespace_); - return bitmap_string_db.SetBit(ns_key, &raw_value, bit_offset, new_bit, old_bit); + return bitmap_string_db.SetBit(ctx, ns_key, &raw_value, bit_offset, new_bit, old_bit); } std::string value; @@ -202,7 +199,7 @@ rocksdb::Status Bitmap::SetBit(const Slice &user_key, uint32_t bit_offset, bool std::string sub_key = InternalKey(ns_key, std::to_string(segment_index), metadata.version, storage_->IsSlotIdEncoded()).Encode(); if (s.ok()) { - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (!s.ok() && !s.IsNotFound()) return s; } uint32_t bit_offset_in_segment = bit_offset % kBitmapSegmentBits; @@ -224,17 +221,17 @@ rocksdb::Status Bitmap::SetBit(const Slice &user_key, uint32_t bit_offset, bool metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Bitmap::BitCount(const Slice &user_key, int64_t start, int64_t stop, bool is_bit_index, uint32_t *cnt) { +rocksdb::Status Bitmap::BitCount(engine::Context &ctx, const Slice &user_key, int64_t start, int64_t stop, + bool is_bit_index, uint32_t *cnt) { *cnt = 0; std::string raw_value; std::string ns_key = AppendNamespacePrefix(user_key); BitmapMetadata metadata(false); - std::optional ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss->GetSnapShot()}, ns_key, &metadata, &raw_value); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata, &raw_value); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; /* Convert negative indexes */ @@ -245,7 +242,6 @@ rocksdb::Status Bitmap::BitCount(const Slice &user_key, int64_t start, int64_t s if (metadata.Type() == kRedisString) { // Release snapshot ahead for performance, this requires // `bitmap_string_db` doesn't get anything. - ss = std::nullopt; redis::BitmapString bitmap_string_db(storage_, namespace_); return bitmap_string_db.BitCount(raw_value, start, stop, is_bit_index, cnt); } @@ -266,8 +262,6 @@ rocksdb::Status Bitmap::BitCount(const Slice &user_key, int64_t start, int64_t s auto u_start = static_cast(start_byte); auto u_stop = static_cast(stop_byte); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss->GetSnapShot(); uint32_t start_index = u_start / kBitmapSegmentBytes; uint32_t stop_index = u_stop / kBitmapSegmentBytes; // Don't use multi get to prevent large range query, and take too much memory @@ -277,7 +271,7 @@ rocksdb::Status Bitmap::BitCount(const Slice &user_key, int64_t start, int64_t s std::string sub_key = InternalKey(ns_key, std::to_string(i * kBitmapSegmentBytes), metadata.version, storage_->IsSlotIdEncoded()) .Encode(); - s = storage_->Get(read_options, sub_key, &pin_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &pin_value); if (!s.ok() && !s.IsNotFound()) return s; // NotFound means all bits in this segment are 0. if (s.IsNotFound()) continue; @@ -310,16 +304,15 @@ rocksdb::Status Bitmap::BitCount(const Slice &user_key, int64_t start, int64_t s return rocksdb::Status::OK(); } -rocksdb::Status Bitmap::BitPos(const Slice &user_key, bool bit, int64_t start, int64_t stop, bool stop_given, - int64_t *pos, bool is_bit_index) { +rocksdb::Status Bitmap::BitPos(engine::Context &ctx, const Slice &user_key, bool bit, int64_t start, int64_t stop, + bool stop_given, int64_t *pos, bool is_bit_index) { if (is_bit_index) DCHECK(stop_given); std::string raw_value; std::string ns_key = AppendNamespacePrefix(user_key); BitmapMetadata metadata(false); - std::optional ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss->GetSnapShot()}, ns_key, &metadata, &raw_value); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata, &raw_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { *pos = bit ? -1 : 0; @@ -327,7 +320,6 @@ rocksdb::Status Bitmap::BitPos(const Slice &user_key, bool bit, int64_t start, i } if (metadata.Type() == kRedisString) { - ss = std::nullopt; redis::BitmapString bitmap_string_db(storage_, namespace_); return bitmap_string_db.BitPos(raw_value, bit, start, stop, stop_given, pos, is_bit_index); } @@ -359,8 +351,7 @@ rocksdb::Status Bitmap::BitPos(const Slice &user_key, bool bit, int64_t start, i return -1; }; - rocksdb::ReadOptions read_options; - read_options.snapshot = ss->GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.GetReadOptions(); // if bit index, (Eg start = 1, stop = 35), then // u_start = 1/8 = 0, u_stop = 35/8 = 4 (in bytes) uint32_t start_segment_index = (u_start / to_bit_factor) / kBitmapSegmentBytes; @@ -389,7 +380,7 @@ rocksdb::Status Bitmap::BitPos(const Slice &user_key, bool bit, int64_t start, i std::string sub_key = InternalKey(ns_key, std::to_string(i * kBitmapSegmentBytes), metadata.version, storage_->IsSlotIdEncoded()) .Encode(); - s = storage_->Get(read_options, sub_key, &pin_value); + s = storage_->Get(ctx, read_options, sub_key, &pin_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { if (!bit) { @@ -463,8 +454,8 @@ rocksdb::Status Bitmap::BitPos(const Slice &user_key, bool bit, int64_t start, i return rocksdb::Status::OK(); } -rocksdb::Status Bitmap::BitOp(BitOpFlags op_flag, const std::string &op_name, const Slice &user_key, - const std::vector &op_keys, int64_t *len) { +rocksdb::Status Bitmap::BitOp(engine::Context &ctx, BitOpFlags op_flag, const std::string &op_name, + const Slice &user_key, const std::vector &op_keys, int64_t *len) { std::string raw_value; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); @@ -475,7 +466,7 @@ rocksdb::Status Bitmap::BitOp(BitOpFlags op_flag, const std::string &op_name, co for (const auto &op_key : op_keys) { BitmapMetadata metadata(false); std::string ns_op_key = AppendNamespacePrefix(op_key); - auto s = GetMetadata(GetOptions{}, ns_op_key, &metadata, &raw_value); + auto s = GetMetadata(ctx, ns_op_key, &metadata, &raw_value); if (!s.ok()) { if (s.IsNotFound()) { continue; @@ -495,7 +486,7 @@ rocksdb::Status Bitmap::BitOp(BitOpFlags op_flag, const std::string &op_name, co if (max_bitmap_size == 0) { /* Compute the bit operation, if all bitmap is empty. cleanup the dest bitmap. */ batch->Delete(metadata_cf_handle_, ns_key); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } std::vector log_args = {std::to_string(kRedisCmdBitOp), op_name}; for (const auto &op_key : op_keys) { @@ -512,9 +503,7 @@ rocksdb::Status Bitmap::BitOp(BitOpFlags op_flag, const std::string &op_name, co uint64_t stop_index = (max_bitmap_size - 1) / kBitmapSegmentBytes; std::unique_ptr frag_res(new unsigned char[kBitmapSegmentBytes]); - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.GetReadOptions(); for (uint64_t frag_index = 0; frag_index <= stop_index; frag_index++) { std::vector fragments; uint16_t frag_maxlen = 0, frag_minlen = 0; @@ -523,7 +512,7 @@ rocksdb::Status Bitmap::BitOp(BitOpFlags op_flag, const std::string &op_name, co meta_pair.second.version, storage_->IsSlotIdEncoded()) .Encode(); rocksdb::PinnableSlice fragment; - auto s = storage_->Get(read_options, sub_key, &fragment); + auto s = storage_->Get(ctx, read_options, sub_key, &fragment); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -653,7 +642,7 @@ rocksdb::Status Bitmap::BitOp(BitOpFlags op_flag, const std::string &op_name, co res_metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); *len = static_cast(max_bitmap_size); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } // SegmentCacheStore is used to read segments from storage. @@ -666,9 +655,9 @@ class Bitmap::SegmentCacheStore { ns_key_(std::move(namespace_key)), metadata_(bitmap_metadata) {} // Get a read-only segment by given index - rocksdb::Status Get(uint32_t index, const std::string **cache) { + rocksdb::Status Get(engine::Context &ctx, uint32_t index, const std::string **cache) { std::string *res = nullptr; - auto s = get(index, /*set_dirty=*/false, &res); + auto s = get(ctx, index, /*set_dirty=*/false, &res); if (s.ok()) { *cache = res; } @@ -676,7 +665,9 @@ class Bitmap::SegmentCacheStore { } // Get a segment by given index, and mark it dirty. - rocksdb::Status GetMut(uint32_t index, std::string **cache) { return get(index, /*set_dirty=*/true, cache); } + rocksdb::Status GetMut(engine::Context &ctx, uint32_t index, std::string **cache) { + return get(ctx, index, /*set_dirty=*/true, cache); + } // Add all dirty segments into write batch. void BatchForFlush(ObserverOrUniquePtr &batch) { @@ -698,7 +689,7 @@ class Bitmap::SegmentCacheStore { } private: - rocksdb::Status get(uint32_t index, bool set_dirty, std::string **cache) { + rocksdb::Status get(engine::Context &ctx, uint32_t index, bool set_dirty, std::string **cache) { auto [seg_itor, no_cache] = cache_.try_emplace(index); auto &[is_dirty, str] = seg_itor->second; @@ -706,7 +697,7 @@ class Bitmap::SegmentCacheStore { is_dirty = false; std::string sub_key = InternalKey(ns_key_, getSegmentSubKey(index), metadata_.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::Status s = storage_->Get(rocksdb::ReadOptions(), sub_key, &str); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &str); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -728,8 +719,9 @@ class Bitmap::SegmentCacheStore { }; // Copy a range of bytes from entire bitmap and store them into ArrayBitfieldBitmap. -static rocksdb::Status CopySegmentsBytesToBitfield(Bitmap::SegmentCacheStore &store, uint32_t byte_offset, - uint32_t bytes, ArrayBitfieldBitmap *bitfield) { +static rocksdb::Status CopySegmentsBytesToBitfield(engine::Context &ctx, Bitmap::SegmentCacheStore &store, + uint32_t byte_offset, uint32_t bytes, + ArrayBitfieldBitmap *bitfield) { bitfield->SetByteOffset(byte_offset); bitfield->Reset(); @@ -739,7 +731,7 @@ static rocksdb::Status CopySegmentsBytesToBitfield(Bitmap::SegmentCacheStore &st auto segment_byte_offset = static_cast(byte_offset % kBitmapSegmentBytes); for (; remain_bytes > 0; ++segment_index) { const std::string *cache = nullptr; - auto cache_status = store.Get(segment_index, &cache); + auto cache_status = store.Get(ctx, segment_index, &cache); if (!cache_status.ok()) { return cache_status; } @@ -781,7 +773,7 @@ static rocksdb::Status GetBitfieldInteger(const ArrayBitfieldBitmap &bitfield, u return rocksdb::Status::OK(); } -static rocksdb::Status CopyBitfieldBytesToSegments(Bitmap::SegmentCacheStore &store, +static rocksdb::Status CopyBitfieldBytesToSegments(engine::Context &ctx, Bitmap::SegmentCacheStore &store, const ArrayBitfieldBitmap &bitfield, uint32_t byte_offset, uint32_t bytes) { uint32_t segment_index = byte_offset / kBitmapSegmentBytes; @@ -789,7 +781,7 @@ static rocksdb::Status CopyBitfieldBytesToSegments(Bitmap::SegmentCacheStore &st auto remain_bytes = static_cast(bytes); for (; remain_bytes > 0; ++segment_index) { std::string *cache = nullptr; - auto cache_status = store.GetMut(segment_index, &cache); + auto cache_status = store.GetMut(ctx, segment_index, &cache); if (!cache_status.ok()) { return cache_status; } @@ -815,7 +807,7 @@ static rocksdb::Status CopyBitfieldBytesToSegments(Bitmap::SegmentCacheStore &st } template -rocksdb::Status Bitmap::bitfield(const Slice &user_key, const std::vector &ops, +rocksdb::Status Bitmap::bitfield(engine::Context &ctx, const Slice &user_key, const std::vector &ops, std::vector> *rets) { std::string ns_key = AppendNamespacePrefix(user_key); @@ -827,7 +819,7 @@ rocksdb::Status Bitmap::bitfield(const Slice &user_key, const std::vector(cache, ops, rets); + runBitfieldOperationsWithCache(ctx, cache, ops, rets); if constexpr (!ReadOnly) { // Write changes into storage. auto batch = storage_->GetWriteBatchBase(); if (bitfieldWriteAheadLog(batch, ops)) { cache.BatchForFlush(batch); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } } return rocksdb::Status::OK(); } template -rocksdb::Status Bitmap::runBitfieldOperationsWithCache(SegmentCacheStore &cache, +rocksdb::Status Bitmap::runBitfieldOperationsWithCache(engine::Context &ctx, SegmentCacheStore &cache, const std::vector &ops, std::vector> *rets) { ArrayBitfieldBitmap bitfield; @@ -872,7 +864,7 @@ rocksdb::Status Bitmap::runBitfieldOperationsWithCache(SegmentCacheStore &cache, uint32_t last_bytes = (op.offset + op.encoding.Bits() - 1) / 8 + 1; uint32_t bytes = last_bytes - first_byte; - auto segment_status = CopySegmentsBytesToBitfield(cache, first_byte, bytes, &bitfield); + auto segment_status = CopySegmentsBytesToBitfield(ctx, cache, first_byte, bytes, &bitfield); if (!segment_status.ok()) { return segment_status; } @@ -896,7 +888,7 @@ rocksdb::Status Bitmap::runBitfieldOperationsWithCache(SegmentCacheStore &cache, if (BitfieldOp(op, unsigned_old_value, &unsigned_new_value).GetValue()) { if (op.type != BitfieldOperation::Type::kGet) { Status _ = bitfield.SetBitfield(op.offset, op.encoding.Bits(), unsigned_new_value); - s = CopyBitfieldBytesToSegments(cache, bitfield, first_byte, bytes); + s = CopyBitfieldBytesToSegments(ctx, cache, bitfield, first_byte, bytes); if (!s.ok()) { return s; } @@ -913,9 +905,11 @@ rocksdb::Status Bitmap::runBitfieldOperationsWithCache(SegmentCacheStore &cache, return rocksdb::Status::OK(); } -template rocksdb::Status Bitmap::bitfield(const Slice &, const std::vector &, +template rocksdb::Status Bitmap::bitfield(engine::Context &ctx, const Slice &, + const std::vector &, std::vector> *); -template rocksdb::Status Bitmap::bitfield(const Slice &, const std::vector &, +template rocksdb::Status Bitmap::bitfield(engine::Context &ctx, const Slice &, + const std::vector &, std::vector> *); // Return true if there are any write operation to bitmap. Otherwise return false. diff --git a/src/types/redis_bitmap.h b/src/types/redis_bitmap.h index 33e8e8d23d9..32a53cc72ab 100644 --- a/src/types/redis_bitmap.h +++ b/src/types/redis_bitmap.h @@ -46,38 +46,40 @@ class Bitmap : public Database { class SegmentCacheStore; Bitmap(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status GetBit(const Slice &user_key, uint32_t bit_offset, bool *bit); - rocksdb::Status GetString(const Slice &user_key, uint32_t max_btos_size, std::string *value); - rocksdb::Status SetBit(const Slice &user_key, uint32_t bit_offset, bool new_bit, bool *old_bit); - rocksdb::Status BitCount(const Slice &user_key, int64_t start, int64_t stop, bool is_bit_index, uint32_t *cnt); - rocksdb::Status BitPos(const Slice &user_key, bool bit, int64_t start, int64_t stop, bool stop_given, int64_t *pos, - bool is_bit_index); - rocksdb::Status BitOp(BitOpFlags op_flag, const std::string &op_name, const Slice &user_key, + rocksdb::Status GetBit(engine::Context &ctx, const Slice &user_key, uint32_t bit_offset, bool *bit); + rocksdb::Status GetString(engine::Context &ctx, const Slice &user_key, uint32_t max_btos_size, std::string *value); + rocksdb::Status SetBit(engine::Context &ctx, const Slice &user_key, uint32_t bit_offset, bool new_bit, bool *old_bit); + rocksdb::Status BitCount(engine::Context &ctx, const Slice &user_key, int64_t start, int64_t stop, bool is_bit_index, + uint32_t *cnt); + rocksdb::Status BitPos(engine::Context &ctx, const Slice &user_key, bool bit, int64_t start, int64_t stop, + bool stop_given, int64_t *pos, bool is_bit_index); + rocksdb::Status BitOp(engine::Context &ctx, BitOpFlags op_flag, const std::string &op_name, const Slice &user_key, const std::vector &op_keys, int64_t *len); - rocksdb::Status Bitfield(const Slice &user_key, const std::vector &ops, + rocksdb::Status Bitfield(engine::Context &ctx, const Slice &user_key, const std::vector &ops, std::vector> *rets) { - return bitfield(user_key, ops, rets); + return bitfield(ctx, user_key, ops, rets); } // read-only version for Bitfield(), if there is a write operation in ops, the function will return with failed // status. - rocksdb::Status BitfieldReadOnly(const Slice &user_key, const std::vector &ops, + rocksdb::Status BitfieldReadOnly(engine::Context &ctx, const Slice &user_key, + const std::vector &ops, std::vector> *rets) { - return bitfield(user_key, ops, rets); + return bitfield(ctx, user_key, ops, rets); } static bool GetBitFromValueAndOffset(std::string_view value, uint32_t bit_offset); static bool IsEmptySegment(const Slice &segment); private: template - rocksdb::Status bitfield(const Slice &user_key, const std::vector &ops, + rocksdb::Status bitfield(engine::Context &ctx, const Slice &user_key, const std::vector &ops, std::vector> *rets); static bool bitfieldWriteAheadLog(const ObserverOrUniquePtr &batch, const std::vector &ops); - rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &ns_key, BitmapMetadata *metadata, + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, BitmapMetadata *metadata, std::string *raw_value); template - static rocksdb::Status runBitfieldOperationsWithCache(SegmentCacheStore &cache, + static rocksdb::Status runBitfieldOperationsWithCache(engine::Context &ctx, SegmentCacheStore &cache, const std::vector &ops, std::vector> *rets); }; diff --git a/src/types/redis_bitmap_string.cc b/src/types/redis_bitmap_string.cc index b10a5d45d49..1c0dff817ac 100644 --- a/src/types/redis_bitmap_string.cc +++ b/src/types/redis_bitmap_string.cc @@ -43,8 +43,8 @@ rocksdb::Status BitmapString::GetBit(const std::string &raw_value, uint32_t bit_ return rocksdb::Status::OK(); } -rocksdb::Status BitmapString::SetBit(const Slice &ns_key, std::string *raw_value, uint32_t bit_offset, bool new_bit, - bool *old_bit) { +rocksdb::Status BitmapString::SetBit(engine::Context &ctx, const Slice &ns_key, std::string *raw_value, + uint32_t bit_offset, bool new_bit, bool *old_bit) { size_t header_offset = Metadata::GetOffsetAfterExpire((*raw_value)[0]); auto string_value = raw_value->substr(header_offset); uint32_t byte_index = bit_offset >> 3; @@ -61,7 +61,7 @@ rocksdb::Status BitmapString::SetBit(const Slice &ns_key, std::string *raw_value WriteBatchLogData log_data(kRedisString); batch->PutLogData(log_data.Encode()); batch->Put(metadata_cf_handle_, ns_key, *raw_value); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } rocksdb::Status BitmapString::BitCount(const std::string &raw_value, int64_t start, int64_t stop, bool is_bit_index, @@ -200,7 +200,7 @@ std::pair BitmapString::NormalizeToByteRangeWithPaddingMask(bo return {origin_start, origin_end}; } -rocksdb::Status BitmapString::Bitfield(const Slice &ns_key, std::string *raw_value, +rocksdb::Status BitmapString::Bitfield(engine::Context &ctx, const Slice &ns_key, std::string *raw_value, const std::vector &ops, std::vector> *rets) { auto header_offset = Metadata::GetOffsetAfterExpire((*raw_value)[0]); @@ -260,7 +260,7 @@ rocksdb::Status BitmapString::Bitfield(const Slice &ns_key, std::string *raw_val batch->PutLogData(log_data.Encode()); batch->Put(metadata_cf_handle_, ns_key, *raw_value); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } rocksdb::Status BitmapString::BitfieldReadOnly(const Slice &ns_key, const std::string &raw_value, diff --git a/src/types/redis_bitmap_string.h b/src/types/redis_bitmap_string.h index 030415c3492..e644cdabdd5 100644 --- a/src/types/redis_bitmap_string.h +++ b/src/types/redis_bitmap_string.h @@ -35,13 +35,14 @@ class BitmapString : public Database { public: BitmapString(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} static rocksdb::Status GetBit(const std::string &raw_value, uint32_t bit_offset, bool *bit); - rocksdb::Status SetBit(const Slice &ns_key, std::string *raw_value, uint32_t bit_offset, bool new_bit, bool *old_bit); + rocksdb::Status SetBit(engine::Context &ctx, const Slice &ns_key, std::string *raw_value, uint32_t bit_offset, + bool new_bit, bool *old_bit); static rocksdb::Status BitCount(const std::string &raw_value, int64_t start, int64_t stop, bool is_bit_index, uint32_t *cnt); static rocksdb::Status BitPos(const std::string &raw_value, bool bit, int64_t start, int64_t stop, bool stop_given, int64_t *pos, bool is_bit_index); - rocksdb::Status Bitfield(const Slice &ns_key, std::string *raw_value, const std::vector &ops, - std::vector> *rets); + rocksdb::Status Bitfield(engine::Context &ctx, const Slice &ns_key, std::string *raw_value, + const std::vector &ops, std::vector> *rets); static rocksdb::Status BitfieldReadOnly(const Slice &ns_key, const std::string &raw_value, const std::vector &ops, std::vector> *rets); diff --git a/src/types/redis_bloom_chain.cc b/src/types/redis_bloom_chain.cc index 6a4f3860464..cb2bf4bda97 100644 --- a/src/types/redis_bloom_chain.cc +++ b/src/types/redis_bloom_chain.cc @@ -24,9 +24,9 @@ namespace redis { -rocksdb::Status BloomChain::getBloomChainMetadata(Database::GetOptions get_options, const Slice &ns_key, +rocksdb::Status BloomChain::getBloomChainMetadata(engine::Context &ctx, const Slice &ns_key, BloomChainMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisBloomFilter}, ns_key, metadata); + return Database::GetMetadata(ctx, {kRedisBloomFilter}, ns_key, metadata); } std::string BloomChain::getBFKey(const Slice &ns_key, const BloomChainMetadata &metadata, uint16_t filters_index) { @@ -45,16 +45,12 @@ void BloomChain::getBFKeyList(const Slice &ns_key, const BloomChainMetadata &met } } -rocksdb::Status BloomChain::getBFDataList(const std::vector &bf_key_list, +rocksdb::Status BloomChain::getBFDataList(engine::Context &ctx, const std::vector &bf_key_list, std::vector *bf_data_list) { - LatestSnapShot ss(storage_); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); - bf_data_list->reserve(bf_key_list.size()); for (const auto &bf_key : bf_key_list) { rocksdb::PinnableSlice pin_value; - rocksdb::Status s = storage_->Get(read_options, bf_key, &pin_value); + rocksdb::Status s = storage_->Get(ctx, ctx.GetReadOptions(), bf_key, &pin_value); if (!s.ok()) return s; bf_data_list->push_back(std::move(pin_value)); } @@ -68,8 +64,8 @@ void BloomChain::getItemHashList(const std::vector &items, std::vec } } -rocksdb::Status BloomChain::createBloomChain(const Slice &ns_key, double error_rate, uint32_t capacity, - uint16_t expansion, BloomChainMetadata *metadata) { +rocksdb::Status BloomChain::createBloomChain(engine::Context &ctx, const Slice &ns_key, double error_rate, + uint32_t capacity, uint16_t expansion, BloomChainMetadata *metadata) { metadata->n_filters = 1; metadata->expansion = expansion; metadata->size = 0; @@ -91,7 +87,7 @@ rocksdb::Status BloomChain::createBloomChain(const Slice &ns_key, double error_r std::string bf_key = getBFKey(ns_key, *metadata, metadata->n_filters - 1); batch->Put(bf_key, block_split_bloom_filter.GetData()); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } void BloomChain::createBloomFilterInBatch(const Slice &ns_key, BloomChainMetadata *metadata, @@ -120,44 +116,47 @@ bool BloomChain::bloomCheck(uint64_t item_hash, std::string_view &bf_data) { return block_split_bloom_filter.FindHash(item_hash); } -rocksdb::Status BloomChain::Reserve(const Slice &user_key, uint32_t capacity, double error_rate, uint16_t expansion) { +rocksdb::Status BloomChain::Reserve(engine::Context &ctx, const Slice &user_key, uint32_t capacity, double error_rate, + uint16_t expansion) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); BloomChainMetadata bloom_chain_metadata; - rocksdb::Status s = getBloomChainMetadata(GetOptions{}, ns_key, &bloom_chain_metadata); + rocksdb::Status s = getBloomChainMetadata(ctx, ns_key, &bloom_chain_metadata); if (!s.ok() && !s.IsNotFound()) return s; if (!s.IsNotFound()) { return rocksdb::Status::InvalidArgument("the key already exists"); } - return createBloomChain(ns_key, error_rate, capacity, expansion, &bloom_chain_metadata); + return createBloomChain(ctx, ns_key, error_rate, capacity, expansion, &bloom_chain_metadata); } -rocksdb::Status BloomChain::Add(const Slice &user_key, const std::string &item, BloomFilterAddResult *ret) { +rocksdb::Status BloomChain::Add(engine::Context &ctx, const Slice &user_key, const std::string &item, + BloomFilterAddResult *ret) { std::vector tmp{BloomFilterAddResult::kOk}; - rocksdb::Status s = MAdd(user_key, {item}, &tmp); + rocksdb::Status s = MAdd(ctx, user_key, {item}, &tmp); *ret = tmp[0]; return s; } -rocksdb::Status BloomChain::MAdd(const Slice &user_key, const std::vector &items, +rocksdb::Status BloomChain::MAdd(engine::Context &ctx, const Slice &user_key, const std::vector &items, std::vector *rets) { BloomFilterInsertOptions insert_options; - return InsertCommon(user_key, items, insert_options, rets); + return InsertCommon(ctx, user_key, items, insert_options, rets); } -rocksdb::Status BloomChain::InsertCommon(const Slice &user_key, const std::vector &items, +rocksdb::Status BloomChain::InsertCommon(engine::Context &ctx, const Slice &user_key, + const std::vector &items, const BloomFilterInsertOptions &insert_options, std::vector *rets) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); BloomChainMetadata metadata; - rocksdb::Status s = getBloomChainMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = getBloomChainMetadata(ctx, ns_key, &metadata); if (s.IsNotFound() && insert_options.auto_create) { - s = createBloomChain(ns_key, insert_options.error_rate, insert_options.capacity, insert_options.expansion, + s = createBloomChain(ctx, ns_key, insert_options.error_rate, insert_options.capacity, insert_options.expansion, &metadata); } if (!s.ok()) return s; @@ -166,7 +165,7 @@ rocksdb::Status BloomChain::InsertCommon(const Slice &user_key, const std::vecto getBFKeyList(ns_key, metadata, &bf_key_list); std::vector bf_data_list; - s = getBFDataList(bf_key_list, &bf_data_list); + s = getBFDataList(ctx, bf_key_list, &bf_data_list); if (!s.ok()) return s; std::vector item_hash_list; @@ -221,22 +220,22 @@ rocksdb::Status BloomChain::InsertCommon(const Slice &user_key, const std::vecto batch->Put(metadata_cf_handle_, ns_key, bloom_chain_metadata_bytes); batch->Put(bf_key_list.back(), bf_data_list.back().ToStringView()); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status BloomChain::Exists(const Slice &user_key, const std::string &item, bool *exist) { +rocksdb::Status BloomChain::Exists(engine::Context &ctx, const Slice &user_key, const std::string &item, bool *exist) { std::vector tmp{false}; - rocksdb::Status s = MExists(user_key, {item}, &tmp); + rocksdb::Status s = MExists(ctx, user_key, {item}, &tmp); *exist = tmp[0]; return s; } -rocksdb::Status BloomChain::MExists(const Slice &user_key, const std::vector &items, +rocksdb::Status BloomChain::MExists(engine::Context &ctx, const Slice &user_key, const std::vector &items, std::vector *exists) { std::string ns_key = AppendNamespacePrefix(user_key); BloomChainMetadata metadata; - rocksdb::Status s = getBloomChainMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = getBloomChainMetadata(ctx, ns_key, &metadata); if (s.IsNotFound()) { std::fill(exists->begin(), exists->end(), false); return rocksdb::Status::OK(); @@ -247,7 +246,7 @@ rocksdb::Status BloomChain::MExists(const Slice &user_key, const std::vector bf_data_list; - s = getBFDataList(bf_key_list, &bf_data_list); + s = getBFDataList(ctx, bf_key_list, &bf_data_list); if (!s.ok()) return s; std::vector item_hash_list; @@ -266,11 +265,11 @@ rocksdb::Status BloomChain::MExists(const Slice &user_key, const std::vectorcapacity = metadata.GetCapacity(); diff --git a/src/types/redis_bloom_chain.h b/src/types/redis_bloom_chain.h index 6f5f76da63f..ff7d80d08a0 100644 --- a/src/types/redis_bloom_chain.h +++ b/src/types/redis_bloom_chain.h @@ -63,27 +63,28 @@ struct BloomFilterInfo { class BloomChain : public Database { public: BloomChain(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Reserve(const Slice &user_key, uint32_t capacity, double error_rate, uint16_t expansion); - rocksdb::Status Add(const Slice &user_key, const std::string &item, BloomFilterAddResult *ret); - rocksdb::Status MAdd(const Slice &user_key, const std::vector &items, + rocksdb::Status Reserve(engine::Context &ctx, const Slice &user_key, uint32_t capacity, double error_rate, + uint16_t expansion); + rocksdb::Status Add(engine::Context &ctx, const Slice &user_key, const std::string &item, BloomFilterAddResult *ret); + rocksdb::Status MAdd(engine::Context &ctx, const Slice &user_key, const std::vector &items, std::vector *rets); - rocksdb::Status InsertCommon(const Slice &user_key, const std::vector &items, + rocksdb::Status InsertCommon(engine::Context &ctx, const Slice &user_key, const std::vector &items, const BloomFilterInsertOptions &insert_options, std::vector *rets); - rocksdb::Status Exists(const Slice &user_key, const std::string &item, bool *exist); - rocksdb::Status MExists(const Slice &user_key, const std::vector &items, std::vector *exists); - rocksdb::Status Info(const Slice &user_key, BloomFilterInfo *info); + rocksdb::Status Exists(engine::Context &ctx, const Slice &user_key, const std::string &item, bool *exist); + rocksdb::Status MExists(engine::Context &ctx, const Slice &user_key, const std::vector &items, + std::vector *exists); + rocksdb::Status Info(engine::Context &ctx, const Slice &user_key, BloomFilterInfo *info); private: - rocksdb::Status getBloomChainMetadata(Database::GetOptions get_options, const Slice &ns_key, - BloomChainMetadata *metadata); + rocksdb::Status getBloomChainMetadata(engine::Context &ctx, const Slice &ns_key, BloomChainMetadata *metadata); std::string getBFKey(const Slice &ns_key, const BloomChainMetadata &metadata, uint16_t filters_index); void getBFKeyList(const Slice &ns_key, const BloomChainMetadata &metadata, std::vector *bf_key_list); - rocksdb::Status getBFDataList(const std::vector &bf_key_list, + rocksdb::Status getBFDataList(engine::Context &ctx, const std::vector &bf_key_list, std::vector *bf_data_list); static void getItemHashList(const std::vector &items, std::vector *item_hash_list); - rocksdb::Status createBloomChain(const Slice &ns_key, double error_rate, uint32_t capacity, uint16_t expansion, - BloomChainMetadata *metadata); + rocksdb::Status createBloomChain(engine::Context &ctx, const Slice &ns_key, double error_rate, uint32_t capacity, + uint16_t expansion, BloomChainMetadata *metadata); void createBloomFilterInBatch(const Slice &ns_key, BloomChainMetadata *metadata, ObserverOrUniquePtr &batch, std::string *bf_data); diff --git a/src/types/redis_geo.cc b/src/types/redis_geo.cc index 966e082f729..2bdac0f5aa0 100644 --- a/src/types/redis_geo.cc +++ b/src/types/redis_geo.cc @@ -24,7 +24,8 @@ namespace redis { -rocksdb::Status Geo::Add(const Slice &user_key, std::vector *geo_points, uint64_t *added_cnt) { +rocksdb::Status Geo::Add(engine::Context &ctx, const Slice &user_key, std::vector *geo_points, + uint64_t *added_cnt) { std::vector member_scores; for (const auto &geo_point : *geo_points) { /* Turn the coordinates into the score of the element. */ @@ -33,12 +34,13 @@ rocksdb::Status Geo::Add(const Slice &user_key, std::vector *geo_point GeoHashFix52Bits bits = GeoHashHelper::Align52Bits(hash); member_scores.emplace_back(MemberScore{geo_point.member, static_cast(bits)}); } - return ZSet::Add(user_key, ZAddFlags::Default(), &member_scores, added_cnt); + return ZSet::Add(ctx, user_key, ZAddFlags::Default(), &member_scores, added_cnt); } -rocksdb::Status Geo::Dist(const Slice &user_key, const Slice &member_1, const Slice &member_2, double *dist) { +rocksdb::Status Geo::Dist(engine::Context &ctx, const Slice &user_key, const Slice &member_1, const Slice &member_2, + double *dist) { std::map geo_points; - auto s = MGet(user_key, {member_1, member_2}, &geo_points); + auto s = MGet(ctx, user_key, {member_1, member_2}, &geo_points); if (!s.ok()) return s; for (const auto &member : {member_1, member_2}) { @@ -53,10 +55,10 @@ rocksdb::Status Geo::Dist(const Slice &user_key, const Slice &member_1, const Sl return rocksdb::Status::OK(); } -rocksdb::Status Geo::Hash(const Slice &user_key, const std::vector &members, +rocksdb::Status Geo::Hash(engine::Context &ctx, const Slice &user_key, const std::vector &members, std::vector *geo_hashes) { std::map geo_points; - auto s = MGet(user_key, members, &geo_points); + auto s = MGet(ctx, user_key, members, &geo_points); if (!s.ok()) return s; for (const auto &member : members) { @@ -71,14 +73,14 @@ rocksdb::Status Geo::Hash(const Slice &user_key, const std::vector &membe return rocksdb::Status::OK(); } -rocksdb::Status Geo::Pos(const Slice &user_key, const std::vector &members, +rocksdb::Status Geo::Pos(engine::Context &ctx, const Slice &user_key, const std::vector &members, std::map *geo_points) { - return MGet(user_key, members, geo_points); + return MGet(ctx, user_key, members, geo_points); } -rocksdb::Status Geo::Radius(const Slice &user_key, double longitude, double latitude, double radius_meters, int count, - DistanceSort sort, const std::string &store_key, bool store_distance, - double unit_conversion, std::vector *geo_points) { +rocksdb::Status Geo::Radius(engine::Context &ctx, const Slice &user_key, double longitude, double latitude, + double radius_meters, int count, DistanceSort sort, const std::string &store_key, + bool store_distance, double unit_conversion, std::vector *geo_points) { GeoShape geo_shape; geo_shape.type = kGeoShapeTypeCircular; geo_shape.xy[0] = longitude; @@ -87,37 +89,38 @@ rocksdb::Status Geo::Radius(const Slice &user_key, double longitude, double lati geo_shape.conversion = 1; std::string dummy_member; - return SearchStore(user_key, geo_shape, kLongLat, dummy_member, count, sort, store_key, store_distance, + return SearchStore(ctx, user_key, geo_shape, kLongLat, dummy_member, count, sort, store_key, store_distance, unit_conversion, geo_points); } -rocksdb::Status Geo::RadiusByMember(const Slice &user_key, const Slice &member, double radius_meters, int count, - DistanceSort sort, const std::string &store_key, bool store_distance, - double unit_conversion, std::vector *geo_points) { +rocksdb::Status Geo::RadiusByMember(engine::Context &ctx, const Slice &user_key, const Slice &member, + double radius_meters, int count, DistanceSort sort, const std::string &store_key, + bool store_distance, double unit_conversion, std::vector *geo_points) { GeoPoint geo_point; - auto s = Get(user_key, member, &geo_point); + auto s = Get(ctx, user_key, member, &geo_point); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; - return Radius(user_key, geo_point.longitude, geo_point.latitude, radius_meters, count, sort, store_key, + return Radius(ctx, user_key, geo_point.longitude, geo_point.latitude, radius_meters, count, sort, store_key, store_distance, unit_conversion, geo_points); } -rocksdb::Status Geo::Search(const Slice &user_key, GeoShape geo_shape, OriginPointType point_type, std::string &member, - int count, DistanceSort sort, bool store_distance, double unit_conversion, - std::vector *geo_points) { - return SearchStore(user_key, geo_shape, point_type, member, count, sort, "", store_distance, unit_conversion, +rocksdb::Status Geo::Search(engine::Context &ctx, const Slice &user_key, GeoShape geo_shape, OriginPointType point_type, + std::string &member, int count, DistanceSort sort, bool store_distance, + double unit_conversion, std::vector *geo_points) { + return SearchStore(ctx, user_key, geo_shape, point_type, member, count, sort, "", store_distance, unit_conversion, geo_points); } -rocksdb::Status Geo::SearchStore(const Slice &user_key, GeoShape geo_shape, OriginPointType point_type, - std::string &member, int count, DistanceSort sort, const std::string &store_key, - bool store_distance, double unit_conversion, std::vector *geo_points) { +rocksdb::Status Geo::SearchStore(engine::Context &ctx, const Slice &user_key, GeoShape geo_shape, + OriginPointType point_type, std::string &member, int count, DistanceSort sort, + const std::string &store_key, bool store_distance, double unit_conversion, + std::vector *geo_points) { if (point_type == kMember) { GeoPoint geo_point; - auto s = Get(user_key, member, &geo_point); + auto s = Get(ctx, user_key, member, &geo_point); // store key is not empty, try to remove it before returning. if (!s.ok() && s.IsNotFound() && !store_key.empty()) { - auto del_s = ZSet::Del(store_key); + auto del_s = ZSet::Del(ctx, store_key); if (!del_s.ok()) return del_s; } if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; @@ -128,10 +131,10 @@ rocksdb::Status Geo::SearchStore(const Slice &user_key, GeoShape geo_shape, Orig std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - rocksdb::Status s = ZSet::GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = ZSet::GetMetadata(ctx, ns_key, &metadata); // store key is not empty, try to remove it before returning. if (!s.ok() && s.IsNotFound() && !store_key.empty()) { - auto del_s = ZSet::Del(store_key); + auto del_s = ZSet::Del(ctx, store_key); if (!del_s.ok()) return del_s; } if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; @@ -140,13 +143,13 @@ rocksdb::Status Geo::SearchStore(const Slice &user_key, GeoShape geo_shape, Orig GeoHashRadius georadius = GeoHashHelper::GetAreasByShapeWGS84(geo_shape); // Get zset for all matching points - membersOfAllNeighbors(user_key, georadius, geo_shape, geo_points); + membersOfAllNeighbors(ctx, user_key, georadius, geo_shape, geo_points); // if no matching results, give empty reply if (geo_points->empty()) { // store key is not empty, try to remove it before returning. if (!store_key.empty()) { - auto del_s = ZSet::Del(store_key); + auto del_s = ZSet::Del(ctx, store_key); if (!del_s.ok()) return del_s; } return rocksdb::Status::OK(); @@ -164,7 +167,7 @@ rocksdb::Status Geo::SearchStore(const Slice &user_key, GeoShape geo_shape, Orig auto result_length = static_cast(geo_points->size()); int64_t returned_items_count = (count == 0 || result_length < count) ? result_length : count; if (returned_items_count == 0) { - auto s = ZSet::Del(user_key); + auto s = ZSet::Del(ctx, user_key); if (!s.ok()) return s; } else { std::vector member_scores; @@ -175,15 +178,15 @@ rocksdb::Status Geo::SearchStore(const Slice &user_key, GeoShape geo_shape, Orig double score = store_distance ? geo_point.dist / unit_conversion : geo_point.score; member_scores.emplace_back(MemberScore{geo_point.member, score}); } - ZSet::Overwrite(store_key, member_scores); + ZSet::Overwrite(ctx, store_key, member_scores); } } return rocksdb::Status::OK(); } -rocksdb::Status Geo::Get(const Slice &user_key, const Slice &member, GeoPoint *geo_point) { +rocksdb::Status Geo::Get(engine::Context &ctx, const Slice &user_key, const Slice &member, GeoPoint *geo_point) { std::map geo_points; - auto s = MGet(user_key, {member}, &geo_points); + auto s = MGet(ctx, user_key, {member}, &geo_points); if (!s.ok()) return s; auto iter = geo_points.find(member.ToString()); @@ -194,10 +197,10 @@ rocksdb::Status Geo::Get(const Slice &user_key, const Slice &member, GeoPoint *g return rocksdb::Status::OK(); } -rocksdb::Status Geo::MGet(const Slice &user_key, const std::vector &members, +rocksdb::Status Geo::MGet(engine::Context &ctx, const Slice &user_key, const std::vector &members, std::map *geo_points) { std::map member_scores; - auto s = ZSet::MGet(user_key, members, &member_scores); + auto s = ZSet::MGet(ctx, user_key, members, &member_scores); if (!s.ok()) return s; for (const auto &member : members) { @@ -253,7 +256,7 @@ int Geo::decodeGeoHash(double bits, double *xy) { } /* Search all eight neighbors + self geohash box */ -int Geo::membersOfAllNeighbors(const Slice &user_key, GeoHashRadius n, const GeoShape &geo_shape, +int Geo::membersOfAllNeighbors(engine::Context &ctx, const Slice &user_key, GeoHashRadius n, const GeoShape &geo_shape, std::vector *geo_points) { GeoHashBits neighbors[9]; unsigned int last_processed = 0; @@ -284,7 +287,7 @@ int Geo::membersOfAllNeighbors(const Slice &user_key, GeoHashRadius n, const Geo neighbors[i].step == neighbors[last_processed].step) { continue; } - count += membersOfGeoHashBox(user_key, neighbors[i], geo_points, geo_shape); + count += membersOfGeoHashBox(ctx, user_key, neighbors[i], geo_points, geo_shape); last_processed = i; } return count; @@ -293,12 +296,12 @@ int Geo::membersOfAllNeighbors(const Slice &user_key, GeoHashRadius n, const Geo /* Obtain all members between the min/max of this geohash bounding box. * Populate a GeoArray of GeoPoints by calling getPointsInRange(). * Return the number of points added to the array. */ -int Geo::membersOfGeoHashBox(const Slice &user_key, GeoHashBits hash, std::vector *geo_points, - const GeoShape &geo_shape) { +int Geo::membersOfGeoHashBox(engine::Context &ctx, const Slice &user_key, GeoHashBits hash, + std::vector *geo_points, const GeoShape &geo_shape) { GeoHashFix52Bits min = 0, max = 0; scoresOfGeoHashBox(hash, &min, &max); - return getPointsInRange(user_key, static_cast(min), static_cast(max), geo_shape, geo_points); + return getPointsInRange(ctx, user_key, static_cast(min), static_cast(max), geo_shape, geo_points); } /* Compute the sorted set scores min (inclusive), max (exclusive) we should @@ -342,8 +345,8 @@ void Geo::scoresOfGeoHashBox(GeoHashBits hash, GeoHashFix52Bits *min, GeoHashFix * using multiple queries to the sorted set, that we later need to sort * via qsort. Similarly we need to be able to reject points outside the search * radius area ASAP in order to allocate and process more points than needed. */ -int Geo::getPointsInRange(const Slice &user_key, double min, double max, const GeoShape &geo_shape, - std::vector *geo_points) { +int Geo::getPointsInRange(engine::Context &ctx, const Slice &user_key, double min, double max, + const GeoShape &geo_shape, std::vector *geo_points) { /* include min in range; exclude max in range */ /* That's: min <= val < max */ RangeScoreSpec spec; @@ -352,7 +355,7 @@ int Geo::getPointsInRange(const Slice &user_key, double min, double max, const G spec.maxex = true; uint64_t size = 0; std::vector member_scores; - rocksdb::Status s = ZSet::RangeByScore(user_key, spec, &member_scores, &size); + rocksdb::Status s = ZSet::RangeByScore(ctx, user_key, spec, &member_scores, &size); if (!s.ok()) return 0; for (const auto &member_score : member_scores) { diff --git a/src/types/redis_geo.h b/src/types/redis_geo.h index c73f580f8a9..05d31e8651f 100644 --- a/src/types/redis_geo.h +++ b/src/types/redis_geo.h @@ -59,36 +59,40 @@ namespace redis { class Geo : public ZSet { public: explicit Geo(engine::Storage *storage, const std::string &ns) : ZSet(storage, ns) {} - rocksdb::Status Add(const Slice &user_key, std::vector *geo_points, uint64_t *added_cnt); - rocksdb::Status Dist(const Slice &user_key, const Slice &member_1, const Slice &member_2, double *dist); - rocksdb::Status Hash(const Slice &user_key, const std::vector &members, std::vector *geo_hashes); - rocksdb::Status Pos(const Slice &user_key, const std::vector &members, + rocksdb::Status Add(engine::Context &ctx, const Slice &user_key, std::vector *geo_points, + uint64_t *added_cnt); + rocksdb::Status Dist(engine::Context &ctx, const Slice &user_key, const Slice &member_1, const Slice &member_2, + double *dist); + rocksdb::Status Hash(engine::Context &ctx, const Slice &user_key, const std::vector &members, + std::vector *geo_hashes); + rocksdb::Status Pos(engine::Context &ctx, const Slice &user_key, const std::vector &members, std::map *geo_points); - rocksdb::Status Radius(const Slice &user_key, double longitude, double latitude, double radius_meters, int count, - DistanceSort sort, const std::string &store_key, bool store_distance, double unit_conversion, - std::vector *geo_points); - rocksdb::Status RadiusByMember(const Slice &user_key, const Slice &member, double radius_meters, int count, - DistanceSort sort, const std::string &store_key, bool store_distance, + rocksdb::Status Radius(engine::Context &ctx, const Slice &user_key, double longitude, double latitude, + double radius_meters, int count, DistanceSort sort, const std::string &store_key, + bool store_distance, double unit_conversion, std::vector *geo_points); + rocksdb::Status RadiusByMember(engine::Context &ctx, const Slice &user_key, const Slice &member, double radius_meters, + int count, DistanceSort sort, const std::string &store_key, bool store_distance, double unit_conversion, std::vector *geo_points); - rocksdb::Status Search(const Slice &user_key, GeoShape geo_shape, OriginPointType point_type, std::string &member, - int count, DistanceSort sort, bool store_distance, double unit_conversion, + rocksdb::Status Search(engine::Context &ctx, const Slice &user_key, GeoShape geo_shape, OriginPointType point_type, + std::string &member, int count, DistanceSort sort, bool store_distance, double unit_conversion, std::vector *geo_points); - rocksdb::Status SearchStore(const Slice &user_key, GeoShape geo_shape, OriginPointType point_type, - std::string &member, int count, DistanceSort sort, const std::string &store_key, - bool store_distance, double unit_conversion, std::vector *geo_points); - rocksdb::Status Get(const Slice &user_key, const Slice &member, GeoPoint *geo_point); - rocksdb::Status MGet(const Slice &user_key, const std::vector &members, + rocksdb::Status SearchStore(engine::Context &ctx, const Slice &user_key, GeoShape geo_shape, + OriginPointType point_type, std::string &member, int count, DistanceSort sort, + const std::string &store_key, bool store_distance, double unit_conversion, + std::vector *geo_points); + rocksdb::Status Get(engine::Context &ctx, const Slice &user_key, const Slice &member, GeoPoint *geo_point); + rocksdb::Status MGet(engine::Context &ctx, const Slice &user_key, const std::vector &members, std::map *geo_points); static std::string EncodeGeoHash(double longitude, double latitude); private: static int decodeGeoHash(double bits, double *xy); - int membersOfAllNeighbors(const Slice &user_key, GeoHashRadius n, const GeoShape &geo_shape, + int membersOfAllNeighbors(engine::Context &ctx, const Slice &user_key, GeoHashRadius n, const GeoShape &geo_shape, std::vector *geo_points); - int membersOfGeoHashBox(const Slice &user_key, GeoHashBits hash, std::vector *geo_points, - const GeoShape &geo_shape); + int membersOfGeoHashBox(engine::Context &ctx, const Slice &user_key, GeoHashBits hash, + std::vector *geo_points, const GeoShape &geo_shape); static void scoresOfGeoHashBox(GeoHashBits hash, GeoHashFix52Bits *min, GeoHashFix52Bits *max); - int getPointsInRange(const Slice &user_key, double min, double max, const GeoShape &geo_shape, + int getPointsInRange(engine::Context &ctx, const Slice &user_key, double min, double max, const GeoShape &geo_shape, std::vector *geo_points); static bool appendIfWithinRadius(std::vector *geo_points, double lon, double lat, double radius, double score, const std::string &member); diff --git a/src/types/redis_hash.cc b/src/types/redis_hash.cc index c4d60685934..6bbb14fe759 100644 --- a/src/types/redis_hash.cc +++ b/src/types/redis_hash.cc @@ -34,34 +34,33 @@ namespace redis { -rocksdb::Status Hash::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, HashMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisHash}, ns_key, metadata); +rocksdb::Status Hash::GetMetadata(engine::Context &ctx, const Slice &ns_key, HashMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisHash}, ns_key, metadata); } -rocksdb::Status Hash::Size(const Slice &user_key, uint64_t *size) { +rocksdb::Status Hash::Size(engine::Context &ctx, const Slice &user_key, uint64_t *size) { *size = 0; std::string ns_key = AppendNamespacePrefix(user_key); HashMetadata metadata(false); - rocksdb::Status s = GetMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; *size = metadata.size; return rocksdb::Status::OK(); } -rocksdb::Status Hash::Get(const Slice &user_key, const Slice &field, std::string *value) { +rocksdb::Status Hash::Get(engine::Context &ctx, const Slice &user_key, const Slice &field, std::string *value) { std::string ns_key = AppendNamespacePrefix(user_key); HashMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(Database::GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string sub_key = InternalKey(ns_key, field, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - return storage_->Get(read_options, sub_key, value); + return storage_->Get(ctx, ctx.GetReadOptions(), sub_key, value); } -rocksdb::Status Hash::IncrBy(const Slice &user_key, const Slice &field, int64_t increment, int64_t *new_value) { +rocksdb::Status Hash::IncrBy(engine::Context &ctx, const Slice &user_key, const Slice &field, int64_t increment, + int64_t *new_value) { bool exists = false; int64_t old_value = 0; @@ -69,13 +68,13 @@ rocksdb::Status Hash::IncrBy(const Slice &user_key, const Slice &field, int64_t LockGuard guard(storage_->GetLockManager(), ns_key); HashMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; std::string sub_key = InternalKey(ns_key, field, metadata.version, storage_->IsSlotIdEncoded()).Encode(); if (s.ok()) { std::string value_bytes; - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value_bytes); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value_bytes); if (!s.ok() && !s.IsNotFound()) return s; if (s.ok()) { auto parse_result = ParseInt(value_bytes, 10); @@ -105,10 +104,11 @@ rocksdb::Status Hash::IncrBy(const Slice &user_key, const Slice &field, int64_t metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Hash::IncrByFloat(const Slice &user_key, const Slice &field, double increment, double *new_value) { +rocksdb::Status Hash::IncrByFloat(engine::Context &ctx, const Slice &user_key, const Slice &field, double increment, + double *new_value) { bool exists = false; double old_value = 0; @@ -116,13 +116,13 @@ rocksdb::Status Hash::IncrByFloat(const Slice &user_key, const Slice &field, dou LockGuard guard(storage_->GetLockManager(), ns_key); HashMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; std::string sub_key = InternalKey(ns_key, field, metadata.version, storage_->IsSlotIdEncoded()).Encode(); if (s.ok()) { std::string value_bytes; - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value_bytes); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value_bytes); if (!s.ok() && !s.IsNotFound()) return s; if (s.ok()) { auto value_stat = ParseFloat(value_bytes); @@ -149,24 +149,22 @@ rocksdb::Status Hash::IncrByFloat(const Slice &user_key, const Slice &field, dou metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Hash::MGet(const Slice &user_key, const std::vector &fields, std::vector *values, - std::vector *statuses) { +rocksdb::Status Hash::MGet(engine::Context &ctx, const Slice &user_key, const std::vector &fields, + std::vector *values, std::vector *statuses) { values->clear(); statuses->clear(); std::string ns_key = AppendNamespacePrefix(user_key); HashMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s; } - rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultMultiGetOptions(); std::vector keys; keys.reserve(fields.size()); @@ -182,7 +180,7 @@ rocksdb::Status Hash::MGet(const Slice &user_key, const std::vector &fiel values_vector.resize(keys.size()); std::vector statuses_vector; statuses_vector.resize(keys.size()); - storage_->MultiGet(read_options, storage_->GetDB()->DefaultColumnFamily(), keys.size(), keys.data(), + storage_->MultiGet(ctx, read_options, storage_->GetDB()->DefaultColumnFamily(), keys.size(), keys.data(), values_vector.data(), statuses_vector.data()); for (size_t i = 0; i < keys.size(); i++) { if (!statuses_vector[i].ok() && !statuses_vector[i].IsNotFound()) return statuses_vector[i]; @@ -192,11 +190,13 @@ rocksdb::Status Hash::MGet(const Slice &user_key, const std::vector &fiel return rocksdb::Status::OK(); } -rocksdb::Status Hash::Set(const Slice &user_key, const Slice &field, const Slice &value, uint64_t *added_cnt) { - return MSet(user_key, {{field.ToString(), value.ToString()}}, false, added_cnt); +rocksdb::Status Hash::Set(engine::Context &ctx, const Slice &user_key, const Slice &field, const Slice &value, + uint64_t *added_cnt) { + return MSet(ctx, user_key, {{field.ToString(), value.ToString()}}, false, added_cnt); } -rocksdb::Status Hash::Delete(const Slice &user_key, const std::vector &fields, uint64_t *deleted_cnt) { +rocksdb::Status Hash::Delete(engine::Context &ctx, const Slice &user_key, const std::vector &fields, + uint64_t *deleted_cnt) { *deleted_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); @@ -205,7 +205,7 @@ rocksdb::Status Hash::Delete(const Slice &user_key, const std::vector &fi WriteBatchLogData log_data(kRedisHash); batch->PutLogData(log_data.Encode()); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string value; @@ -215,7 +215,7 @@ rocksdb::Status Hash::Delete(const Slice &user_key, const std::vector &fi continue; } std::string sub_key = InternalKey(ns_key, field, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (s.ok()) { *deleted_cnt += 1; batch->Delete(sub_key); @@ -228,17 +228,17 @@ rocksdb::Status Hash::Delete(const Slice &user_key, const std::vector &fi std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Hash::MSet(const Slice &user_key, const std::vector &field_values, bool nx, - uint64_t *added_cnt) { +rocksdb::Status Hash::MSet(engine::Context &ctx, const Slice &user_key, const std::vector &field_values, + bool nx, uint64_t *added_cnt) { *added_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); HashMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; int added = 0; @@ -256,7 +256,7 @@ rocksdb::Status Hash::MSet(const Slice &user_key, const std::vector if (metadata.size > 0) { std::string field_value; - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &field_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &field_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.ok()) { @@ -279,10 +279,10 @@ rocksdb::Status Hash::MSet(const Slice &user_key, const std::vector batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Hash::RangeByLex(const Slice &user_key, const RangeLexSpec &spec, +rocksdb::Status Hash::RangeByLex(engine::Context &ctx, const Slice &user_key, const RangeLexSpec &spec, std::vector *field_values) { field_values->clear(); if (spec.count == 0) { @@ -290,8 +290,7 @@ rocksdb::Status Hash::RangeByLex(const Slice &user_key, const RangeLexSpec &spec } std::string ns_key = AppendNamespacePrefix(user_key); HashMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string start_member = spec.reversed ? spec.max : spec.min; @@ -299,14 +298,13 @@ rocksdb::Status Hash::RangeByLex(const Slice &user_key, const RangeLexSpec &spec std::string prefix_key = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); if (!spec.reversed) { iter->Seek(start_key); } else { @@ -341,25 +339,24 @@ rocksdb::Status Hash::RangeByLex(const Slice &user_key, const RangeLexSpec &spec return rocksdb::Status::OK(); } -rocksdb::Status Hash::GetAll(const Slice &user_key, std::vector *field_values, HashFetchType type) { +rocksdb::Status Hash::GetAll(engine::Context &ctx, const Slice &user_key, std::vector *field_values, + HashFetchType type) { field_values->clear(); std::string ns_key = AppendNamespacePrefix(user_key); HashMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string prefix_key = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (iter->Seek(prefix_key); iter->Valid() && iter->key().starts_with(prefix_key); iter->Next()) { if (type == HashFetchType::kOnlyKey) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); @@ -374,20 +371,20 @@ rocksdb::Status Hash::GetAll(const Slice &user_key, std::vector *fie return rocksdb::Status::OK(); } -rocksdb::Status Hash::Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, +rocksdb::Status Hash::Scan(engine::Context &ctx, const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &field_prefix, std::vector *fields, std::vector *values) { - return SubKeyScanner::Scan(kRedisHash, user_key, cursor, limit, field_prefix, fields, values); + return SubKeyScanner::Scan(ctx, kRedisHash, user_key, cursor, limit, field_prefix, fields, values); } -rocksdb::Status Hash::RandField(const Slice &user_key, int64_t command_count, std::vector *field_values, - HashFetchType type) { +rocksdb::Status Hash::RandField(engine::Context &ctx, const Slice &user_key, int64_t command_count, + std::vector *field_values, HashFetchType type) { uint64_t count = (command_count >= 0) ? static_cast(command_count) : static_cast(-command_count); bool unique = (command_count >= 0); std::string ns_key = AppendNamespacePrefix(user_key); HashMetadata metadata(/*generate_version=*/false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; std::vector samples; @@ -395,7 +392,9 @@ rocksdb::Status Hash::RandField(const Slice &user_key, int64_t command_count, st if (count == 0) return rocksdb::Status::OK(); s = ExtractRandMemberFromSet( unique, count, - [this, user_key, type](std::vector *elements) { return this->GetAll(user_key, elements, type); }, + [this, user_key, type, &ctx](std::vector *elements) { + return this->GetAll(ctx, user_key, elements, type); + }, field_values); if (!s.ok()) { return s; diff --git a/src/types/redis_hash.h b/src/types/redis_hash.h index 10fc7d54502..e5779c7c49c 100644 --- a/src/types/redis_hash.h +++ b/src/types/redis_hash.h @@ -45,27 +45,32 @@ class Hash : public SubKeyScanner { public: Hash(engine::Storage *storage, const std::string &ns) : SubKeyScanner(storage, ns) {} - rocksdb::Status Size(const Slice &user_key, uint64_t *size); - rocksdb::Status Get(const Slice &user_key, const Slice &field, std::string *value); - rocksdb::Status Set(const Slice &user_key, const Slice &field, const Slice &value, uint64_t *added_cnt); - rocksdb::Status Delete(const Slice &user_key, const std::vector &fields, uint64_t *deleted_cnt); - rocksdb::Status IncrBy(const Slice &user_key, const Slice &field, int64_t increment, int64_t *new_value); - rocksdb::Status IncrByFloat(const Slice &user_key, const Slice &field, double increment, double *new_value); - rocksdb::Status MSet(const Slice &user_key, const std::vector &field_values, bool nx, - uint64_t *added_cnt); - rocksdb::Status RangeByLex(const Slice &user_key, const RangeLexSpec &spec, std::vector *field_values); - rocksdb::Status MGet(const Slice &user_key, const std::vector &fields, std::vector *values, - std::vector *statuses); - rocksdb::Status GetAll(const Slice &user_key, std::vector *field_values, + rocksdb::Status Size(engine::Context &ctx, const Slice &user_key, uint64_t *size); + rocksdb::Status Get(engine::Context &ctx, const Slice &user_key, const Slice &field, std::string *value); + rocksdb::Status Set(engine::Context &ctx, const Slice &user_key, const Slice &field, const Slice &value, + uint64_t *added_cnt); + rocksdb::Status Delete(engine::Context &ctx, const Slice &user_key, const std::vector &fields, + uint64_t *deleted_cnt); + rocksdb::Status IncrBy(engine::Context &ctx, const Slice &user_key, const Slice &field, int64_t increment, + int64_t *new_value); + rocksdb::Status IncrByFloat(engine::Context &ctx, const Slice &user_key, const Slice &field, double increment, + double *new_value); + rocksdb::Status MSet(engine::Context &ctx, const Slice &user_key, const std::vector &field_values, + bool nx, uint64_t *added_cnt); + rocksdb::Status RangeByLex(engine::Context &ctx, const Slice &user_key, const RangeLexSpec &spec, + std::vector *field_values); + rocksdb::Status MGet(engine::Context &ctx, const Slice &user_key, const std::vector &fields, + std::vector *values, std::vector *statuses); + rocksdb::Status GetAll(engine::Context &ctx, const Slice &user_key, std::vector *field_values, HashFetchType type = HashFetchType::kAll); - rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, + rocksdb::Status Scan(engine::Context &ctx, const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &field_prefix, std::vector *fields, std::vector *values = nullptr); - rocksdb::Status RandField(const Slice &user_key, int64_t command_count, std::vector *field_values, - HashFetchType type = HashFetchType::kOnlyKey); + rocksdb::Status RandField(engine::Context &ctx, const Slice &user_key, int64_t command_count, + std::vector *field_values, HashFetchType type = HashFetchType::kOnlyKey); private: - rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &ns_key, HashMetadata *metadata); + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, HashMetadata *metadata); friend struct FieldValueRetriever; }; diff --git a/src/types/redis_hyperloglog.cc b/src/types/redis_hyperloglog.cc index e6c0e420323..9b9b5a50125 100644 --- a/src/types/redis_hyperloglog.cc +++ b/src/types/redis_hyperloglog.cc @@ -97,9 +97,8 @@ class HllSegmentCache { } }; -rocksdb::Status HyperLogLog::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, - HyperLogLogMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisHyperLogLog}, ns_key, metadata); +rocksdb::Status HyperLogLog::GetMetadata(engine::Context &ctx, const Slice &ns_key, HyperLogLogMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisHyperLogLog}, ns_key, metadata); } uint64_t HyperLogLog::HllHash(std::string_view element) { @@ -108,13 +107,14 @@ uint64_t HyperLogLog::HllHash(std::string_view element) { } /* the max 0 pattern counter of the subset the element belongs to is incremented if needed */ -rocksdb::Status HyperLogLog::Add(const Slice &user_key, const std::vector &element_hashes, uint64_t *ret) { +rocksdb::Status HyperLogLog::Add(engine::Context &ctx, const Slice &user_key, + const std::vector &element_hashes, uint64_t *ret) { *ret = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); HyperLogLogMetadata metadata{}; - rocksdb::Status s = GetMetadata(GetOptions(), ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -131,11 +131,11 @@ rocksdb::Status HyperLogLog::Add(const Slice &user_key, const std::vector rocksdb::Status { + [this, &ns_key, &metadata, &ctx](uint32_t segment_index, std::string *segment) -> rocksdb::Status { std::string sub_key = InternalKey(ns_key, std::to_string(segment_index), metadata.version, storage_->IsSlotIdEncoded()) .Encode(); - return storage_->Get(rocksdb::ReadOptions(), sub_key, segment); + return storage_->Get(ctx, ctx.GetReadOptions(), sub_key, segment); }, &entry); if (!s.ok()) return s; @@ -172,20 +172,16 @@ rocksdb::Status HyperLogLog::Add(const Slice &user_key, const std::vectorPut(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status HyperLogLog::Count(const Slice &user_key, uint64_t *ret) { +rocksdb::Status HyperLogLog::Count(engine::Context &ctx, const Slice &user_key, uint64_t *ret) { std::string ns_key = AppendNamespacePrefix(user_key); *ret = 0; std::vector registers; - { - LatestSnapShot ss(storage_); - Database::GetOptions get_options(ss.GetSnapShot()); - auto s = getRegisters(get_options, ns_key, ®isters); - if (!s.ok()) { - return s; - } + auto s = getRegisters(ctx, ns_key, ®isters); + if (!s.ok()) { + return s; } DCHECK_EQ(kHyperLogLogSegmentCount, registers.size()); std::vector> register_segments = TransformToSpan(registers); @@ -193,12 +189,12 @@ rocksdb::Status HyperLogLog::Count(const Slice &user_key, uint64_t *ret) { return rocksdb::Status::OK(); } -rocksdb::Status HyperLogLog::mergeUserKeys(Database::GetOptions get_options, const std::vector &user_keys, +rocksdb::Status HyperLogLog::mergeUserKeys(engine::Context &ctx, const std::vector &user_keys, std::vector *register_segments) { DCHECK_GE(user_keys.size(), static_cast(1)); std::string first_ns_key = AppendNamespacePrefix(user_keys[0]); - rocksdb::Status s = getRegisters(get_options, first_ns_key, register_segments); + rocksdb::Status s = getRegisters(ctx, first_ns_key, register_segments); if (!s.ok()) return s; // The set of keys that have been seen so far std::unordered_set seend_user_keys; @@ -212,7 +208,7 @@ rocksdb::Status HyperLogLog::mergeUserKeys(Database::GetOptions get_options, con } std::string source_key = AppendNamespacePrefix(source_user_key); std::vector source_registers; - s = getRegisters(get_options, source_key, &source_registers); + s = getRegisters(ctx, source_key, &source_registers); if (!s.ok()) return s; DCHECK_EQ(kHyperLogLogSegmentCount, source_registers.size()); DCHECK_EQ(kHyperLogLogSegmentCount, register_segments->size()); @@ -222,20 +218,18 @@ rocksdb::Status HyperLogLog::mergeUserKeys(Database::GetOptions get_options, con return rocksdb::Status::OK(); } -rocksdb::Status HyperLogLog::CountMultiple(const std::vector &user_key, uint64_t *ret) { +rocksdb::Status HyperLogLog::CountMultiple(engine::Context &ctx, const std::vector &user_key, uint64_t *ret) { DCHECK_GT(user_key.size(), static_cast(1)); std::vector register_segments; - // Using same snapshot for all get operations - LatestSnapShot ss(storage_); - Database::GetOptions get_options(ss.GetSnapShot()); - auto s = mergeUserKeys(get_options, user_key, ®ister_segments); + auto s = mergeUserKeys(ctx, user_key, ®ister_segments); if (!s.ok()) return s; std::vector> register_segment_span = TransformToSpan(register_segments); *ret = HllDenseEstimate(register_segment_span); return rocksdb::Status::OK(); } -rocksdb::Status HyperLogLog::Merge(const Slice &dest_user_key, const std::vector &source_user_keys) { +rocksdb::Status HyperLogLog::Merge(engine::Context &ctx, const Slice &dest_user_key, + const std::vector &source_user_keys) { if (source_user_keys.empty()) { return rocksdb::Status::OK(); } @@ -244,22 +238,17 @@ rocksdb::Status HyperLogLog::Merge(const Slice &dest_user_key, const std::vector LockGuard guard(storage_->GetLockManager(), dest_key); std::vector registers; HyperLogLogMetadata metadata; + + rocksdb::Status s = GetMetadata(ctx, dest_user_key, &metadata); + if (!s.ok() && !s.IsNotFound()) return s; { - // Using same snapshot for all get operations and release it after - // finishing the merge operation - LatestSnapShot ss(storage_); - Database::GetOptions get_options(ss.GetSnapShot()); - rocksdb::Status s = GetMetadata(get_options, dest_user_key, &metadata); - if (!s.ok() && !s.IsNotFound()) return s; - { - std::vector all_user_keys; - all_user_keys.reserve(source_user_keys.size() + 1); - all_user_keys.push_back(dest_user_key); - for (const auto &source_user_key : source_user_keys) { - all_user_keys.push_back(source_user_key); - } - s = mergeUserKeys(get_options, all_user_keys, ®isters); + std::vector all_user_keys; + all_user_keys.reserve(source_user_keys.size() + 1); + all_user_keys.push_back(dest_user_key); + for (const auto &source_user_key : source_user_keys) { + all_user_keys.push_back(source_user_key); } + s = mergeUserKeys(ctx, all_user_keys, ®isters); } auto batch = storage_->GetWriteBatchBase(); @@ -283,13 +272,13 @@ rocksdb::Status HyperLogLog::Merge(const Slice &dest_user_key, const std::vector batch->Put(metadata_cf_handle_, dest_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status HyperLogLog::getRegisters(Database::GetOptions get_options, const Slice &ns_key, +rocksdb::Status HyperLogLog::getRegisters(engine::Context &ctx, const Slice &ns_key, std::vector *register_segments) { HyperLogLogMetadata metadata; - rocksdb::Status s = GetMetadata(get_options, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { if (s.IsNotFound()) { // return empty registers with the right size. @@ -299,8 +288,6 @@ rocksdb::Status HyperLogLog::getRegisters(Database::GetOptions get_options, cons return s; } - rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions(); - read_options.snapshot = get_options.snapshot; // Multi get all segments std::vector sub_segment_keys; sub_segment_keys.reserve(kHyperLogLogSegmentCount); @@ -316,8 +303,8 @@ rocksdb::Status HyperLogLog::getRegisters(Database::GetOptions get_options, cons } register_segments->resize(kHyperLogLogSegmentCount); std::vector statuses(kHyperLogLogSegmentCount); - storage_->MultiGet(read_options, storage_->GetDB()->DefaultColumnFamily(), kHyperLogLogSegmentCount, - sub_segment_slices.data(), register_segments->data(), statuses.data()); + storage_->MultiGet(ctx, ctx.DefaultMultiGetOptions(), storage_->GetDB()->DefaultColumnFamily(), + kHyperLogLogSegmentCount, sub_segment_slices.data(), register_segments->data(), statuses.data()); for (size_t i = 0; i < kHyperLogLogSegmentCount; i++) { if (!statuses[i].ok() && !statuses[i].IsNotFound()) { register_segments->at(i).clear(); @@ -327,10 +314,10 @@ rocksdb::Status HyperLogLog::getRegisters(Database::GetOptions get_options, cons return rocksdb::Status::OK(); } -rocksdb::Status HyperLogLog::getRegisters(Database::GetOptions get_options, const Slice &ns_key, +rocksdb::Status HyperLogLog::getRegisters(engine::Context &ctx, const Slice &ns_key, std::vector *register_segments) { std::vector pinnable_slices; - rocksdb::Status s = getRegisters(get_options, ns_key, &pinnable_slices); + rocksdb::Status s = getRegisters(ctx, ns_key, &pinnable_slices); if (!s.ok()) return s; register_segments->reserve(kHyperLogLogSegmentCount); for (auto &pinnable_slice : pinnable_slices) { diff --git a/src/types/redis_hyperloglog.h b/src/types/redis_hyperloglog.h index 6b2e441b668..cf09f4445fb 100644 --- a/src/types/redis_hyperloglog.h +++ b/src/types/redis_hyperloglog.h @@ -28,27 +28,27 @@ namespace redis { class HyperLogLog : public Database { public: explicit HyperLogLog(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Add(const Slice &user_key, const std::vector &element_hashes, uint64_t *ret); - rocksdb::Status Count(const Slice &user_key, uint64_t *ret); + rocksdb::Status Add(engine::Context &ctx, const Slice &user_key, const std::vector &element_hashes, + uint64_t *ret); + rocksdb::Status Count(engine::Context &ctx, const Slice &user_key, uint64_t *ret); /// The count when user_keys.size() is greater than 1. - rocksdb::Status CountMultiple(const std::vector &user_key, uint64_t *ret); - rocksdb::Status Merge(const Slice &dest_user_key, const std::vector &source_user_keys); + rocksdb::Status CountMultiple(engine::Context &ctx, const std::vector &user_key, uint64_t *ret); + rocksdb::Status Merge(engine::Context &ctx, const Slice &dest_user_key, const std::vector &source_user_keys); static uint64_t HllHash(std::string_view); private: - [[nodiscard]] rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &ns_key, - HyperLogLogMetadata *metadata); + [[nodiscard]] rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, HyperLogLogMetadata *metadata); - [[nodiscard]] rocksdb::Status mergeUserKeys(Database::GetOptions get_options, const std::vector &user_keys, + [[nodiscard]] rocksdb::Status mergeUserKeys(engine::Context &ctx, const std::vector &user_keys, std::vector *register_segments); /// Using multi-get to acquire the register_segments /// /// If the metadata is not found, register_segments will be initialized with 16 empty slices. - [[nodiscard]] rocksdb::Status getRegisters(Database::GetOptions get_options, const Slice &ns_key, + [[nodiscard]] rocksdb::Status getRegisters(engine::Context &ctx, const Slice &ns_key, std::vector *register_segments); /// Same with getRegisters, but the result is stored in a vector of strings. - [[nodiscard]] rocksdb::Status getRegisters(Database::GetOptions get_options, const Slice &ns_key, + [[nodiscard]] rocksdb::Status getRegisters(engine::Context &ctx, const Slice &ns_key, std::vector *register_segments); }; diff --git a/src/types/redis_json.cc b/src/types/redis_json.cc index eba2eae115d..f8dc1e15916 100644 --- a/src/types/redis_json.cc +++ b/src/types/redis_json.cc @@ -26,7 +26,7 @@ namespace redis { -rocksdb::Status Json::write(Slice ns_key, JsonMetadata *metadata, const JsonValue &json_val) { +rocksdb::Status Json::write(engine::Context &ctx, Slice ns_key, JsonMetadata *metadata, const JsonValue &json_val) { auto batch = storage_->GetWriteBatchBase(); WriteBatchLogData log_data(kRedisJson); batch->PutLogData(log_data.Encode()); @@ -51,7 +51,7 @@ rocksdb::Status Json::write(Slice ns_key, JsonMetadata *metadata, const JsonValu batch->Put(metadata_cf_handle_, ns_key, val); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } rocksdb::Status Json::parse(const JsonMetadata &metadata, const Slice &json_bytes, JsonValue *value) { @@ -70,42 +70,43 @@ rocksdb::Status Json::parse(const JsonMetadata &metadata, const Slice &json_byte return rocksdb::Status::OK(); } -rocksdb::Status Json::read(const Slice &ns_key, JsonMetadata *metadata, JsonValue *value) { +rocksdb::Status Json::read(engine::Context &ctx, const Slice &ns_key, JsonMetadata *metadata, JsonValue *value) { std::string bytes; Slice rest; - auto s = GetMetadata(GetOptions{}, {kRedisJson}, ns_key, &bytes, metadata, &rest); + auto s = GetMetadata(ctx, {kRedisJson}, ns_key, &bytes, metadata, &rest); if (!s.ok()) return s; return parse(*metadata, rest, value); } -rocksdb::Status Json::create(const std::string &ns_key, JsonMetadata &metadata, const std::string &value) { +rocksdb::Status Json::create(engine::Context &ctx, const std::string &ns_key, JsonMetadata &metadata, + const std::string &value) { auto json_res = JsonValue::FromString(value, storage_->GetConfig()->json_max_nesting_depth); if (!json_res) return rocksdb::Status::InvalidArgument(json_res.Msg()); auto json_val = *std::move(json_res); - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::del(const Slice &ns_key) { +rocksdb::Status Json::del(engine::Context &ctx, const Slice &ns_key) { auto batch = storage_->GetWriteBatchBase(); WriteBatchLogData log_data(kRedisJson); batch->PutLogData(log_data.Encode()); batch->Delete(metadata_cf_handle_, ns_key); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Json::Info(const std::string &user_key, JsonStorageFormat *storage_format) { +rocksdb::Status Json::Info(engine::Context &ctx, const std::string &user_key, JsonStorageFormat *storage_format) { auto ns_key = AppendNamespacePrefix(user_key); std::string bytes; Slice rest; JsonMetadata metadata; - auto s = GetMetadata(GetOptions{}, {kRedisJson}, ns_key, &bytes, &metadata, &rest); + auto s = GetMetadata(ctx, {kRedisJson}, ns_key, &bytes, &metadata, &rest); if (!s.ok()) return s; *storage_format = metadata.format; @@ -113,19 +114,20 @@ rocksdb::Status Json::Info(const std::string &user_key, JsonStorageFormat *stora return rocksdb::Status::OK(); } -rocksdb::Status Json::Set(const std::string &user_key, const std::string &path, const std::string &value) { +rocksdb::Status Json::Set(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value) { auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); JsonMetadata metadata; JsonValue origin; - auto s = read(ns_key, &metadata, &origin); + auto s = read(ctx, ns_key, &metadata, &origin); if (s.IsNotFound()) { if (path != "$") return rocksdb::Status::InvalidArgument("new objects must be created at the root"); - return create(ns_key, metadata, value); + return create(ctx, ns_key, metadata, value); } if (!s.ok()) return s; @@ -137,15 +139,16 @@ rocksdb::Status Json::Set(const std::string &user_key, const std::string &path, auto set_res = origin.Set(path, std::move(new_val)); if (!set_res) return rocksdb::Status::InvalidArgument(set_res.Msg()); - return write(ns_key, &metadata, origin); + return write(ctx, ns_key, &metadata, origin); } -rocksdb::Status Json::Get(const std::string &user_key, const std::vector &paths, JsonValue *result) { +rocksdb::Status Json::Get(engine::Context &ctx, const std::string &user_key, const std::vector &paths, + JsonValue *result) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; JsonValue res; @@ -168,7 +171,7 @@ rocksdb::Status Json::Get(const std::string &user_key, const std::vector &values, Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); @@ -185,7 +188,7 @@ rocksdb::Status Json::ArrAppend(const std::string &user_key, const std::string & JsonMetadata metadata; JsonValue value; - auto s = read(ns_key, &metadata, &value); + auto s = read(ctx, ns_key, &metadata, &value); if (!s.ok()) return s; auto append_res = value.ArrAppend(path, append_values); @@ -196,11 +199,11 @@ rocksdb::Status Json::ArrAppend(const std::string &user_key, const std::string & std::any_of(results->begin(), results->end(), [](std::optional c) { return c.has_value(); }); if (!is_write) return rocksdb::Status::OK(); - return write(ns_key, &metadata, value); + return write(ctx, ns_key, &metadata, value); } -rocksdb::Status Json::ArrIndex(const std::string &user_key, const std::string &path, const std::string &needle, - ssize_t start, ssize_t end, Optionals *results) { +rocksdb::Status Json::ArrIndex(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &needle, ssize_t start, ssize_t end, Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); auto needle_res = JsonValue::FromString(needle, storage_->GetConfig()->json_max_nesting_depth); @@ -209,7 +212,7 @@ rocksdb::Status Json::ArrIndex(const std::string &user_key, const std::string &p JsonMetadata metadata; JsonValue value; - auto s = read(ns_key, &metadata, &value); + auto s = read(ctx, ns_key, &metadata, &value); if (!s.ok()) return s; auto index_res = value.ArrIndex(path, needle_value.value, start, end); @@ -219,12 +222,13 @@ rocksdb::Status Json::ArrIndex(const std::string &user_key, const std::string &p return rocksdb::Status::OK(); } -rocksdb::Status Json::Type(const std::string &user_key, const std::string &path, std::vector *results) { +rocksdb::Status Json::Type(engine::Context &ctx, const std::string &user_key, const std::string &path, + std::vector *results) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto res = json_val.Type(path); @@ -234,8 +238,8 @@ rocksdb::Status Json::Type(const std::string &user_key, const std::string &path, return rocksdb::Status::OK(); } -rocksdb::Status Json::Merge(const std::string &user_key, const std::string &path, const std::string &merge_value, - bool &result) { +rocksdb::Status Json::Merge(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &merge_value, bool &result) { auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); @@ -243,12 +247,12 @@ rocksdb::Status Json::Merge(const std::string &user_key, const std::string &path JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (s.IsNotFound()) { if (path != "$") return rocksdb::Status::InvalidArgument("new objects must be created at the root"); result = true; - return create(ns_key, metadata, merge_value); + return create(ctx, ns_key, metadata, merge_value); } if (!s.ok()) return s; @@ -262,17 +266,18 @@ rocksdb::Status Json::Merge(const std::string &user_key, const std::string &path return rocksdb::Status::OK(); } - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::Clear(const std::string &user_key, const std::string &path, size_t *result) { +rocksdb::Status Json::Clear(engine::Context &ctx, const std::string &user_key, const std::string &path, + size_t *result) { auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); JsonValue json_val; JsonMetadata metadata; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; @@ -284,14 +289,15 @@ rocksdb::Status Json::Clear(const std::string &user_key, const std::string &path return rocksdb::Status::OK(); } - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::ArrLen(const std::string &user_key, const std::string &path, Optionals *results) { +rocksdb::Status Json::ArrLen(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto len_res = json_val.ArrLen(path); @@ -301,8 +307,9 @@ rocksdb::Status Json::ArrLen(const std::string &user_key, const std::string &pat return rocksdb::Status::OK(); } -rocksdb::Status Json::ArrInsert(const std::string &user_key, const std::string &path, const int64_t &index, - const std::vector &values, Optionals *results) { +rocksdb::Status Json::ArrInsert(engine::Context &ctx, const std::string &user_key, const std::string &path, + const int64_t &index, const std::vector &values, + Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); std::vector insert_values; @@ -318,7 +325,7 @@ rocksdb::Status Json::ArrInsert(const std::string &user_key, const std::string & JsonMetadata metadata; JsonValue value; - auto s = read(ns_key, &metadata, &value); + auto s = read(ctx, ns_key, &metadata, &value); if (!s.ok()) return s; auto insert_res = value.ArrInsert(path, index, insert_values); @@ -329,27 +336,28 @@ rocksdb::Status Json::ArrInsert(const std::string &user_key, const std::string & std::any_of(results->begin(), results->end(), [](std::optional c) { return c.has_value(); }); if (!is_write) return rocksdb::Status::OK(); - return write(ns_key, &metadata, value); + return write(ctx, ns_key, &metadata, value); } -rocksdb::Status Json::Toggle(const std::string &user_key, const std::string &path, Optionals *results) { +rocksdb::Status Json::Toggle(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); JsonMetadata metadata; JsonValue origin; - auto s = read(ns_key, &metadata, &origin); + auto s = read(ctx, ns_key, &metadata, &origin); if (!s.ok()) return s; auto toggle_res = origin.Toggle(path); if (!toggle_res) return rocksdb::Status::InvalidArgument(toggle_res.Msg()); *results = std::move(*toggle_res); - return write(ns_key, &metadata, origin); + return write(ctx, ns_key, &metadata, origin); } -rocksdb::Status Json::ArrPop(const std::string &user_key, const std::string &path, int64_t index, +rocksdb::Status Json::ArrPop(engine::Context &ctx, const std::string &user_key, const std::string &path, int64_t index, std::vector> *results) { auto ns_key = AppendNamespacePrefix(user_key); @@ -357,7 +365,7 @@ rocksdb::Status Json::ArrPop(const std::string &user_key, const std::string &pat JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto pop_res = json_val.ArrPop(path, index); @@ -368,15 +376,15 @@ rocksdb::Status Json::ArrPop(const std::string &user_key, const std::string &pat [](const std::optional &val) { return val.has_value(); }); if (!is_write) return rocksdb::Status::OK(); - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::ObjKeys(const std::string &user_key, const std::string &path, +rocksdb::Status Json::ObjKeys(engine::Context &ctx, const std::string &user_key, const std::string &path, Optionals> *keys) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto keys_res = json_val.ObjKeys(path); if (!keys_res) return rocksdb::Status::InvalidArgument(keys_res.Msg()); @@ -385,15 +393,15 @@ rocksdb::Status Json::ObjKeys(const std::string &user_key, const std::string &pa return rocksdb::Status::OK(); } -rocksdb::Status Json::ArrTrim(const std::string &user_key, const std::string &path, int64_t start, int64_t stop, - Optionals *results) { +rocksdb::Status Json::ArrTrim(engine::Context &ctx, const std::string &user_key, const std::string &path, int64_t start, + int64_t stop, Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto len_res = json_val.ArrTrim(path, start, stop); @@ -403,17 +411,17 @@ rocksdb::Status Json::ArrTrim(const std::string &user_key, const std::string &pa bool is_write = std::any_of(results->begin(), results->end(), [](const std::optional &val) { return val.has_value(); }); if (!is_write) return rocksdb::Status::OK(); - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::Del(const std::string &user_key, const std::string &path, size_t *result) { +rocksdb::Status Json::Del(engine::Context &ctx, const std::string &user_key, const std::string &path, size_t *result) { *result = 0; auto ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); JsonValue json_val; JsonMetadata metadata; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { @@ -422,7 +430,7 @@ rocksdb::Status Json::Del(const std::string &user_key, const std::string &path, if (path == "$") { *result = 1; - return del(ns_key); + return del(ctx, ns_key); } auto res = json_val.Del(path); @@ -432,21 +440,21 @@ rocksdb::Status Json::Del(const std::string &user_key, const std::string &path, if (*result == 0) { return rocksdb::Status::OK(); } - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::NumIncrBy(const std::string &user_key, const std::string &path, const std::string &value, - JsonValue *result) { - return numop(JsonValue::NumOpEnum::Incr, user_key, path, value, result); +rocksdb::Status Json::NumIncrBy(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, JsonValue *result) { + return numop(ctx, JsonValue::NumOpEnum::Incr, user_key, path, value, result); } -rocksdb::Status Json::NumMultBy(const std::string &user_key, const std::string &path, const std::string &value, - JsonValue *result) { - return numop(JsonValue::NumOpEnum::Mul, user_key, path, value, result); +rocksdb::Status Json::NumMultBy(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, JsonValue *result) { + return numop(ctx, JsonValue::NumOpEnum::Mul, user_key, path, value, result); } -rocksdb::Status Json::numop(JsonValue::NumOpEnum op, const std::string &user_key, const std::string &path, - const std::string &value, JsonValue *result) { +rocksdb::Status Json::numop(engine::Context &ctx, JsonValue::NumOpEnum op, const std::string &user_key, + const std::string &path, const std::string &value, JsonValue *result) { auto number_res = JsonValue::FromString(value); if (!number_res || !number_res.GetValue().value.is_number() || number_res.GetValue().value.is_string()) { return rocksdb::Status::InvalidArgument("the input value should be a number"); @@ -456,7 +464,7 @@ rocksdb::Status Json::numop(JsonValue::NumOpEnum op, const std::string &user_key auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; LockGuard guard(storage_->GetLockManager(), ns_key); @@ -465,15 +473,15 @@ rocksdb::Status Json::numop(JsonValue::NumOpEnum op, const std::string &user_key if (!res) { return rocksdb::Status::InvalidArgument(res.Msg()); } - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::StrAppend(const std::string &user_key, const std::string &path, const std::string &value, - Optionals *results) { +rocksdb::Status Json::StrAppend(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto append_res = json_val.StrAppend(path, value); @@ -486,14 +494,15 @@ rocksdb::Status Json::StrAppend(const std::string &user_key, const std::string & return rocksdb::Status::OK(); } - return write(ns_key, &metadata, json_val); + return write(ctx, ns_key, &metadata, json_val); } -rocksdb::Status Json::StrLen(const std::string &user_key, const std::string &path, Optionals *results) { +rocksdb::Status Json::StrLen(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto str_lens = json_val.StrLen(path); @@ -502,11 +511,12 @@ rocksdb::Status Json::StrLen(const std::string &user_key, const std::string &pat return rocksdb::Status::OK(); } -rocksdb::Status Json::ObjLen(const std::string &user_key, const std::string &path, Optionals *results) { +rocksdb::Status Json::ObjLen(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto obj_lens = json_val.ObjLen(path); @@ -515,8 +525,8 @@ rocksdb::Status Json::ObjLen(const std::string &user_key, const std::string &pat return rocksdb::Status::OK(); } -std::vector Json::MGet(const std::vector &user_keys, const std::string &path, - std::vector &results) { +std::vector Json::MGet(engine::Context &ctx, const std::vector &user_keys, + const std::string &path, std::vector &results) { std::vector ns_keys; std::vector ns_keys_string; ns_keys.resize(user_keys.size()); @@ -529,7 +539,7 @@ std::vector Json::MGet(const std::vector &user_key std::vector json_vals; json_vals.resize(ns_keys.size()); - auto statuses = readMulti(ns_keys, json_vals); + auto statuses = readMulti(ctx, ns_keys, json_vals); results.resize(ns_keys.size()); for (size_t i = 0; i < ns_keys.size(); i++) { @@ -547,8 +557,8 @@ std::vector Json::MGet(const std::vector &user_key return statuses; } -rocksdb::Status Json::MSet(const std::vector &user_keys, const std::vector &paths, - const std::vector &values) { +rocksdb::Status Json::MSet(engine::Context &ctx, const std::vector &user_keys, + const std::vector &paths, const std::vector &values) { std::vector ns_keys; ns_keys.reserve(user_keys.size()); for (const auto &user_key : user_keys) { @@ -568,7 +578,7 @@ rocksdb::Status Json::MSet(const std::vector &user_keys, const std: JsonMetadata metadata; JsonValue value; - if (auto s = read(ns_keys[i], &metadata, &value); s.IsNotFound()) { + if (auto s = read(ctx, ns_keys[i], &metadata, &value); s.IsNotFound()) { if (paths[i] != "$") return rocksdb::Status::InvalidArgument("new objects must be created at the root"); value = *std::move(json_res); @@ -601,17 +611,16 @@ rocksdb::Status Json::MSet(const std::vector &user_keys, const std: batch->Put(metadata_cf_handle_, ns_keys[i], val); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -std::vector Json::readMulti(const std::vector &ns_keys, std::vector &values) { - rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); +std::vector Json::readMulti(engine::Context &ctx, const std::vector &ns_keys, + std::vector &values) { + rocksdb::ReadOptions read_options = ctx.DefaultMultiGetOptions(); std::vector statuses(ns_keys.size()); std::vector pin_values(ns_keys.size()); - storage_->MultiGet(read_options, metadata_cf_handle_, ns_keys.size(), ns_keys.data(), pin_values.data(), + storage_->MultiGet(ctx, read_options, metadata_cf_handle_, ns_keys.size(), ns_keys.data(), pin_values.data(), statuses.data()); for (size_t i = 0; i < ns_keys.size(); i++) { if (!statuses[i].ok()) continue; @@ -626,18 +635,19 @@ std::vector Json::readMulti(const std::vector &ns_keys, return statuses; } -rocksdb::Status Json::DebugMemory(const std::string &user_key, const std::string &path, std::vector *results) { +rocksdb::Status Json::DebugMemory(engine::Context &ctx, const std::string &user_key, const std::string &path, + std::vector *results) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; if (path == "$") { std::string bytes; Slice rest; - auto s = GetMetadata(GetOptions{}, {kRedisJson}, ns_key, &bytes, &metadata, &rest); + auto s = GetMetadata(ctx, {kRedisJson}, ns_key, &bytes, &metadata, &rest); if (!s.ok()) return s; results->emplace_back(rest.size()); } else { JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto str_bytes = json_val.GetBytes(path, metadata.format, storage_->GetConfig()->json_max_nesting_depth); if (!str_bytes) return rocksdb::Status::InvalidArgument(str_bytes.Msg()); @@ -646,12 +656,12 @@ rocksdb::Status Json::DebugMemory(const std::string &user_key, const std::string return rocksdb::Status::OK(); } -rocksdb::Status Json::Resp(const std::string &user_key, const std::string &path, std::vector *results, - RESP resp) { +rocksdb::Status Json::Resp(engine::Context &ctx, const std::string &user_key, const std::string &path, + std::vector *results, RESP resp) { auto ns_key = AppendNamespacePrefix(user_key); JsonMetadata metadata; JsonValue json_val; - auto s = read(ns_key, &metadata, &json_val); + auto s = read(ctx, ns_key, &metadata, &json_val); if (!s.ok()) return s; auto json_resps = json_val.ConvertToResp(path, resp); diff --git a/src/types/redis_json.h b/src/types/redis_json.h index d34a2f3f52e..1a69408ee87 100644 --- a/src/types/redis_json.h +++ b/src/types/redis_json.h @@ -34,55 +34,66 @@ class Json : public Database { public: Json(engine::Storage *storage, std::string ns) : Database(storage, std::move(ns)) {} - rocksdb::Status Set(const std::string &user_key, const std::string &path, const std::string &value); - rocksdb::Status Get(const std::string &user_key, const std::vector &paths, JsonValue *result); - rocksdb::Status Info(const std::string &user_key, JsonStorageFormat *storage_format); - rocksdb::Status Type(const std::string &user_key, const std::string &path, std::vector *results); - rocksdb::Status ArrAppend(const std::string &user_key, const std::string &path, + rocksdb::Status Set(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value); + rocksdb::Status Get(engine::Context &ctx, const std::string &user_key, const std::vector &paths, + JsonValue *result); + rocksdb::Status Info(engine::Context &ctx, const std::string &user_key, JsonStorageFormat *storage_format); + rocksdb::Status Type(engine::Context &ctx, const std::string &user_key, const std::string &path, + std::vector *results); + rocksdb::Status ArrAppend(engine::Context &ctx, const std::string &user_key, const std::string &path, const std::vector &values, Optionals *results); - rocksdb::Status Merge(const std::string &user_key, const std::string &path, const std::string &value, bool &result); - rocksdb::Status Clear(const std::string &user_key, const std::string &path, size_t *result); - rocksdb::Status ArrLen(const std::string &user_key, const std::string &path, Optionals *results); - rocksdb::Status ArrInsert(const std::string &user_key, const std::string &path, const int64_t &index, - const std::vector &values, Optionals *results); - rocksdb::Status Toggle(const std::string &user_key, const std::string &path, Optionals *results); - rocksdb::Status ObjKeys(const std::string &user_key, const std::string &path, + rocksdb::Status Merge(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, bool &result); + rocksdb::Status Clear(engine::Context &ctx, const std::string &user_key, const std::string &path, size_t *result); + rocksdb::Status ArrLen(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results); + rocksdb::Status ArrInsert(engine::Context &ctx, const std::string &user_key, const std::string &path, + const int64_t &index, const std::vector &values, Optionals *results); + rocksdb::Status Toggle(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results); + rocksdb::Status ObjKeys(engine::Context &ctx, const std::string &user_key, const std::string &path, Optionals> *keys); - rocksdb::Status ArrPop(const std::string &user_key, const std::string &path, int64_t index, + rocksdb::Status ArrPop(engine::Context &ctx, const std::string &user_key, const std::string &path, int64_t index, std::vector> *results); - rocksdb::Status ArrIndex(const std::string &user_key, const std::string &path, const std::string &needle, - ssize_t start, ssize_t end, Optionals *results); - rocksdb::Status NumIncrBy(const std::string &user_key, const std::string &path, const std::string &value, - JsonValue *result); - rocksdb::Status NumMultBy(const std::string &user_key, const std::string &path, const std::string &value, - JsonValue *result); + rocksdb::Status ArrIndex(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &needle, ssize_t start, ssize_t end, Optionals *results); + rocksdb::Status NumIncrBy(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, JsonValue *result); + rocksdb::Status NumMultBy(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, JsonValue *result); - rocksdb::Status ArrTrim(const std::string &user_key, const std::string &path, int64_t start, int64_t stop, - Optionals *results); - rocksdb::Status Del(const std::string &user_key, const std::string &path, size_t *result); - rocksdb::Status StrAppend(const std::string &user_key, const std::string &path, const std::string &value, - Optionals *results); - rocksdb::Status StrLen(const std::string &user_key, const std::string &path, Optionals *results); - rocksdb::Status ObjLen(const std::string &user_key, const std::string &path, Optionals *results); + rocksdb::Status ArrTrim(engine::Context &ctx, const std::string &user_key, const std::string &path, int64_t start, + int64_t stop, Optionals *results); + rocksdb::Status Del(engine::Context &ctx, const std::string &user_key, const std::string &path, size_t *result); + rocksdb::Status StrAppend(engine::Context &ctx, const std::string &user_key, const std::string &path, + const std::string &value, Optionals *results); + rocksdb::Status StrLen(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results); + rocksdb::Status ObjLen(engine::Context &ctx, const std::string &user_key, const std::string &path, + Optionals *results); - std::vector MGet(const std::vector &user_keys, const std::string &path, - std::vector &results); - rocksdb::Status MSet(const std::vector &user_keys, const std::vector &paths, - const std::vector &values); - rocksdb::Status DebugMemory(const std::string &user_key, const std::string &path, std::vector *results); + std::vector MGet(engine::Context &ctx, const std::vector &user_keys, + const std::string &path, std::vector &results); + rocksdb::Status MSet(engine::Context &ctx, const std::vector &user_keys, + const std::vector &paths, const std::vector &values); + rocksdb::Status DebugMemory(engine::Context &ctx, const std::string &user_key, const std::string &path, + std::vector *results); - rocksdb::Status Resp(const std::string &user_key, const std::string &path, std::vector *results, - RESP resp); + rocksdb::Status Resp(engine::Context &ctx, const std::string &user_key, const std::string &path, + std::vector *results, RESP resp); private: - rocksdb::Status write(Slice ns_key, JsonMetadata *metadata, const JsonValue &json_val); - rocksdb::Status read(const Slice &ns_key, JsonMetadata *metadata, JsonValue *value); + rocksdb::Status write(engine::Context &ctx, Slice ns_key, JsonMetadata *metadata, const JsonValue &json_val); + rocksdb::Status read(engine::Context &ctx, const Slice &ns_key, JsonMetadata *metadata, JsonValue *value); static rocksdb::Status parse(const JsonMetadata &metadata, const Slice &json_byt, JsonValue *value); - rocksdb::Status create(const std::string &ns_key, JsonMetadata &metadata, const std::string &value); - rocksdb::Status del(const Slice &ns_key); - rocksdb::Status numop(JsonValue::NumOpEnum op, const std::string &user_key, const std::string &path, - const std::string &value, JsonValue *result); - std::vector readMulti(const std::vector &ns_keys, std::vector &values); + rocksdb::Status create(engine::Context &ctx, const std::string &ns_key, JsonMetadata &metadata, + const std::string &value); + rocksdb::Status del(engine::Context &ctx, const Slice &ns_key); + rocksdb::Status numop(engine::Context &ctx, JsonValue::NumOpEnum op, const std::string &user_key, + const std::string &path, const std::string &value, JsonValue *result); + std::vector readMulti(engine::Context &ctx, const std::vector &ns_keys, + std::vector &values); friend struct FieldValueRetriever; }; diff --git a/src/types/redis_list.cc b/src/types/redis_list.cc index 21edda041e4..1fdd2188537 100644 --- a/src/types/redis_list.cc +++ b/src/types/redis_list.cc @@ -27,31 +27,33 @@ namespace redis { -rocksdb::Status List::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, ListMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisList}, ns_key, metadata); +rocksdb::Status List::GetMetadata(engine::Context &ctx, const Slice &ns_key, ListMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisList}, ns_key, metadata); } -rocksdb::Status List::Size(const Slice &user_key, uint64_t *size) { +rocksdb::Status List::Size(engine::Context &ctx, const Slice &user_key, uint64_t *size) { *size = 0; std::string ns_key = AppendNamespacePrefix(user_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; *size = metadata.size; return rocksdb::Status::OK(); } -rocksdb::Status List::Push(const Slice &user_key, const std::vector &elems, bool left, uint64_t *new_size) { - return push(user_key, elems, true, left, new_size); +rocksdb::Status List::Push(engine::Context &ctx, const Slice &user_key, const std::vector &elems, bool left, + uint64_t *new_size) { + return push(ctx, user_key, elems, true, left, new_size); } -rocksdb::Status List::PushX(const Slice &user_key, const std::vector &elems, bool left, uint64_t *new_size) { - return push(user_key, elems, false, left, new_size); +rocksdb::Status List::PushX(engine::Context &ctx, const Slice &user_key, const std::vector &elems, bool left, + uint64_t *new_size) { + return push(ctx, user_key, elems, false, left, new_size); } -rocksdb::Status List::push(const Slice &user_key, const std::vector &elems, bool create_if_missing, bool left, - uint64_t *new_size) { +rocksdb::Status List::push(engine::Context &ctx, const Slice &user_key, const std::vector &elems, + bool create_if_missing, bool left, uint64_t *new_size) { *new_size = 0; std::string ns_key = AppendNamespacePrefix(user_key); @@ -61,7 +63,7 @@ rocksdb::Status List::push(const Slice &user_key, const std::vector &elem WriteBatchLogData log_data(kRedisList, {std::to_string(cmd)}); batch->PutLogData(log_data.Encode()); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !(create_if_missing && s.IsNotFound())) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -83,21 +85,21 @@ rocksdb::Status List::push(const Slice &user_key, const std::vector &elem metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); *new_size = metadata.size; - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status List::Pop(const Slice &user_key, bool left, std::string *elem) { +rocksdb::Status List::Pop(engine::Context &ctx, const Slice &user_key, bool left, std::string *elem) { elem->clear(); std::vector elems; - auto s = PopMulti(user_key, left, 1, &elems); + auto s = PopMulti(ctx, user_key, left, 1, &elems); if (!s.ok()) return s; *elem = std::move(elems[0]); return rocksdb::Status::OK(); } -rocksdb::Status List::PopMulti(const rocksdb::Slice &user_key, bool left, uint32_t count, +rocksdb::Status List::PopMulti(engine::Context &ctx, const rocksdb::Slice &user_key, bool left, uint32_t count, std::vector *elems) { elems->clear(); @@ -105,7 +107,7 @@ rocksdb::Status List::PopMulti(const rocksdb::Slice &user_key, bool left, uint32 LockGuard guard(storage_->GetLockManager(), ns_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; auto batch = storage_->GetWriteBatchBase(); @@ -119,7 +121,7 @@ rocksdb::Status List::PopMulti(const rocksdb::Slice &user_key, bool left, uint32 PutFixed64(&buf, index); std::string sub_key = InternalKey(ns_key, buf, metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string elem; - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &elem); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &elem); if (!s.ok()) { // FIXME: should be always exists?? return s; @@ -140,7 +142,7 @@ rocksdb::Status List::PopMulti(const rocksdb::Slice &user_key, bool left, uint32 batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } /* @@ -162,14 +164,15 @@ rocksdb::Status List::PopMulti(const rocksdb::Slice &user_key, bool left, uint32 * then trim the list from tail with num of elems to delete, here is 2. * and list would become: | E1 | E2 | E3 | E4 | E5 | E6 | */ -rocksdb::Status List::Rem(const Slice &user_key, int count, const Slice &elem, uint64_t *removed_cnt) { +rocksdb::Status List::Rem(engine::Context &ctx, const Slice &user_key, int count, const Slice &elem, + uint64_t *removed_cnt) { *removed_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; uint64_t index = count >= 0 ? metadata.head : metadata.tail - 1; @@ -181,15 +184,13 @@ rocksdb::Status List::Rem(const Slice &user_key, int count, const Slice &elem, u bool reversed = count < 0; std::vector to_delete_indexes; - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (iter->Seek(start_key); iter->Valid() && iter->key().starts_with(prefix); !reversed ? iter->Next() : iter->Prev()) { if (iter->value() == elem) { @@ -250,16 +251,17 @@ rocksdb::Status List::Rem(const Slice &user_key, int count, const Slice &elem, u } *removed_cnt = to_delete_indexes.size(); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status List::Insert(const Slice &user_key, const Slice &pivot, const Slice &elem, bool before, int *new_size) { +rocksdb::Status List::Insert(engine::Context &ctx, const Slice &user_key, const Slice &pivot, const Slice &elem, + bool before, int *new_size) { *new_size = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; std::string buf; @@ -269,13 +271,11 @@ rocksdb::Status List::Insert(const Slice &user_key, const Slice &pivot, const Sl std::string prefix = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix); read_options.iterate_upper_bound = &upper_bound; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (iter->Seek(start_key); iter->Valid() && iter->key().starts_with(prefix); iter->Next()) { if (iter->value() == pivot) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); @@ -326,27 +326,24 @@ rocksdb::Status List::Insert(const Slice &user_key, const Slice &pivot, const Sl batch->Put(metadata_cf_handle_, ns_key, bytes); *new_size = static_cast(metadata.size); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status List::Index(const Slice &user_key, int index, std::string *elem) { +rocksdb::Status List::Index(engine::Context &ctx, const Slice &user_key, int index, std::string *elem) { elem->clear(); std::string ns_key = AppendNamespacePrefix(user_key); ListMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; if (index < 0) index += static_cast(metadata.size); if (index < 0 || index >= static_cast(metadata.size)) return rocksdb::Status::NotFound(); - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string buf; PutFixed64(&buf, metadata.head + index); std::string sub_key = InternalKey(ns_key, buf, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - return storage_->Get(read_options, sub_key, elem); + return storage_->Get(ctx, ctx.GetReadOptions(), sub_key, elem); } // The offset can also be negative, -1 is the last element, -2 the penultimate @@ -354,13 +351,13 @@ rocksdb::Status List::Index(const Slice &user_key, int index, std::string *elem) // If start is larger than the end of the list, an empty list is returned. // If stop is larger than the actual end of the list, // Redis will treat it like the last element of the list. -rocksdb::Status List::Range(const Slice &user_key, int start, int stop, std::vector *elems) { +rocksdb::Status List::Range(engine::Context &ctx, const Slice &user_key, int start, int stop, + std::vector *elems) { elems->clear(); std::string ns_key = AppendNamespacePrefix(user_key); ListMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; if (start < 0) start = static_cast(metadata.size) + start; @@ -374,12 +371,11 @@ rocksdb::Status List::Range(const Slice &user_key, int start, int stop, std::vec std::string prefix = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix); read_options.iterate_upper_bound = &upper_bound; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (iter->Seek(start_key); iter->Valid() && iter->key().starts_with(prefix); iter->Next()) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); Slice sub_key = ikey.GetSubKey(); @@ -392,13 +388,13 @@ rocksdb::Status List::Range(const Slice &user_key, int start, int stop, std::vec return rocksdb::Status::OK(); } -rocksdb::Status List::Pos(const Slice &user_key, const Slice &elem, const PosSpec &spec, +rocksdb::Status List::Pos(engine::Context &ctx, const Slice &user_key, const Slice &elem, const PosSpec &spec, std::vector *indexes) { indexes->clear(); std::string ns_key = AppendNamespacePrefix(user_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; // A negative rank means start from the tail. @@ -417,9 +413,7 @@ rocksdb::Status List::Pos(const Slice &user_key, const Slice &elem, const PosSpe std::string prefix = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix); @@ -430,7 +424,7 @@ rocksdb::Status List::Pos(const Slice &user_key, const Slice &elem, const PosSpe int64_t count = spec.count.value_or(-1); int64_t offset = 0, matches = 0; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); iter->Seek(start_key); while (iter->Valid() && iter->key().starts_with(prefix) && (max_len == 0 || offset < max_len)) { if (iter->value() == elem) { @@ -449,12 +443,12 @@ rocksdb::Status List::Pos(const Slice &user_key, const Slice &elem, const PosSpe return rocksdb::Status::OK(); } -rocksdb::Status List::Set(const Slice &user_key, int index, Slice elem) { +rocksdb::Status List::Set(engine::Context &ctx, const Slice &user_key, int index, Slice elem) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; if (index < 0) index += static_cast(metadata.size); if (index < 0 || index >= static_cast(metadata.size)) { @@ -464,7 +458,7 @@ rocksdb::Status List::Set(const Slice &user_key, int index, Slice elem) { std::string buf, value; PutFixed64(&buf, metadata.head + index); std::string sub_key = InternalKey(ns_key, buf, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (!s.ok()) { return s; } @@ -474,23 +468,24 @@ rocksdb::Status List::Set(const Slice &user_key, int index, Slice elem) { WriteBatchLogData log_data(kRedisList, {std::to_string(kRedisCmdLSet), std::to_string(index)}); batch->PutLogData(log_data.Encode()); batch->Put(sub_key, elem); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status List::LMove(const rocksdb::Slice &src, const rocksdb::Slice &dst, bool src_left, bool dst_left, - std::string *elem) { +rocksdb::Status List::LMove(engine::Context &ctx, const rocksdb::Slice &src, const rocksdb::Slice &dst, bool src_left, + bool dst_left, std::string *elem) { if (src == dst) { - return lmoveOnSingleList(src, src_left, dst_left, elem); + return lmoveOnSingleList(ctx, src, src_left, dst_left, elem); } - return lmoveOnTwoLists(src, dst, src_left, dst_left, elem); + return lmoveOnTwoLists(ctx, src, dst, src_left, dst_left, elem); } -rocksdb::Status List::lmoveOnSingleList(const rocksdb::Slice &src, bool src_left, bool dst_left, std::string *elem) { +rocksdb::Status List::lmoveOnSingleList(engine::Context &ctx, const rocksdb::Slice &src, bool src_left, bool dst_left, + std::string *elem) { std::string ns_key = AppendNamespacePrefix(src); LockGuard guard(storage_->GetLockManager(), ns_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s; } @@ -502,7 +497,7 @@ rocksdb::Status List::lmoveOnSingleList(const rocksdb::Slice &src, bool src_left PutFixed64(&curr_index_buf, curr_index); std::string curr_sub_key = InternalKey(ns_key, curr_index_buf, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), curr_sub_key, elem); + s = storage_->Get(ctx, ctx.GetReadOptions(), curr_sub_key, elem); if (!s.ok()) { return s; } @@ -542,24 +537,24 @@ rocksdb::Status List::lmoveOnSingleList(const rocksdb::Slice &src, bool src_left metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status List::lmoveOnTwoLists(const rocksdb::Slice &src, const rocksdb::Slice &dst, bool src_left, - bool dst_left, std::string *elem) { +rocksdb::Status List::lmoveOnTwoLists(engine::Context &ctx, const rocksdb::Slice &src, const rocksdb::Slice &dst, + bool src_left, bool dst_left, std::string *elem) { std::string src_ns_key = AppendNamespacePrefix(src); std::string dst_ns_key = AppendNamespacePrefix(dst); std::vector lock_keys{src_ns_key, dst_ns_key}; MultiLockGuard guard(storage_->GetLockManager(), lock_keys); ListMetadata src_metadata(false); - auto s = GetMetadata(GetOptions{}, src_ns_key, &src_metadata); + auto s = GetMetadata(ctx, src_ns_key, &src_metadata); if (!s.ok()) { return s; } ListMetadata dst_metadata(false); - s = GetMetadata(GetOptions{}, dst_ns_key, &dst_metadata); + s = GetMetadata(ctx, dst_ns_key, &dst_metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -576,7 +571,7 @@ rocksdb::Status List::lmoveOnTwoLists(const rocksdb::Slice &src, const rocksdb:: PutFixed64(&src_buf, src_index); std::string src_sub_key = InternalKey(src_ns_key, src_buf, src_metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), src_sub_key, elem); + s = storage_->Get(ctx, ctx.GetReadOptions(), src_sub_key, elem); if (!s.ok()) { return s; } @@ -605,17 +600,17 @@ rocksdb::Status List::lmoveOnTwoLists(const rocksdb::Slice &src, const rocksdb:: dst_metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, dst_ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } // Caution: trim the big list may block the server -rocksdb::Status List::Trim(const Slice &user_key, int start, int stop) { +rocksdb::Status List::Trim(engine::Context &ctx, const Slice &user_key, int start, int stop) { uint32_t trim_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ListMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; if (start < 0) start += static_cast(metadata.size); @@ -623,7 +618,7 @@ rocksdb::Status List::Trim(const Slice &user_key, int start, int stop) { // the result will be empty list when start > stop, // or start is larger than the end of list if (start > stop) { - return storage_->Delete(storage_->DefaultWriteOptions(), metadata_cf_handle_, ns_key); + return storage_->Delete(ctx, storage_->DefaultWriteOptions(), metadata_cf_handle_, ns_key); } if (start < 0) start = 0; @@ -658,6 +653,6 @@ rocksdb::Status List::Trim(const Slice &user_key, int start, int stop) { std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } } // namespace redis diff --git a/src/types/redis_list.h b/src/types/redis_list.h index d5e6c7a1fae..97239a43a4a 100644 --- a/src/types/redis_list.h +++ b/src/types/redis_list.h @@ -41,25 +41,34 @@ namespace redis { class List : public Database { public: explicit List(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Size(const Slice &user_key, uint64_t *size); - rocksdb::Status Trim(const Slice &user_key, int start, int stop); - rocksdb::Status Set(const Slice &user_key, int index, Slice elem); - rocksdb::Status Insert(const Slice &user_key, const Slice &pivot, const Slice &elem, bool before, int *new_size); - rocksdb::Status Pop(const Slice &user_key, bool left, std::string *elem); - rocksdb::Status PopMulti(const Slice &user_key, bool left, uint32_t count, std::vector *elems); - rocksdb::Status Rem(const Slice &user_key, int count, const Slice &elem, uint64_t *removed_cnt); - rocksdb::Status Index(const Slice &user_key, int index, std::string *elem); - rocksdb::Status LMove(const Slice &src, const Slice &dst, bool src_left, bool dst_left, std::string *elem); - rocksdb::Status Push(const Slice &user_key, const std::vector &elems, bool left, uint64_t *new_size); - rocksdb::Status PushX(const Slice &user_key, const std::vector &elems, bool left, uint64_t *new_size); - rocksdb::Status Range(const Slice &user_key, int start, int stop, std::vector *elems); - rocksdb::Status Pos(const Slice &user_key, const Slice &elem, const PosSpec &spec, std::vector *indexes); + rocksdb::Status Size(engine::Context &ctx, const Slice &user_key, uint64_t *size); + rocksdb::Status Trim(engine::Context &ctx, const Slice &user_key, int start, int stop); + rocksdb::Status Set(engine::Context &ctx, const Slice &user_key, int index, Slice elem); + rocksdb::Status Insert(engine::Context &ctx, const Slice &user_key, const Slice &pivot, const Slice &elem, + bool before, int *new_size); + rocksdb::Status Pop(engine::Context &ctx, const Slice &user_key, bool left, std::string *elem); + rocksdb::Status PopMulti(engine::Context &ctx, const Slice &user_key, bool left, uint32_t count, + std::vector *elems); + rocksdb::Status Rem(engine::Context &ctx, const Slice &user_key, int count, const Slice &elem, uint64_t *removed_cnt); + rocksdb::Status Index(engine::Context &ctx, const Slice &user_key, int index, std::string *elem); + rocksdb::Status LMove(engine::Context &ctx, const Slice &src, const Slice &dst, bool src_left, bool dst_left, + std::string *elem); + rocksdb::Status Push(engine::Context &ctx, const Slice &user_key, const std::vector &elems, bool left, + uint64_t *new_size); + rocksdb::Status PushX(engine::Context &ctx, const Slice &user_key, const std::vector &elems, bool left, + uint64_t *new_size); + rocksdb::Status Range(engine::Context &ctx, const Slice &user_key, int start, int stop, + std::vector *elems); + rocksdb::Status Pos(engine::Context &ctx, const Slice &user_key, const Slice &elem, const PosSpec &spec, + std::vector *indexes); private: - rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &ns_key, ListMetadata *metadata); - rocksdb::Status push(const Slice &user_key, const std::vector &elems, bool create_if_missing, bool left, - uint64_t *new_size); - rocksdb::Status lmoveOnSingleList(const Slice &src, bool src_left, bool dst_left, std::string *elem); - rocksdb::Status lmoveOnTwoLists(const Slice &src, const Slice &dst, bool src_left, bool dst_left, std::string *elem); + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, ListMetadata *metadata); + rocksdb::Status push(engine::Context &ctx, const Slice &user_key, const std::vector &elems, + bool create_if_missing, bool left, uint64_t *new_size); + rocksdb::Status lmoveOnSingleList(engine::Context &ctx, const Slice &src, bool src_left, bool dst_left, + std::string *elem); + rocksdb::Status lmoveOnTwoLists(engine::Context &ctx, const Slice &src, const Slice &dst, bool src_left, + bool dst_left, std::string *elem); }; } // namespace redis diff --git a/src/types/redis_set.cc b/src/types/redis_set.cc index 0c7e4009b28..6527a20bcdf 100644 --- a/src/types/redis_set.cc +++ b/src/types/redis_set.cc @@ -29,12 +29,12 @@ namespace redis { -rocksdb::Status Set::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, SetMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisSet}, ns_key, metadata); +rocksdb::Status Set::GetMetadata(engine::Context &ctx, const Slice &ns_key, SetMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisSet}, ns_key, metadata); } // Make sure members are uniq before use Overwrite -rocksdb::Status Set::Overwrite(Slice user_key, const std::vector &members) { +rocksdb::Status Set::Overwrite(engine::Context &ctx, Slice user_key, const std::vector &members) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); @@ -50,17 +50,18 @@ rocksdb::Status Set::Overwrite(Slice user_key, const std::vector &m std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Set::Add(const Slice &user_key, const std::vector &members, uint64_t *added_cnt) { +rocksdb::Status Set::Add(engine::Context &ctx, const Slice &user_key, const std::vector &members, + uint64_t *added_cnt) { *added_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); SetMetadata metadata; - rocksdb::Status s = GetMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; std::string value; @@ -73,7 +74,7 @@ rocksdb::Status Set::Add(const Slice &user_key, const std::vector &member continue; } std::string sub_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (s.ok()) continue; batch->Put(sub_key, Slice()); *added_cnt += 1; @@ -84,17 +85,18 @@ rocksdb::Status Set::Add(const Slice &user_key, const std::vector &member metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Set::Remove(const Slice &user_key, const std::vector &members, uint64_t *removed_cnt) { +rocksdb::Status Set::Remove(engine::Context &ctx, const Slice &user_key, const std::vector &members, + uint64_t *removed_cnt) { *removed_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); SetMetadata metadata(false); - rocksdb::Status s = GetMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string value; @@ -107,7 +109,7 @@ rocksdb::Status Set::Remove(const Slice &user_key, const std::vector &mem continue; } std::string sub_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (!s.ok()) continue; batch->Delete(sub_key); *removed_cnt += 1; @@ -122,40 +124,38 @@ rocksdb::Status Set::Remove(const Slice &user_key, const std::vector &mem batch->Delete(metadata_cf_handle_, ns_key); } } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Set::Card(const Slice &user_key, uint64_t *size) { +rocksdb::Status Set::Card(engine::Context &ctx, const Slice &user_key, uint64_t *size) { *size = 0; std::string ns_key = AppendNamespacePrefix(user_key); SetMetadata metadata(false); - rocksdb::Status s = GetMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; *size = metadata.size; return rocksdb::Status::OK(); } -rocksdb::Status Set::Members(const Slice &user_key, std::vector *members) { +rocksdb::Status Set::Members(engine::Context &ctx, const Slice &user_key, std::vector *members) { members->clear(); std::string ns_key = AppendNamespacePrefix(user_key); SetMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(Database::GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string prefix = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix); read_options.iterate_upper_bound = &upper_bound; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (iter->Seek(prefix); iter->Valid() && iter->key().starts_with(prefix); iter->Next()) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); members->emplace_back(ikey.GetSubKey().ToString()); @@ -163,31 +163,28 @@ rocksdb::Status Set::Members(const Slice &user_key, std::vector *me return rocksdb::Status::OK(); } -rocksdb::Status Set::IsMember(const Slice &user_key, const Slice &member, bool *flag) { +rocksdb::Status Set::IsMember(engine::Context &ctx, const Slice &user_key, const Slice &member, bool *flag) { std::vector exists; - rocksdb::Status s = MIsMember(user_key, {member}, &exists); + rocksdb::Status s = MIsMember(ctx, user_key, {member}, &exists); if (!s.ok()) return s; *flag = exists[0]; return s; } -rocksdb::Status Set::MIsMember(const Slice &user_key, const std::vector &members, std::vector *exists) { +rocksdb::Status Set::MIsMember(engine::Context &ctx, const Slice &user_key, const std::vector &members, + std::vector *exists) { exists->clear(); std::string ns_key = AppendNamespacePrefix(user_key); SetMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(Database::GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; - rocksdb::ReadOptions read_options; - - read_options.snapshot = ss.GetSnapShot(); std::string value; for (const auto &member : members) { std::string sub_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(read_options, sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { exists->emplace_back(0); @@ -198,7 +195,8 @@ rocksdb::Status Set::MIsMember(const Slice &user_key, const std::vector & return rocksdb::Status::OK(); } -rocksdb::Status Set::Take(const Slice &user_key, std::vector *members, int count, bool pop) { +rocksdb::Status Set::Take(engine::Context &ctx, const Slice &user_key, std::vector *members, int count, + bool pop) { members->clear(); bool unique = true; if (count == 0) return rocksdb::Status::OK(); @@ -214,7 +212,7 @@ rocksdb::Status Set::Take(const Slice &user_key, std::vector *membe if (pop) lock_guard.emplace(storage_->GetLockManager(), ns_key); SetMetadata metadata(false); - rocksdb::Status s = GetMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; ObserverOrUniquePtr batch = storage_->GetWriteBatchBase(); @@ -224,7 +222,8 @@ rocksdb::Status Set::Take(const Slice &user_key, std::vector *membe } members->clear(); s = ExtractRandMemberFromSet( - unique, count, [this, user_key](std::vector *samples) { return this->Members(user_key, samples); }, + unique, count, + [this, user_key, &ctx](std::vector *samples) { return this->Members(ctx, user_key, samples); }, members); if (!s.ok()) { return s; @@ -241,12 +240,12 @@ rocksdb::Status Set::Take(const Slice &user_key, std::vector *membe std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Set::Move(const Slice &src, const Slice &dst, const Slice &member, bool *flag) { +rocksdb::Status Set::Move(engine::Context &ctx, const Slice &src, const Slice &dst, const Slice &member, bool *flag) { RedisType type = kRedisNone; - rocksdb::Status s = Type(dst, &type); + rocksdb::Status s = Type(ctx, dst, &type); if (!s.ok()) return s; if (type != kRedisNone && type != kRedisSet) { return rocksdb::Status::InvalidArgument(kErrMsgWrongType); @@ -254,19 +253,19 @@ rocksdb::Status Set::Move(const Slice &src, const Slice &dst, const Slice &membe uint64_t ret = 0; std::vector members{member}; - s = Remove(src, members, &ret); + s = Remove(ctx, src, members, &ret); *flag = (ret != 0); if (!s.ok() || !*flag) { return s; } - s = Add(dst, members, &ret); + s = Add(ctx, dst, members, &ret); *flag = (ret != 0); return s; } -rocksdb::Status Set::Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, +rocksdb::Status Set::Scan(engine::Context &ctx, const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &member_prefix, std::vector *members) { - return SubKeyScanner::Scan(kRedisSet, user_key, cursor, limit, member_prefix, members); + return SubKeyScanner::Scan(ctx, kRedisSet, user_key, cursor, limit, member_prefix, members); } /* @@ -277,7 +276,7 @@ rocksdb::Status Set::Scan(const Slice &user_key, const std::string &cursor, uint * key3 = {a,c,e} * DIFF key1 key2 key3 = {b,d} */ -rocksdb::Status Set::Diff(const std::vector &keys, std::vector *members) { +rocksdb::Status Set::Diff(engine::Context &ctx, const std::vector &keys, std::vector *members) { std::vector lock_keys; lock_keys.reserve(keys.size()); for (const auto key : keys) { @@ -288,13 +287,13 @@ rocksdb::Status Set::Diff(const std::vector &keys, std::vectorclear(); std::vector source_members; - auto s = Members(keys[0], &source_members); + auto s = Members(ctx, keys[0], &source_members); if (!s.ok()) return s; std::map exclude_members; std::vector target_members; for (size_t i = 1; i < keys.size(); i++) { - s = Members(keys[i], &target_members); + s = Members(ctx, keys[i], &target_members); if (!s.ok()) return s; for (const auto &member : target_members) { exclude_members[member] = true; @@ -316,7 +315,7 @@ rocksdb::Status Set::Diff(const std::vector &keys, std::vector &keys, std::vector *members) { +rocksdb::Status Set::Union(engine::Context &ctx, const std::vector &keys, std::vector *members) { std::vector lock_keys; lock_keys.reserve(keys.size()); for (const auto key : keys) { @@ -330,7 +329,7 @@ rocksdb::Status Set::Union(const std::vector &keys, std::vector union_members; std::vector target_members; for (const auto &key : keys) { - auto s = Members(key, &target_members); + auto s = Members(ctx, key, &target_members); if (!s.ok()) return s; for (const auto &member : target_members) { union_members[member] = true; @@ -350,7 +349,7 @@ rocksdb::Status Set::Union(const std::vector &keys, std::vector &keys, std::vector *members) { +rocksdb::Status Set::Inter(engine::Context &ctx, const std::vector &keys, std::vector *members) { std::vector lock_keys; lock_keys.reserve(keys.size()); for (const auto key : keys) { @@ -363,13 +362,13 @@ rocksdb::Status Set::Inter(const std::vector &keys, std::vector member_counters; std::vector target_members; - auto s = Members(keys[0], &target_members); + auto s = Members(ctx, keys[0], &target_members); if (!s.ok() || target_members.empty()) return s; for (const auto &member : target_members) { member_counters[member] = 1; } for (size_t i = 1; i < keys.size(); i++) { - s = Members(keys[i], &target_members); + s = Members(ctx, keys[i], &target_members); if (!s.ok() || target_members.empty()) return s; for (const auto &member : target_members) { if (member_counters.find(member) == member_counters.end()) continue; @@ -384,13 +383,14 @@ rocksdb::Status Set::Inter(const std::vector &keys, std::vector &keys, uint64_t limit, uint64_t *cardinality) { +rocksdb::Status Set::InterCard(engine::Context &ctx, const std::vector &keys, uint64_t limit, + uint64_t *cardinality) { *cardinality = 0; std::map member_counters; std::vector target_members; - auto s = Members(keys[0], &target_members); + auto s = Members(ctx, keys[0], &target_members); if (!s.ok() || target_members.empty()) return s; for (const auto &member : target_members) { member_counters[member] = 1; @@ -407,7 +407,7 @@ rocksdb::Status Set::InterCard(const std::vector &keys, uint64_t limit, u bool limit_reached = false; for (size_t i = 1; i < keys_size; i++) { - s = Members(keys[i], &target_members); + s = Members(ctx, keys[i], &target_members); if (!s.ok() || target_members.empty()) { return s; } @@ -430,30 +430,33 @@ rocksdb::Status Set::InterCard(const std::vector &keys, uint64_t limit, u return rocksdb::Status::OK(); } -rocksdb::Status Set::DiffStore(const Slice &dst, const std::vector &keys, uint64_t *saved_cnt) { +rocksdb::Status Set::DiffStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *saved_cnt) { *saved_cnt = 0; std::vector members; - auto s = Diff(keys, &members); + auto s = Diff(ctx, keys, &members); if (!s.ok()) return s; *saved_cnt = members.size(); - return Overwrite(dst, members); + return Overwrite(ctx, dst, members); } -rocksdb::Status Set::UnionStore(const Slice &dst, const std::vector &keys, uint64_t *save_cnt) { +rocksdb::Status Set::UnionStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *save_cnt) { *save_cnt = 0; std::vector members; - auto s = Union(keys, &members); + auto s = Union(ctx, keys, &members); if (!s.ok()) return s; *save_cnt = members.size(); - return Overwrite(dst, members); + return Overwrite(ctx, dst, members); } -rocksdb::Status Set::InterStore(const Slice &dst, const std::vector &keys, uint64_t *saved_cnt) { +rocksdb::Status Set::InterStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *saved_cnt) { *saved_cnt = 0; std::vector members; - auto s = Inter(keys, &members); + auto s = Inter(ctx, keys, &members); if (!s.ok()) return s; *saved_cnt = members.size(); - return Overwrite(dst, members); + return Overwrite(ctx, dst, members); } } // namespace redis diff --git a/src/types/redis_set.h b/src/types/redis_set.h index bfd8bd3c7aa..c6b7ca9b264 100644 --- a/src/types/redis_set.h +++ b/src/types/redis_set.h @@ -32,27 +32,35 @@ class Set : public SubKeyScanner { public: explicit Set(engine::Storage *storage, const std::string &ns) : SubKeyScanner(storage, ns) {} - rocksdb::Status Card(const Slice &user_key, uint64_t *size); - rocksdb::Status IsMember(const Slice &user_key, const Slice &member, bool *flag); - rocksdb::Status MIsMember(const Slice &user_key, const std::vector &members, std::vector *exists); - rocksdb::Status Add(const Slice &user_key, const std::vector &members, uint64_t *added_cnt); - rocksdb::Status Remove(const Slice &user_key, const std::vector &members, uint64_t *removed_cnt); - rocksdb::Status Members(const Slice &user_key, std::vector *members); - rocksdb::Status Move(const Slice &src, const Slice &dst, const Slice &member, bool *flag); - rocksdb::Status Take(const Slice &user_key, std::vector *members, int count, bool pop); - rocksdb::Status Diff(const std::vector &keys, std::vector *members); - rocksdb::Status Union(const std::vector &keys, std::vector *members); - rocksdb::Status Inter(const std::vector &keys, std::vector *members); - rocksdb::Status InterCard(const std::vector &keys, uint64_t limit, uint64_t *cardinality); - rocksdb::Status Overwrite(Slice user_key, const std::vector &members); - rocksdb::Status DiffStore(const Slice &dst, const std::vector &keys, uint64_t *saved_cnt); - rocksdb::Status UnionStore(const Slice &dst, const std::vector &keys, uint64_t *save_cnt); - rocksdb::Status InterStore(const Slice &dst, const std::vector &keys, uint64_t *saved_cnt); - rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, + rocksdb::Status Card(engine::Context &ctx, const Slice &user_key, uint64_t *size); + rocksdb::Status IsMember(engine::Context &ctx, const Slice &user_key, const Slice &member, bool *flag); + rocksdb::Status MIsMember(engine::Context &ctx, const Slice &user_key, const std::vector &members, + std::vector *exists); + rocksdb::Status Add(engine::Context &ctx, const Slice &user_key, const std::vector &members, + uint64_t *added_cnt); + rocksdb::Status Remove(engine::Context &ctx, const Slice &user_key, const std::vector &members, + uint64_t *removed_cnt); + rocksdb::Status Members(engine::Context &ctx, const Slice &user_key, std::vector *members); + rocksdb::Status Move(engine::Context &ctx, const Slice &src, const Slice &dst, const Slice &member, bool *flag); + rocksdb::Status Take(engine::Context &ctx, const Slice &user_key, std::vector *members, int count, + bool pop); + rocksdb::Status Diff(engine::Context &ctx, const std::vector &keys, std::vector *members); + rocksdb::Status Union(engine::Context &ctx, const std::vector &keys, std::vector *members); + rocksdb::Status Inter(engine::Context &ctx, const std::vector &keys, std::vector *members); + rocksdb::Status InterCard(engine::Context &ctx, const std::vector &keys, uint64_t limit, + uint64_t *cardinality); + rocksdb::Status Overwrite(engine::Context &ctx, Slice user_key, const std::vector &members); + rocksdb::Status DiffStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *saved_cnt); + rocksdb::Status UnionStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *save_cnt); + rocksdb::Status InterStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *saved_cnt); + rocksdb::Status Scan(engine::Context &ctx, const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &member_prefix, std::vector *members); private: - rocksdb::Status GetMetadata(Database::GetOptions options, const Slice &ns_key, SetMetadata *metadata); + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, SetMetadata *metadata); }; } // namespace redis diff --git a/src/types/redis_sortedint.cc b/src/types/redis_sortedint.cc index 7de9e70a0e0..ac45fd1ac44 100644 --- a/src/types/redis_sortedint.cc +++ b/src/types/redis_sortedint.cc @@ -28,19 +28,19 @@ namespace redis { -rocksdb::Status Sortedint::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, - SortedintMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisSortedint}, ns_key, metadata); +rocksdb::Status Sortedint::GetMetadata(engine::Context &ctx, const Slice &ns_key, SortedintMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisSortedint}, ns_key, metadata); } -rocksdb::Status Sortedint::Add(const Slice &user_key, const std::vector &ids, uint64_t *added_cnt) { +rocksdb::Status Sortedint::Add(engine::Context &ctx, const Slice &user_key, const std::vector &ids, + uint64_t *added_cnt) { *added_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); SortedintMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; std::string value; @@ -51,7 +51,7 @@ rocksdb::Status Sortedint::Add(const Slice &user_key, const std::vectorIsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (s.ok()) continue; batch->Put(sub_key, Slice()); *added_cnt += 1; @@ -63,17 +63,18 @@ rocksdb::Status Sortedint::Add(const Slice &user_key, const std::vectorPut(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Sortedint::Remove(const Slice &user_key, const std::vector &ids, uint64_t *removed_cnt) { +rocksdb::Status Sortedint::Remove(engine::Context &ctx, const Slice &user_key, const std::vector &ids, + uint64_t *removed_cnt) { *removed_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); SortedintMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string value; @@ -84,7 +85,7 @@ rocksdb::Status Sortedint::Remove(const Slice &user_key, const std::vectorIsSlotIdEncoded()).Encode(); - s = storage_->Get(rocksdb::ReadOptions(), sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (!s.ok()) continue; batch->Delete(sub_key); *removed_cnt += 1; @@ -94,29 +95,28 @@ rocksdb::Status Sortedint::Remove(const Slice &user_key, const std::vectorPut(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Sortedint::Card(const Slice &user_key, uint64_t *size) { +rocksdb::Status Sortedint::Card(engine::Context &ctx, const Slice &user_key, uint64_t *size) { *size = 0; std::string ns_key = AppendNamespacePrefix(user_key); SortedintMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; *size = metadata.size; return rocksdb::Status::OK(); } -rocksdb::Status Sortedint::Range(const Slice &user_key, uint64_t cursor_id, uint64_t offset, uint64_t limit, - bool reversed, std::vector *ids) { +rocksdb::Status Sortedint::Range(engine::Context &ctx, const Slice &user_key, uint64_t cursor_id, uint64_t offset, + uint64_t limit, bool reversed, std::vector *ids) { ids->clear(); std::string ns_key = AppendNamespacePrefix(user_key); SortedintMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string start_buf; @@ -129,15 +129,14 @@ rocksdb::Status Sortedint::Range(const Slice &user_key, uint64_t cursor_id, uint std::string prefix = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix); read_options.iterate_lower_bound = &lower_bound; uint64_t id = 0, pos = 0; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); for (!reversed ? iter->Seek(start_key) : iter->SeekForPrev(start_key); iter->Valid() && iter->key().starts_with(prefix); !reversed ? iter->Next() : iter->Prev()) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); @@ -150,16 +149,15 @@ rocksdb::Status Sortedint::Range(const Slice &user_key, uint64_t cursor_id, uint return rocksdb::Status::OK(); } -rocksdb::Status Sortedint::RangeByValue(const Slice &user_key, SortedintRangeSpec spec, std::vector *ids, - int *size) { +rocksdb::Status Sortedint::RangeByValue(engine::Context &ctx, const Slice &user_key, SortedintRangeSpec spec, + std::vector *ids, int *size) { if (size) *size = 0; if (ids) ids->clear(); std::string ns_key = AppendNamespacePrefix(user_key); SortedintMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string start_buf; @@ -169,15 +167,14 @@ rocksdb::Status Sortedint::RangeByValue(const Slice &user_key, SortedintRangeSpe std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; int pos = 0; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); if (!spec.reversed) { iter->Seek(start_key); } else { @@ -204,22 +201,20 @@ rocksdb::Status Sortedint::RangeByValue(const Slice &user_key, SortedintRangeSpe return rocksdb::Status::OK(); } -rocksdb::Status Sortedint::MExist(const Slice &user_key, const std::vector &ids, std::vector *exists) { +rocksdb::Status Sortedint::MExist(engine::Context &ctx, const Slice &user_key, const std::vector &ids, + std::vector *exists) { std::string ns_key = AppendNamespacePrefix(user_key); SortedintMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string value; for (const auto id : ids) { std::string id_buf; PutFixed64(&id_buf, id); std::string sub_key = InternalKey(ns_key, id_buf, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(read_options, sub_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), sub_key, &value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { exists->emplace_back(0); diff --git a/src/types/redis_sortedint.h b/src/types/redis_sortedint.h index c7f10febd65..5f9ad64d165 100644 --- a/src/types/redis_sortedint.h +++ b/src/types/redis_sortedint.h @@ -40,17 +40,21 @@ namespace redis { class Sortedint : public Database { public: explicit Sortedint(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Card(const Slice &user_key, uint64_t *size); - rocksdb::Status MExist(const Slice &user_key, const std::vector &ids, std::vector *exists); - rocksdb::Status Add(const Slice &user_key, const std::vector &ids, uint64_t *added_cnt); - rocksdb::Status Remove(const Slice &user_key, const std::vector &ids, uint64_t *removed_cnt); - rocksdb::Status Range(const Slice &user_key, uint64_t cursor_id, uint64_t page, uint64_t limit, bool reversed, - std::vector *ids); - rocksdb::Status RangeByValue(const Slice &user_key, SortedintRangeSpec spec, std::vector *ids, int *size); + rocksdb::Status Card(engine::Context &ctx, const Slice &user_key, uint64_t *size); + rocksdb::Status MExist(engine::Context &ctx, const Slice &user_key, const std::vector &ids, + std::vector *exists); + rocksdb::Status Add(engine::Context &ctx, const Slice &user_key, const std::vector &ids, + uint64_t *added_cnt); + rocksdb::Status Remove(engine::Context &ctx, const Slice &user_key, const std::vector &ids, + uint64_t *removed_cnt); + rocksdb::Status Range(engine::Context &ctx, const Slice &user_key, uint64_t cursor_id, uint64_t page, uint64_t limit, + bool reversed, std::vector *ids); + rocksdb::Status RangeByValue(engine::Context &ctx, const Slice &user_key, SortedintRangeSpec spec, + std::vector *ids, int *size); static Status ParseRangeSpec(const std::string &min, const std::string &max, SortedintRangeSpec *spec); private: - rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &ns_key, SortedintMetadata *metadata); + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, SortedintMetadata *metadata); }; } // namespace redis diff --git a/src/types/redis_stream.cc b/src/types/redis_stream.cc index 40f42012ac1..cc2e19236d4 100644 --- a/src/types/redis_stream.cc +++ b/src/types/redis_stream.cc @@ -43,16 +43,15 @@ const char *errXGroupSubcommandRequiresKeyExist = "The XGROUP subcommand requires the key to exist.\ Note that for CREATE you may want to use the MKSTREAM option to create an empty stream automatically."; -rocksdb::Status Stream::GetMetadata(Database::GetOptions get_options, const Slice &stream_name, - StreamMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisStream}, stream_name, metadata); +rocksdb::Status Stream::GetMetadata(engine::Context &ctx, const Slice &stream_name, StreamMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisStream}, stream_name, metadata); } -rocksdb::Status Stream::GetLastGeneratedID(const Slice &stream_name, StreamEntryID *id) { +rocksdb::Status Stream::GetLastGeneratedID(engine::Context &ctx, const Slice &stream_name, StreamEntryID *id) { std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -85,7 +84,7 @@ std::string Stream::internalKeyFromEntryID(const std::string &ns_key, const Stre return entry_key; } -rocksdb::Status Stream::Add(const Slice &stream_name, const StreamAddOptions &options, +rocksdb::Status Stream::Add(engine::Context &ctx, const Slice &stream_name, const StreamAddOptions &options, const std::vector &args, StreamEntryID *id) { for (auto const &v : args) { if (v.size() > INT32_MAX) { @@ -99,7 +98,7 @@ rocksdb::Status Stream::Add(const Slice &stream_name, const StreamAddOptions &op LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound() && options.nomkstream) { @@ -124,7 +123,7 @@ rocksdb::Status Stream::Add(const Slice &stream_name, const StreamAddOptions &op trim_options.max_len = options.trim_options.max_len > 0 ? options.trim_options.max_len - 1 : 0; } - trim(ns_key, trim_options, &metadata, batch->GetWriteBatch()); + trim(ctx, ns_key, trim_options, &metadata, batch->GetWriteBatch()); if (trim_options.strategy == StreamTrimStrategy::MinID && next_entry_id < trim_options.min_id) { // there is no sense to add this element because it would be removed, so just modify metadata and return it's ID @@ -162,7 +161,7 @@ rocksdb::Status Stream::Add(const Slice &stream_name, const StreamAddOptions &op *id = next_entry_id; - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } std::string Stream::internalKeyFromGroupName(const std::string &ns_key, const StreamMetadata &metadata, @@ -323,7 +322,7 @@ StreamSubkeyType Stream::identifySubkeyType(const rocksdb::Slice &key) const { return (StreamSubkeyType)type_delimiter; } -rocksdb::Status Stream::DeletePelEntries(const Slice &stream_name, const std::string &group_name, +rocksdb::Status Stream::DeletePelEntries(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::vector &entry_ids, uint64_t *acknowledged) { *acknowledged = 0; @@ -331,14 +330,14 @@ rocksdb::Status Stream::DeletePelEntries(const Slice &stream_name, const std::st LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } std::string group_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_group_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, group_key, &get_group_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, group_key, &get_group_value); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -351,7 +350,7 @@ rocksdb::Status Stream::DeletePelEntries(const Slice &stream_name, const std::st for (const auto &id : entry_ids) { std::string entry_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, id); std::string value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, &value); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -373,7 +372,7 @@ rocksdb::Status Stream::DeletePelEntries(const Slice &stream_name, const std::st for (const auto &[consumer_name, ack_count] : consumer_acknowledges) { auto consumer_meta_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string consumer_meta_original; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_meta_key, &consumer_meta_original); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_meta_key, &consumer_meta_original); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -384,34 +383,34 @@ rocksdb::Status Stream::DeletePelEntries(const Slice &stream_name, const std::st } } } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::ClaimPelEntries(const Slice &stream_name, const std::string &group_name, +rocksdb::Status Stream::ClaimPelEntries(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, const uint64_t min_idle_time_ms, const std::vector &entry_ids, const StreamClaimOptions &options, StreamClaimResult *result) { std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; std::string group_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_group_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, group_key, &get_group_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, group_key, &get_group_value); if (!s.ok()) return s; StreamConsumerGroupMetadata group_metadata = decodeStreamConsumerGroupMetadataValue(get_group_value); std::string consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string get_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok() && !s.IsNotFound()) { return s; } if (s.IsNotFound()) { int created_number = 0; - s = createConsumerWithoutLock(stream_name, group_name, consumer_name, &created_number); + s = createConsumerWithoutLock(ctx, stream_name, group_name, consumer_name, &created_number); if (!s.ok()) { return s; } @@ -431,7 +430,7 @@ rocksdb::Status Stream::ClaimPelEntries(const Slice &stream_name, const std::str for (const auto &id : entry_ids) { std::string raw_value; - rocksdb::Status s = getEntryRawValue(ns_key, metadata, id, &raw_value); + rocksdb::Status s = getEntryRawValue(ctx, ns_key, metadata, id, &raw_value); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -439,7 +438,7 @@ rocksdb::Status Stream::ClaimPelEntries(const Slice &stream_name, const std::str std::string entry_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, id); std::string value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, &value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, &value); StreamPelEntry pel_entry; if (!s.ok() && s.IsNotFound() && options.force) { @@ -469,7 +468,7 @@ rocksdb::Status Stream::ClaimPelEntries(const Slice &stream_name, const std::str std::string original_consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, pel_entry.consumer_name); std::string get_original_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, original_consumer_key, + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, original_consumer_key, &get_original_consumer_value); if (!s.ok()) { return s; @@ -510,10 +509,10 @@ rocksdb::Status Stream::ClaimPelEntries(const Slice &stream_name, const std::str batch->Put(stream_cf_handle_, consumer_key, encodeStreamConsumerMetadataValue(consumer_metadata)); batch->Put(stream_cf_handle_, group_key, encodeStreamConsumerGroupMetadataValue(group_metadata)); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &group_name, +rocksdb::Status Stream::AutoClaim(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, const StreamAutoClaimOptions &options, StreamAutoClaimResult *result) { if (options.exclude_start && options.start_id.IsMaximum()) { @@ -524,24 +523,24 @@ rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &g StreamMetadata metadata(false); LockGuard guard(storage_->GetLockManager(), ns_key); - auto s = GetMetadata(GetOptions{}, ns_key, &metadata); + auto s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { // not found will be caught by outside with no such key or consumer group return s; } std::string consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string get_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok() && !s.IsNotFound()) { return s; } if (s.IsNotFound()) { int created_number = 0; - s = createConsumerWithoutLock(stream_name, group_name, consumer_name, &created_number); + s = createConsumerWithoutLock(ctx, stream_name, group_name, consumer_name, &created_number); if (!s.ok()) { return s; } - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok()) { return s; } @@ -552,9 +551,7 @@ rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &g std::string prefix_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, options.start_id); std::string end_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, StreamEntryID::Maximum()); - LatestSnapShot ss{storage_}; - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice lower_bound(prefix_key); rocksdb::Slice upper_bound(end_key); read_options.iterate_lower_bound = &lower_bound; @@ -570,7 +567,7 @@ rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &g WriteBatchLogData log_data(kRedisStream); batch->PutLogData(log_data.Encode()); - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); uint64_t total_claimed_count = 0; for (iter->SeekToFirst(); iter->Valid() && count > 0 && attempts > 0; iter->Next()) { std::string tmp_group_name; @@ -589,7 +586,7 @@ rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &g auto entry_key = internalKeyFromEntryID(ns_key, metadata, entry_id); std::string entry_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, &entry_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, &entry_value); if (!s.ok()) { if (s.IsNotFound()) { deleted_entries.push_back(entry_id); @@ -633,7 +630,7 @@ rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &g for (const auto &[consumer, count] : claimed_consumer_entity_count) { std::string tmp_consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer); std::string tmp_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, tmp_consumer_key, &tmp_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, tmp_consumer_key, &tmp_consumer_value); if (!s.ok()) { return s; } @@ -667,11 +664,10 @@ rocksdb::Status Stream::AutoClaim(const Slice &stream_name, const std::string &g std::transform(deleted_entries.cbegin(), deleted_entries.cend(), std::back_inserter(result->deleted_ids), [](const StreamEntryID &id) { return id.ToString(); }); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } - -rocksdb::Status Stream::CreateGroup(const Slice &stream_name, const StreamXGroupCreateOptions &options, - const std::string &group_name) { +rocksdb::Status Stream::CreateGroup(engine::Context &ctx, const Slice &stream_name, + const StreamXGroupCreateOptions &options, const std::string &group_name) { if (std::isdigit(group_name[0])) { return rocksdb::Status::InvalidArgument("group name cannot start with number"); } @@ -679,7 +675,7 @@ rocksdb::Status Stream::CreateGroup(const Slice &stream_name, const StreamXGroup LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -706,7 +702,7 @@ rocksdb::Status Stream::CreateGroup(const Slice &stream_name, const StreamXGroup batch->PutLogData(log_data.Encode()); std::string get_entry_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, &get_entry_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, &get_entry_value); if (!s.IsNotFound()) { if (!s.ok()) { return s; @@ -719,16 +715,17 @@ rocksdb::Status Stream::CreateGroup(const Slice &stream_name, const StreamXGroup std::string metadata_bytes; metadata.Encode(&metadata_bytes); batch->Put(metadata_cf_handle_, ns_key, metadata_bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::DestroyGroup(const Slice &stream_name, const std::string &group_name, uint64_t *delete_cnt) { +rocksdb::Status Stream::DestroyGroup(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, + uint64_t *delete_cnt) { *delete_cnt = 0; std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -748,15 +745,13 @@ rocksdb::Status Stream::DestroyGroup(const Slice &stream_name, const std::string InternalKey(ns_key, sub_key_prefix, metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); std::string prefix_key = InternalKey(ns_key, sub_key_prefix, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { batch->Delete(stream_cf_handle_, iter->key()); *delete_cnt += 1; @@ -773,17 +768,18 @@ rocksdb::Status Stream::DestroyGroup(const Slice &stream_name, const std::string batch->Put(metadata_cf_handle_, ns_key, metadata_bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::createConsumerWithoutLock(const Slice &stream_name, const std::string &group_name, - const std::string &consumer_name, int *created_number) { +rocksdb::Status Stream::createConsumerWithoutLock(engine::Context &ctx, const Slice &stream_name, + const std::string &group_name, const std::string &consumer_name, + int *created_number) { if (std::isdigit(consumer_name[0])) { return rocksdb::Status::InvalidArgument("consumer name cannot start with number"); } std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -793,7 +789,7 @@ rocksdb::Status Stream::createConsumerWithoutLock(const Slice &stream_name, cons std::string entry_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_entry_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, &get_entry_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, &get_entry_value); if (!s.ok()) return s; StreamConsumerMetadata consumer_metadata; @@ -803,7 +799,7 @@ rocksdb::Status Stream::createConsumerWithoutLock(const Slice &stream_name, cons std::string consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string consumer_value = encodeStreamConsumerMetadataValue(consumer_metadata); std::string get_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.IsNotFound()) { return s; } @@ -817,24 +813,24 @@ rocksdb::Status Stream::createConsumerWithoutLock(const Slice &stream_name, cons consumer_group_metadata.consumer_number += 1; std::string consumer_group_metadata_bytes = encodeStreamConsumerGroupMetadataValue(consumer_group_metadata); batch->Put(stream_cf_handle_, entry_key, consumer_group_metadata_bytes); - s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); if (s.ok()) *created_number = 1; return s; } -rocksdb::Status Stream::CreateConsumer(const Slice &stream_name, const std::string &group_name, +rocksdb::Status Stream::CreateConsumer(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, int *created_number) { std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); - return createConsumerWithoutLock(stream_name, group_name, consumer_name, created_number); + return createConsumerWithoutLock(ctx, stream_name, group_name, consumer_name, created_number); } -rocksdb::Status Stream::DestroyConsumer(const Slice &stream_name, const std::string &group_name, +rocksdb::Status Stream::DestroyConsumer(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, uint64_t &deleted_pel) { std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -844,12 +840,12 @@ rocksdb::Status Stream::DestroyConsumer(const Slice &stream_name, const std::str std::string group_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_group_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, group_key, &get_group_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, group_key, &get_group_value); if (!s.ok()) return s; std::string consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string get_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -866,15 +862,13 @@ rocksdb::Status Stream::DestroyConsumer(const Slice &stream_name, const std::str std::string prefix_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, StreamEntryID::Minimum()); std::string end_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, StreamEntryID::Maximum()); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(end_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { StreamPelEntry pel_entry = decodeStreamPelEntryValue(iter->value().ToString()); if (pel_entry.consumer_name == consumer_name) { @@ -891,15 +885,15 @@ rocksdb::Status Stream::DestroyConsumer(const Slice &stream_name, const std::str group_metadata.consumer_number -= 1; group_metadata.pending_number -= deleted_pel; batch->Put(stream_cf_handle_, group_key, encodeStreamConsumerGroupMetadataValue(group_metadata)); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::GroupSetId(const Slice &stream_name, const std::string &group_name, +rocksdb::Status Stream::GroupSetId(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const StreamXGroupCreateOptions &options) { std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata; - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -909,7 +903,7 @@ rocksdb::Status Stream::GroupSetId(const Slice &stream_name, const std::string & std::string entry_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_entry_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, &get_entry_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, &get_entry_value); if (!s.ok()) return s; StreamConsumerGroupMetadata consumer_group_metadata = decodeStreamConsumerGroupMetadataValue(get_entry_value); @@ -928,18 +922,18 @@ rocksdb::Status Stream::GroupSetId(const Slice &stream_name, const std::string & WriteBatchLogData log_data(kRedisStream); batch->PutLogData(log_data.Encode()); batch->Put(stream_cf_handle_, entry_key, entry_value); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::DeleteEntries(const Slice &stream_name, const std::vector &ids, - uint64_t *deleted_cnt) { +rocksdb::Status Stream::DeleteEntries(engine::Context &ctx, const Slice &stream_name, + const std::vector &ids, uint64_t *deleted_cnt) { *deleted_cnt = 0; std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -952,20 +946,18 @@ rocksdb::Status Stream::DeleteEntries(const Slice &stream_name, const std::vecto InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); std::string prefix_key = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); for (const auto &id : ids) { std::string entry_key = internalKeyFromEntryID(ns_key, metadata, id); std::string value; - s = storage_->Get(read_options, stream_cf_handle_, entry_key, &value); + s = storage_->Get(ctx, read_options, stream_cf_handle_, entry_key, &value); if (s.ok()) { *deleted_cnt += 1; batch->Delete(stream_cf_handle_, entry_key); @@ -1013,7 +1005,7 @@ rocksdb::Status Stream::DeleteEntries(const Slice &stream_name, const std::vecto batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } // If `options` is StreamLenOptions{} the function just returns the number of entries in the stream. @@ -1023,12 +1015,13 @@ rocksdb::Status Stream::DeleteEntries(const Slice &stream_name, const std::vecto // If `StreamLenOptions::to_first` is set to true, the function will count elements // between specified ID and the first element in the stream. // The entry with the ID `StreamLenOptions::entry_id` has not taken into account (it serves as exclusive boundary). -rocksdb::Status Stream::Len(const Slice &stream_name, const StreamLenOptions &options, uint64_t *size) { +rocksdb::Status Stream::Len(engine::Context &ctx, const Slice &stream_name, const StreamLenOptions &options, + uint64_t *size) { *size = 0; std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -1058,15 +1051,13 @@ rocksdb::Status Stream::Len(const Slice &stream_name, const StreamLenOptions &op std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); std::string start_key = internalKeyFromEntryID(ns_key, metadata, options.entry_id); iter->Seek(start_key); @@ -1093,7 +1084,7 @@ rocksdb::Status Stream::Len(const Slice &stream_name, const StreamLenOptions &op return rocksdb::Status::OK(); } -rocksdb::Status Stream::range(const std::string &ns_key, const StreamMetadata &metadata, +rocksdb::Status Stream::range(engine::Context &ctx, const std::string &ns_key, const StreamMetadata &metadata, const StreamRangeOptions &options, std::vector *entries) const { std::string start_key = internalKeyFromEntryID(ns_key, metadata, options.start); std::string end_key = internalKeyFromEntryID(ns_key, metadata, options.end); @@ -1104,7 +1095,7 @@ rocksdb::Status Stream::range(const std::string &ns_key, const StreamMetadata &m } std::string entry_value; - auto s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, start_key, &entry_value); + auto s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, start_key, &entry_value); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -1127,15 +1118,13 @@ rocksdb::Status Stream::range(const std::string &ns_key, const StreamMetadata &m InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); std::string prefix_key = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); iter->Seek(start_key); if (options.reverse && (!iter->Valid() || iter->key().ToString() != start_key)) { iter->SeekForPrev(start_key); @@ -1174,18 +1163,20 @@ rocksdb::Status Stream::range(const std::string &ns_key, const StreamMetadata &m return rocksdb::Status::OK(); } -rocksdb::Status Stream::getEntryRawValue(const std::string &ns_key, const StreamMetadata &metadata, - const StreamEntryID &id, std::string *value) const { +rocksdb::Status Stream::getEntryRawValue(engine::Context &ctx, const std::string &ns_key, + const StreamMetadata &metadata, const StreamEntryID &id, + std::string *value) const { std::string entry_key = internalKeyFromEntryID(ns_key, metadata, id); - return storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, entry_key, value); + return storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, entry_key, value); } -rocksdb::Status Stream::GetStreamInfo(const rocksdb::Slice &stream_name, bool full, uint64_t count, StreamInfo *info) { +rocksdb::Status Stream::GetStreamInfo(engine::Context &ctx, const rocksdb::Slice &stream_name, bool full, + uint64_t count, StreamInfo *info) { std::string ns_key = AppendNamespacePrefix(stream_name); LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; info->size = metadata.size; @@ -1215,13 +1206,13 @@ rocksdb::Status Stream::GetStreamInfo(const rocksdb::Slice &stream_name, bool fu options.exclude_start = false; options.exclude_end = false; - s = range(ns_key, metadata, options, &info->entries); + s = range(ctx, ns_key, metadata, options, &info->entries); if (!s.ok()) { return s; } } else { std::string first_value; - s = getEntryRawValue(ns_key, metadata, metadata.first_entry_id, &first_value); + s = getEntryRawValue(ctx, ns_key, metadata, metadata.first_entry_id, &first_value); if (!s.ok()) { return s; } @@ -1235,7 +1226,7 @@ rocksdb::Status Stream::GetStreamInfo(const rocksdb::Slice &stream_name, bool fu info->first_entry = std::make_unique(metadata.first_entry_id.ToString(), std::move(values)); std::string last_value; - s = getEntryRawValue(ns_key, metadata, metadata.last_entry_id, &last_value); + s = getEntryRawValue(ctx, ns_key, metadata, metadata.last_entry_id, &last_value); if (!s.ok()) { return s; } @@ -1305,11 +1296,11 @@ static void CheckLagValid(const StreamMetadata &stream_metadata, StreamConsumerG } } -rocksdb::Status Stream::GetGroupInfo(const Slice &stream_name, +rocksdb::Status Stream::GetGroupInfo(engine::Context &ctx, const Slice &stream_name, std::vector> &group_metadata) { std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; std::string subkey_type_delimiter = std::to_string(UINT64_MAX); @@ -1319,15 +1310,13 @@ rocksdb::Status Stream::GetGroupInfo(const Slice &stream_name, std::string prefix_key = InternalKey(ns_key, subkey_type_delimiter, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { std::string group_name = groupNameFromInternalKey(iter->key()); StreamConsumerGroupMetadata cg_metadata = decodeStreamConsumerGroupMetadataValue(iter->value().ToString()); @@ -1339,11 +1328,11 @@ rocksdb::Status Stream::GetGroupInfo(const Slice &stream_name, } rocksdb::Status Stream::GetConsumerInfo( - const Slice &stream_name, const std::string &group_name, + engine::Context &ctx, const Slice &stream_name, const std::string &group_name, std::vector> &consumer_metadata) { std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; std::string subkey_type_delimiter; @@ -1356,15 +1345,13 @@ rocksdb::Status Stream::GetConsumerInfo( std::string prefix_key = InternalKey(ns_key, subkey_type_delimiter, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { std::string consumer_name = consumerNameFromInternalKey(iter->key()); StreamConsumerMetadata c_metadata = decodeStreamConsumerMetadataValue(iter->value().ToString()); @@ -1374,7 +1361,7 @@ rocksdb::Status Stream::GetConsumerInfo( return iter->status(); } -rocksdb::Status Stream::Range(const Slice &stream_name, const StreamRangeOptions &options, +rocksdb::Status Stream::Range(engine::Context &ctx, const Slice &stream_name, const StreamRangeOptions &options, std::vector *entries) { entries->clear(); @@ -1393,15 +1380,15 @@ rocksdb::Status Stream::Range(const Slice &stream_name, const StreamRangeOptions std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } - return range(ns_key, metadata, options, entries); + return range(ctx, ns_key, metadata, options, entries); } -rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOptions &options, +rocksdb::Status Stream::RangeWithPending(engine::Context &ctx, const Slice &stream_name, StreamRangeOptions &options, std::vector *entries, std::string &group_name, std::string &consumer_name, bool noack, bool latest) { entries->clear(); @@ -1422,29 +1409,29 @@ rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOp LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } std::string group_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_group_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, group_key, &get_group_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, group_key, &get_group_value); if (!s.ok()) return s; std::string consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string get_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok() && !s.IsNotFound()) { return s; } if (s.IsNotFound()) { int created_number = 0; - s = createConsumerWithoutLock(stream_name, group_name, consumer_name, &created_number); + s = createConsumerWithoutLock(ctx, stream_name, group_name, consumer_name, &created_number); if (!s.ok()) { return s; } - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, group_key, &get_group_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, group_key, &get_group_value); } auto batch = storage_->GetWriteBatchBase(); @@ -1452,7 +1439,7 @@ rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOp batch->PutLogData(log_data.Encode()); StreamConsumerGroupMetadata consumergroup_metadata = decodeStreamConsumerGroupMetadataValue(get_group_value); - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -1463,7 +1450,7 @@ rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOp if (latest) { options.start = consumergroup_metadata.last_delivered_id; - s = range(ns_key, metadata, options, entries); + s = range(ctx, ns_key, metadata, options, entries); if (!s.ok()) { return s; } @@ -1494,15 +1481,13 @@ rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOp std::string prefix_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, options.start); std::string end_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, StreamEntryID::Maximum()); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(end_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); uint64_t count = 0; for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { std::string tmp_group_name; @@ -1510,7 +1495,7 @@ rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOp StreamPelEntry pel_entry = decodeStreamPelEntryValue(iter->value().ToString()); if (pel_entry.consumer_name != consumer_name) continue; std::string raw_value; - rocksdb::Status st = getEntryRawValue(ns_key, metadata, entry_id, &raw_value); + rocksdb::Status st = getEntryRawValue(ctx, ns_key, metadata, entry_id, &raw_value); if (!st.ok() && !st.IsNotFound()) { return st; } @@ -1533,10 +1518,11 @@ rocksdb::Status Stream::RangeWithPending(const Slice &stream_name, StreamRangeOp } batch->Put(stream_cf_handle_, group_key, encodeStreamConsumerGroupMetadataValue(consumergroup_metadata)); batch->Put(stream_cf_handle_, consumer_key, encodeStreamConsumerMetadataValue(consumer_metadata)); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::Trim(const Slice &stream_name, const StreamTrimOptions &options, uint64_t *delete_cnt) { +rocksdb::Status Stream::Trim(engine::Context &ctx, const Slice &stream_name, const StreamTrimOptions &options, + uint64_t *delete_cnt) { *delete_cnt = 0; if (options.strategy == StreamTrimStrategy::None) { @@ -1548,7 +1534,7 @@ rocksdb::Status Stream::Trim(const Slice &stream_name, const StreamTrimOptions & LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -1557,21 +1543,21 @@ rocksdb::Status Stream::Trim(const Slice &stream_name, const StreamTrimOptions & WriteBatchLogData log_data(kRedisStream); batch->PutLogData(log_data.Encode()); - *delete_cnt = trim(ns_key, options, &metadata, batch->GetWriteBatch()); + *delete_cnt = trim(ctx, ns_key, options, &metadata, batch->GetWriteBatch()); if (*delete_cnt > 0) { std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } return rocksdb::Status::OK(); } -uint64_t Stream::trim(const std::string &ns_key, const StreamTrimOptions &options, StreamMetadata *metadata, - rocksdb::WriteBatch *batch) { +uint64_t Stream::trim(engine::Context &ctx, const std::string &ns_key, const StreamTrimOptions &options, + StreamMetadata *metadata, rocksdb::WriteBatch *batch) { if (metadata->size == 0) { return 0; } @@ -1590,15 +1576,13 @@ uint64_t Stream::trim(const std::string &ns_key, const StreamTrimOptions &option InternalKey(ns_key, "", metadata->version + 1, storage_->IsSlotIdEncoded()).Encode(); std::string prefix_key = InternalKey(ns_key, "", metadata->version, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); std::string start_key = internalKeyFromEntryID(ns_key, *metadata, metadata->first_entry_id); iter->Seek(start_key); @@ -1642,7 +1626,7 @@ uint64_t Stream::trim(const std::string &ns_key, const StreamTrimOptions &option return ret; } -rocksdb::Status Stream::SetId(const Slice &stream_name, const StreamEntryID &last_generated_id, +rocksdb::Status Stream::SetId(engine::Context &ctx, const Slice &stream_name, const StreamEntryID &last_generated_id, std::optional entries_added, std::optional max_deleted_id) { if (max_deleted_id && last_generated_id < max_deleted_id) { return rocksdb::Status::InvalidArgument(errMaxDeletedIdGreaterThanLastGenerated); @@ -1653,7 +1637,7 @@ rocksdb::Status Stream::SetId(const Slice &stream_name, const StreamEntryID &las LockGuard guard(storage_->GetLockManager(), ns_key); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) { return s; } @@ -1695,24 +1679,25 @@ rocksdb::Status Stream::SetId(const Slice &stream_name, const StreamEntryID &las metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status Stream::GetPendingEntries(StreamPendingOptions &options, StreamGetPendingEntryResult &pending_infos, +rocksdb::Status Stream::GetPendingEntries(engine::Context &ctx, StreamPendingOptions &options, + StreamGetPendingEntryResult &pending_infos, std::vector &ext_results) { const std::string &stream_name = options.stream_name; const std::string &group_name = options.group_name; std::string ns_key = AppendNamespacePrefix(stream_name); StreamMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } std::string group_key = internalKeyFromGroupName(ns_key, metadata, group_name); std::string get_group_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, group_key, &get_group_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, group_key, &get_group_value); if (!s.ok()) { return s.IsNotFound() ? rocksdb::Status::OK() : s; } @@ -1720,15 +1705,13 @@ rocksdb::Status Stream::GetPendingEntries(StreamPendingOptions &options, StreamG std::string prefix_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, options.start_id); std::string end_key = internalPelKeyFromGroupAndEntryId(ns_key, metadata, group_name, options.end_id); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(end_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, stream_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, stream_cf_handle_); std::unordered_set consumer_names; StreamEntryID first_entry_id{StreamEntryID::Maximum()}; StreamEntryID last_entry_id{StreamEntryID::Minimum()}; @@ -1766,7 +1749,7 @@ rocksdb::Status Stream::GetPendingEntries(StreamPendingOptions &options, StreamG } std::string consumer_key = internalKeyFromConsumerName(ns_key, metadata, group_name, consumer_name); std::string get_consumer_value; - s = storage_->Get(rocksdb::ReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); + s = storage_->Get(ctx, ctx.GetReadOptions(), stream_cf_handle_, consumer_key, &get_consumer_value); if (!s.ok() && !s.IsNotFound()) { return s; } diff --git a/src/types/redis_stream.h b/src/types/redis_stream.h index 57e7e978ada..3f094e8d7f3 100644 --- a/src/types/redis_stream.h +++ b/src/types/redis_stream.h @@ -37,56 +37,62 @@ class Stream : public SubKeyScanner { public: explicit Stream(engine::Storage *storage, const std::string &ns) : SubKeyScanner(storage, ns), stream_cf_handle_(storage->GetCFHandle(ColumnFamilyID::Stream)) {} - rocksdb::Status Add(const Slice &stream_name, const StreamAddOptions &options, const std::vector &values, - StreamEntryID *id); - rocksdb::Status CreateGroup(const Slice &stream_name, const StreamXGroupCreateOptions &options, + rocksdb::Status Add(engine::Context &ctx, const Slice &stream_name, const StreamAddOptions &options, + const std::vector &values, StreamEntryID *id); + rocksdb::Status CreateGroup(engine::Context &ctx, const Slice &stream_name, const StreamXGroupCreateOptions &options, const std::string &group_name); - rocksdb::Status DestroyGroup(const Slice &stream_name, const std::string &group_name, uint64_t *delete_cnt); - rocksdb::Status CreateConsumer(const Slice &stream_name, const std::string &group_name, + rocksdb::Status DestroyGroup(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, + uint64_t *delete_cnt); + rocksdb::Status CreateConsumer(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, int *created_number); - rocksdb::Status DestroyConsumer(const Slice &stream_name, const std::string &group_name, + rocksdb::Status DestroyConsumer(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, uint64_t &deleted_pel); - rocksdb::Status GroupSetId(const Slice &stream_name, const std::string &group_name, + rocksdb::Status GroupSetId(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const StreamXGroupCreateOptions &options); - rocksdb::Status DeleteEntries(const Slice &stream_name, const std::vector &ids, uint64_t *deleted_cnt); - rocksdb::Status DeletePelEntries(const Slice &stream_name, const std::string &group_name, + rocksdb::Status DeleteEntries(engine::Context &ctx, const Slice &stream_name, const std::vector &ids, + uint64_t *deleted_cnt); + rocksdb::Status DeletePelEntries(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::vector &entry_ids, uint64_t *acknowledged); - rocksdb::Status ClaimPelEntries(const Slice &stream_name, const std::string &group_name, + rocksdb::Status ClaimPelEntries(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, uint64_t min_idle_time_ms, const std::vector &entry_ids, const StreamClaimOptions &options, StreamClaimResult *result); - rocksdb::Status AutoClaim(const Slice &stream_name, const std::string &group_name, const std::string &consumer_name, - const StreamAutoClaimOptions &options, StreamAutoClaimResult *result); - rocksdb::Status Len(const Slice &stream_name, const StreamLenOptions &options, uint64_t *size); - rocksdb::Status GetStreamInfo(const Slice &stream_name, bool full, uint64_t count, StreamInfo *info); - rocksdb::Status GetGroupInfo(const Slice &stream_name, + rocksdb::Status AutoClaim(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, + const std::string &consumer_name, const StreamAutoClaimOptions &options, + StreamAutoClaimResult *result); + rocksdb::Status Len(engine::Context &ctx, const Slice &stream_name, const StreamLenOptions &options, uint64_t *size); + rocksdb::Status GetStreamInfo(engine::Context &ctx, const Slice &stream_name, bool full, uint64_t count, + StreamInfo *info); + rocksdb::Status GetGroupInfo(engine::Context &ctx, const Slice &stream_name, std::vector> &group_metadata); - rocksdb::Status GetConsumerInfo(const Slice &stream_name, const std::string &group_name, + rocksdb::Status GetConsumerInfo(engine::Context &ctx, const Slice &stream_name, const std::string &group_name, std::vector> &consumer_metadata); - rocksdb::Status GetPendingEntries(StreamPendingOptions &options, StreamGetPendingEntryResult &pending_infos, - std::vector &ext_results); - rocksdb::Status Range(const Slice &stream_name, const StreamRangeOptions &options, std::vector *entries); - rocksdb::Status RangeWithPending(const Slice &stream_name, StreamRangeOptions &options, + rocksdb::Status GetPendingEntries(engine::Context &ctx, StreamPendingOptions &options, + StreamGetPendingEntryResult &pending_infos, std::vector &ext_results); + rocksdb::Status Range(engine::Context &ctx, const Slice &stream_name, const StreamRangeOptions &options, + std::vector *entries); + rocksdb::Status RangeWithPending(engine::Context &ctx, const Slice &stream_name, StreamRangeOptions &options, std::vector *entries, std::string &group_name, std::string &consumer_name, bool noack, bool latest); - rocksdb::Status Trim(const Slice &stream_name, const StreamTrimOptions &options, uint64_t *delete_cnt); - rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &stream_name, StreamMetadata *metadata); - rocksdb::Status GetLastGeneratedID(const Slice &stream_name, StreamEntryID *id); - rocksdb::Status SetId(const Slice &stream_name, const StreamEntryID &last_generated_id, + rocksdb::Status Trim(engine::Context &ctx, const Slice &stream_name, const StreamTrimOptions &options, + uint64_t *delete_cnt); + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &stream_name, StreamMetadata *metadata); + rocksdb::Status GetLastGeneratedID(engine::Context &ctx, const Slice &stream_name, StreamEntryID *id); + rocksdb::Status SetId(engine::Context &ctx, const Slice &stream_name, const StreamEntryID &last_generated_id, std::optional entries_added, std::optional max_deleted_id); private: rocksdb::ColumnFamilyHandle *stream_cf_handle_; - rocksdb::Status range(const std::string &ns_key, const StreamMetadata &metadata, const StreamRangeOptions &options, - std::vector *entries) const; - rocksdb::Status getEntryRawValue(const std::string &ns_key, const StreamMetadata &metadata, const StreamEntryID &id, - std::string *value) const; + rocksdb::Status range(engine::Context &ctx, const std::string &ns_key, const StreamMetadata &metadata, + const StreamRangeOptions &options, std::vector *entries) const; + rocksdb::Status getEntryRawValue(engine::Context &ctx, const std::string &ns_key, const StreamMetadata &metadata, + const StreamEntryID &id, std::string *value) const; StreamEntryID entryIDFromInternalKey(const rocksdb::Slice &key) const; std::string internalKeyFromEntryID(const std::string &ns_key, const StreamMetadata &metadata, const StreamEntryID &id) const; - uint64_t trim(const std::string &ns_key, const StreamTrimOptions &options, StreamMetadata *metadata, - rocksdb::WriteBatch *batch); + uint64_t trim(engine::Context &ctx, const std::string &ns_key, const StreamTrimOptions &options, + StreamMetadata *metadata, rocksdb::WriteBatch *batch); std::string internalKeyFromGroupName(const std::string &ns_key, const StreamMetadata &metadata, const std::string &group_name) const; std::string groupNameFromInternalKey(rocksdb::Slice key) const; @@ -97,8 +103,9 @@ class Stream : public SubKeyScanner { std::string consumerNameFromInternalKey(rocksdb::Slice key) const; static std::string encodeStreamConsumerMetadataValue(const StreamConsumerMetadata &consumer_metadata); static StreamConsumerMetadata decodeStreamConsumerMetadataValue(const std::string &value); - rocksdb::Status createConsumerWithoutLock(const Slice &stream_name, const std::string &group_name, - const std::string &consumer_name, int *created_number); + rocksdb::Status createConsumerWithoutLock(engine::Context &ctx, const Slice &stream_name, + const std::string &group_name, const std::string &consumer_name, + int *created_number); std::string internalPelKeyFromGroupAndEntryId(const std::string &ns_key, const StreamMetadata &metadata, const std::string &group_name, const StreamEntryID &id); StreamEntryID groupAndEntryIdFromPelInternalKey(rocksdb::Slice key, std::string &group_name); diff --git a/src/types/redis_string.cc b/src/types/redis_string.cc index dca9b326c0d..9cd973476e2 100644 --- a/src/types/redis_string.cc +++ b/src/types/redis_string.cc @@ -32,17 +32,16 @@ namespace redis { -std::vector String::getRawValues(const std::vector &keys, +std::vector String::getRawValues(engine::Context &ctx, const std::vector &keys, std::vector *raw_values) { raw_values->clear(); - rocksdb::ReadOptions read_options = storage_->DefaultMultiGetOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultMultiGetOptions(); raw_values->resize(keys.size()); std::vector statuses(keys.size()); std::vector pin_values(keys.size()); - storage_->MultiGet(read_options, metadata_cf_handle_, keys.size(), keys.data(), pin_values.data(), statuses.data()); + storage_->MultiGet(ctx, read_options, metadata_cf_handle_, keys.size(), keys.data(), pin_values.data(), + statuses.data()); for (size_t i = 0; i < keys.size(); i++) { if (!statuses[i].ok()) continue; (*raw_values)[i].assign(pin_values[i].data(), pin_values[i].size()); @@ -58,10 +57,10 @@ std::vector String::getRawValues(const std::vector &keys return statuses; } -rocksdb::Status String::getRawValue(const std::string &ns_key, std::string *raw_value) { +rocksdb::Status String::getRawValue(engine::Context &ctx, const std::string &ns_key, std::string *raw_value) { raw_value->clear(); - auto s = GetRawMetadata(GetOptions{}, ns_key, raw_value); + auto s = GetRawMetadata(ctx, ns_key, raw_value); if (!s.ok()) return s; Metadata metadata(kRedisNone, false); @@ -69,11 +68,12 @@ rocksdb::Status String::getRawValue(const std::string &ns_key, std::string *raw_ return ParseMetadata({kRedisString}, &slice, &metadata); } -rocksdb::Status String::getValueAndExpire(const std::string &ns_key, std::string *value, uint64_t *expire) { +rocksdb::Status String::getValueAndExpire(engine::Context &ctx, const std::string &ns_key, std::string *value, + uint64_t *expire) { value->clear(); std::string raw_value; - auto s = getRawValue(ns_key, &raw_value); + auto s = getRawValue(ctx, ns_key, &raw_value); if (!s.ok()) return s; size_t offset = Metadata::GetOffsetAfterExpire(raw_value[0]); @@ -88,12 +88,13 @@ rocksdb::Status String::getValueAndExpire(const std::string &ns_key, std::string return rocksdb::Status::OK(); } -rocksdb::Status String::getValue(const std::string &ns_key, std::string *value) { - return getValueAndExpire(ns_key, value, nullptr); +rocksdb::Status String::getValue(engine::Context &ctx, const std::string &ns_key, std::string *value) { + return getValueAndExpire(ctx, ns_key, value, nullptr); } -std::vector String::getValues(const std::vector &ns_keys, std::vector *values) { - auto statuses = getRawValues(ns_keys, values); +std::vector String::getValues(engine::Context &ctx, const std::vector &ns_keys, + std::vector *values) { + auto statuses = getRawValues(ctx, ns_keys, values); for (size_t i = 0; i < ns_keys.size(); i++) { if (!statuses[i].ok()) continue; size_t offset = Metadata::GetOffsetAfterExpire((*values)[i][0]); @@ -102,21 +103,22 @@ std::vector String::getValues(const std::vector &ns_keys return statuses; } -rocksdb::Status String::updateRawValue(const std::string &ns_key, const std::string &raw_value) { +rocksdb::Status String::updateRawValue(engine::Context &ctx, const std::string &ns_key, const std::string &raw_value) { auto batch = storage_->GetWriteBatchBase(); WriteBatchLogData log_data(kRedisString); batch->PutLogData(log_data.Encode()); batch->Put(metadata_cf_handle_, ns_key, raw_value); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status String::Append(const std::string &user_key, const std::string &value, uint64_t *new_size) { +rocksdb::Status String::Append(engine::Context &ctx, const std::string &user_key, const std::string &value, + uint64_t *new_size) { *new_size = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); std::string raw_value; - rocksdb::Status s = getRawValue(ns_key, &raw_value); + rocksdb::Status s = getRawValue(ctx, ns_key, &raw_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { Metadata metadata(kRedisString, false); @@ -124,10 +126,11 @@ rocksdb::Status String::Append(const std::string &user_key, const std::string &v } raw_value.append(value); *new_size = raw_value.size() - Metadata::GetOffsetAfterExpire(raw_value[0]); - return updateRawValue(ns_key, raw_value); + return updateRawValue(ctx, ns_key, raw_value); } -std::vector String::MGet(const std::vector &keys, std::vector *values) { +std::vector String::MGet(engine::Context &ctx, const std::vector &keys, + std::vector *values) { std::vector ns_keys; ns_keys.reserve(keys.size()); for (const auto &key : keys) { @@ -139,19 +142,20 @@ std::vector String::MGet(const std::vector &keys, std::v for (const auto &ns_key : ns_keys) { slice_keys.emplace_back(ns_key); } - return getValues(slice_keys, values); + return getValues(ctx, slice_keys, values); } -rocksdb::Status String::Get(const std::string &user_key, std::string *value) { +rocksdb::Status String::Get(engine::Context &ctx, const std::string &user_key, std::string *value) { std::string ns_key = AppendNamespacePrefix(user_key); - return getValue(ns_key, value); + return getValue(ctx, ns_key, value); } -rocksdb::Status String::GetEx(const std::string &user_key, std::string *value, std::optional expire) { +rocksdb::Status String::GetEx(engine::Context &ctx, const std::string &user_key, std::string *value, + std::optional expire) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = getValue(ns_key, value); + rocksdb::Status s = getValue(ctx, ns_key, value); if (!s.ok()) return s; std::string raw_data; @@ -168,33 +172,34 @@ rocksdb::Status String::GetEx(const std::string &user_key, std::string *value, s WriteBatchLogData log_data(kRedisString); batch->PutLogData(log_data.Encode()); batch->Put(metadata_cf_handle_, ns_key, raw_data); - s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); if (!s.ok()) return s; return rocksdb::Status::OK(); } -rocksdb::Status String::GetSet(const std::string &user_key, const std::string &new_value, +rocksdb::Status String::GetSet(engine::Context &ctx, const std::string &user_key, const std::string &new_value, std::optional &old_value) { - auto s = Set(user_key, new_value, {/*expire=*/0, StringSetType::NONE, /*get=*/true, /*keep_ttl=*/false}, old_value); + auto s = + Set(ctx, user_key, new_value, {/*expire=*/0, StringSetType::NONE, /*get=*/true, /*keep_ttl=*/false}, old_value); return s; } -rocksdb::Status String::GetDel(const std::string &user_key, std::string *value) { +rocksdb::Status String::GetDel(engine::Context &ctx, const std::string &user_key, std::string *value) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = getValue(ns_key, value); + rocksdb::Status s = getValue(ctx, ns_key, value); if (!s.ok()) return s; - return storage_->Delete(storage_->DefaultWriteOptions(), metadata_cf_handle_, ns_key); + return storage_->Delete(ctx, storage_->DefaultWriteOptions(), metadata_cf_handle_, ns_key); } -rocksdb::Status String::Set(const std::string &user_key, const std::string &value) { +rocksdb::Status String::Set(engine::Context &ctx, const std::string &user_key, const std::string &value) { std::vector pairs{StringPair{user_key, value}}; - return MSet(pairs, /*expire=*/0, /*lock=*/true); + return MSet(ctx, pairs, /*expire=*/0, /*lock=*/true); } -rocksdb::Status String::Set(const std::string &user_key, const std::string &value, StringSetArgs args, - std::optional &ret) { +rocksdb::Status String::Set(engine::Context &ctx, const std::string &user_key, const std::string &value, + StringSetArgs args, std::optional &ret) { uint64_t expire = 0; std::string ns_key = AppendNamespacePrefix(user_key); @@ -203,7 +208,7 @@ rocksdb::Status String::Set(const std::string &user_key, const std::string &valu if (need_old_value) { std::string old_value; uint64_t old_expire = 0; - auto s = getValueAndExpire(ns_key, &old_value, &old_expire); + auto s = getValueAndExpire(ctx, ns_key, &old_value, &old_expire); if (!s.ok() && !s.IsNotFound() && !s.IsInvalidArgument()) return s; // GET option if (args.get) { @@ -251,35 +256,38 @@ rocksdb::Status String::Set(const std::string &user_key, const std::string &valu metadata.expire = expire; metadata.Encode(&new_raw_value); new_raw_value.append(value); - return updateRawValue(ns_key, new_raw_value); + return updateRawValue(ctx, ns_key, new_raw_value); } -rocksdb::Status String::SetEX(const std::string &user_key, const std::string &value, uint64_t expire_ms) { +rocksdb::Status String::SetEX(engine::Context &ctx, const std::string &user_key, const std::string &value, + uint64_t expire_ms) { std::optional ret; - return Set(user_key, value, {expire_ms, StringSetType::NONE, /*get=*/false, /*keep_ttl=*/false}, ret); + return Set(ctx, user_key, value, {expire_ms, StringSetType::NONE, /*get=*/false, /*keep_ttl=*/false}, ret); } -rocksdb::Status String::SetNX(const std::string &user_key, const std::string &value, uint64_t expire_ms, bool *flag) { +rocksdb::Status String::SetNX(engine::Context &ctx, const std::string &user_key, const std::string &value, + uint64_t expire_ms, bool *flag) { std::optional ret; - auto s = Set(user_key, value, {expire_ms, StringSetType::NX, /*get=*/false, /*keep_ttl=*/false}, ret); + auto s = Set(ctx, user_key, value, {expire_ms, StringSetType::NX, /*get=*/false, /*keep_ttl=*/false}, ret); *flag = ret.has_value(); return s; } -rocksdb::Status String::SetXX(const std::string &user_key, const std::string &value, uint64_t expire_ms, bool *flag) { +rocksdb::Status String::SetXX(engine::Context &ctx, const std::string &user_key, const std::string &value, + uint64_t expire_ms, bool *flag) { std::optional ret; - auto s = Set(user_key, value, {expire_ms, StringSetType::XX, /*get=*/false, /*keep_ttl=*/false}, ret); + auto s = Set(ctx, user_key, value, {expire_ms, StringSetType::XX, /*get=*/false, /*keep_ttl=*/false}, ret); *flag = ret.has_value(); return s; } -rocksdb::Status String::SetRange(const std::string &user_key, size_t offset, const std::string &value, - uint64_t *new_size) { +rocksdb::Status String::SetRange(engine::Context &ctx, const std::string &user_key, size_t offset, + const std::string &value, uint64_t *new_size) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); std::string raw_value; - rocksdb::Status s = getRawValue(ns_key, &raw_value); + rocksdb::Status s = getRawValue(ctx, ns_key, &raw_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { @@ -310,15 +318,16 @@ rocksdb::Status String::SetRange(const std::string &user_key, size_t offset, con } } *new_size = raw_value.size() - header_offset; - return updateRawValue(ns_key, raw_value); + return updateRawValue(ctx, ns_key, raw_value); } -rocksdb::Status String::IncrBy(const std::string &user_key, int64_t increment, int64_t *new_value) { +rocksdb::Status String::IncrBy(engine::Context &ctx, const std::string &user_key, int64_t increment, + int64_t *new_value) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); std::string raw_value; - rocksdb::Status s = getRawValue(ns_key, &raw_value); + rocksdb::Status s = getRawValue(ctx, ns_key, &raw_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { Metadata metadata(kRedisString, false); @@ -347,14 +356,15 @@ rocksdb::Status String::IncrBy(const std::string &user_key, int64_t increment, i raw_value = raw_value.substr(0, offset); raw_value.append(std::to_string(n)); - return updateRawValue(ns_key, raw_value); + return updateRawValue(ctx, ns_key, raw_value); } -rocksdb::Status String::IncrByFloat(const std::string &user_key, double increment, double *new_value) { +rocksdb::Status String::IncrByFloat(engine::Context &ctx, const std::string &user_key, double increment, + double *new_value) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); std::string raw_value; - rocksdb::Status s = getRawValue(ns_key, &raw_value); + rocksdb::Status s = getRawValue(ctx, ns_key, &raw_value); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { @@ -380,10 +390,11 @@ rocksdb::Status String::IncrByFloat(const std::string &user_key, double incremen raw_value = raw_value.substr(0, offset); raw_value.append(std::to_string(n)); - return updateRawValue(ns_key, raw_value); + return updateRawValue(ctx, ns_key, raw_value); } -rocksdb::Status String::MSet(const std::vector &pairs, uint64_t expire_ms, bool lock) { +rocksdb::Status String::MSet(engine::Context &ctx, const std::vector &pairs, uint64_t expire_ms, + bool lock) { // Data race, key string maybe overwrite by other key while didn't lock the keys here, // to improve the set performance std::optional guard; @@ -409,10 +420,11 @@ rocksdb::Status String::MSet(const std::vector &pairs, uint64_t expi std::string ns_key = AppendNamespacePrefix(pair.key); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status String::MSetNX(const std::vector &pairs, uint64_t expire_ms, bool *flag) { +rocksdb::Status String::MSetNX(engine::Context &ctx, const std::vector &pairs, uint64_t expire_ms, + bool *flag) { *flag = false; int exists = 0; @@ -430,11 +442,11 @@ rocksdb::Status String::MSetNX(const std::vector &pairs, uint64_t ex // Lock these keys before doing anything. MultiLockGuard guard(storage_->GetLockManager(), lock_keys); - if (Exists(keys, &exists).ok() && exists > 0) { + if (Exists(ctx, keys, &exists).ok() && exists > 0) { return rocksdb::Status::OK(); } - rocksdb::Status s = MSet(pairs, /*expire_ms=*/expire_ms, /*lock=*/false); + rocksdb::Status s = MSet(ctx, pairs, /*expire_ms=*/expire_ms, /*lock=*/false); if (!s.ok()) return s; *flag = true; @@ -446,15 +458,15 @@ rocksdb::Status String::MSetNX(const std::vector &pairs, uint64_t ex // 1 if the operation is successful // -1 if the user_key does not exist // 0 if the operation fails -rocksdb::Status String::CAS(const std::string &user_key, const std::string &old_value, const std::string &new_value, - uint64_t expire, int *flag) { +rocksdb::Status String::CAS(engine::Context &ctx, const std::string &user_key, const std::string &old_value, + const std::string &new_value, uint64_t expire, int *flag) { *flag = 0; std::string current_value; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = getValue(ns_key, ¤t_value); + rocksdb::Status s = getValue(ctx, ns_key, ¤t_value); if (!s.ok() && !s.IsNotFound()) { return s; @@ -471,7 +483,7 @@ rocksdb::Status String::CAS(const std::string &user_key, const std::string &old_ metadata.expire = expire; metadata.Encode(&raw_value); raw_value.append(new_value); - auto write_status = updateRawValue(ns_key, raw_value); + auto write_status = updateRawValue(ctx, ns_key, raw_value); if (!write_status.ok()) { return write_status; } @@ -483,14 +495,14 @@ rocksdb::Status String::CAS(const std::string &user_key, const std::string &old_ // Delete a specified user_key if the current value of the user_key matches a specified value. // For ret, same as CAS. -rocksdb::Status String::CAD(const std::string &user_key, const std::string &value, int *flag) { +rocksdb::Status String::CAD(engine::Context &ctx, const std::string &user_key, const std::string &value, int *flag) { *flag = 0; std::string current_value; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); - rocksdb::Status s = getValue(ns_key, ¤t_value); + rocksdb::Status s = getValue(ctx, ns_key, ¤t_value); if (!s.ok() && !s.IsNotFound()) { return s; @@ -503,7 +515,7 @@ rocksdb::Status String::CAD(const std::string &user_key, const std::string &valu if (value == current_value) { auto delete_status = - storage_->Delete(storage_->DefaultWriteOptions(), storage_->GetCFHandle(ColumnFamilyID::Metadata), ns_key); + storage_->Delete(ctx, storage_->DefaultWriteOptions(), storage_->GetCFHandle(ColumnFamilyID::Metadata), ns_key); if (!delete_status.ok()) { return delete_status; } @@ -513,8 +525,8 @@ rocksdb::Status String::CAD(const std::string &user_key, const std::string &valu return rocksdb::Status::OK(); } -rocksdb::Status String::LCS(const std::string &user_key1, const std::string &user_key2, StringLCSArgs args, - StringLCSResult *rst) { +rocksdb::Status String::LCS(engine::Context &ctx, const std::string &user_key1, const std::string &user_key2, + StringLCSArgs args, StringLCSResult *rst) { if (args.type == StringLCSType::LEN) { *rst = static_cast(0); } else if (args.type == StringLCSType::IDX) { @@ -527,8 +539,8 @@ rocksdb::Status String::LCS(const std::string &user_key1, const std::string &use std::string b; std::string ns_key1 = AppendNamespacePrefix(user_key1); std::string ns_key2 = AppendNamespacePrefix(user_key2); - auto s1 = getValue(ns_key1, &a); - auto s2 = getValue(ns_key2, &b); + auto s1 = getValue(ctx, ns_key1, &a); + auto s2 = getValue(ctx, ns_key2, &b); if (!s1.ok() && !s1.IsNotFound()) { return s1; diff --git a/src/types/redis_string.h b/src/types/redis_string.h index 34afb0bd95b..b218bae346a 100644 --- a/src/types/redis_string.h +++ b/src/types/redis_string.h @@ -77,37 +77,48 @@ namespace redis { class String : public Database { public: explicit String(engine::Storage *storage, const std::string &ns) : Database(storage, ns) {} - rocksdb::Status Append(const std::string &user_key, const std::string &value, uint64_t *new_size); - rocksdb::Status Get(const std::string &user_key, std::string *value); - rocksdb::Status GetEx(const std::string &user_key, std::string *value, std::optional expire); - rocksdb::Status GetSet(const std::string &user_key, const std::string &new_value, + rocksdb::Status Append(engine::Context &ctx, const std::string &user_key, const std::string &value, + uint64_t *new_size); + rocksdb::Status Get(engine::Context &ctx, const std::string &user_key, std::string *value); + rocksdb::Status GetEx(engine::Context &ctx, const std::string &user_key, std::string *value, + std::optional expire); + rocksdb::Status GetSet(engine::Context &ctx, const std::string &user_key, const std::string &new_value, std::optional &old_value); - rocksdb::Status GetDel(const std::string &user_key, std::string *value); - rocksdb::Status Set(const std::string &user_key, const std::string &value); - rocksdb::Status Set(const std::string &user_key, const std::string &value, StringSetArgs args, + rocksdb::Status GetDel(engine::Context &ctx, const std::string &user_key, std::string *value); + rocksdb::Status Set(engine::Context &ctx, const std::string &user_key, const std::string &value); + rocksdb::Status Set(engine::Context &ctx, const std::string &user_key, const std::string &value, StringSetArgs args, std::optional &ret); - rocksdb::Status SetEX(const std::string &user_key, const std::string &value, uint64_t expire_ms); - rocksdb::Status SetNX(const std::string &user_key, const std::string &value, uint64_t expire_ms, bool *flag); - rocksdb::Status SetXX(const std::string &user_key, const std::string &value, uint64_t expire_ms, bool *flag); - rocksdb::Status SetRange(const std::string &user_key, size_t offset, const std::string &value, uint64_t *new_size); - rocksdb::Status IncrBy(const std::string &user_key, int64_t increment, int64_t *new_value); - rocksdb::Status IncrByFloat(const std::string &user_key, double increment, double *new_value); - std::vector MGet(const std::vector &keys, std::vector *values); - rocksdb::Status MSet(const std::vector &pairs, uint64_t expire_ms, bool lock = true); - rocksdb::Status MSetNX(const std::vector &pairs, uint64_t expire_ms, bool *flag); - rocksdb::Status CAS(const std::string &user_key, const std::string &old_value, const std::string &new_value, - uint64_t expire_ms, int *flag); - rocksdb::Status CAD(const std::string &user_key, const std::string &value, int *flag); - rocksdb::Status LCS(const std::string &user_key1, const std::string &user_key2, StringLCSArgs args, - StringLCSResult *rst); + rocksdb::Status SetEX(engine::Context &ctx, const std::string &user_key, const std::string &value, + uint64_t expire_ms); + rocksdb::Status SetNX(engine::Context &ctx, const std::string &user_key, const std::string &value, uint64_t expire_ms, + bool *flag); + rocksdb::Status SetXX(engine::Context &ctx, const std::string &user_key, const std::string &value, uint64_t expire_ms, + bool *flag); + rocksdb::Status SetRange(engine::Context &ctx, const std::string &user_key, size_t offset, const std::string &value, + uint64_t *new_size); + rocksdb::Status IncrBy(engine::Context &ctx, const std::string &user_key, int64_t increment, int64_t *new_value); + rocksdb::Status IncrByFloat(engine::Context &ctx, const std::string &user_key, double increment, double *new_value); + std::vector MGet(engine::Context &ctx, const std::vector &keys, + std::vector *values); + rocksdb::Status MSet(engine::Context &ctx, const std::vector &pairs, uint64_t expire_ms, + bool lock = true); + rocksdb::Status MSetNX(engine::Context &ctx, const std::vector &pairs, uint64_t expire_ms, bool *flag); + rocksdb::Status CAS(engine::Context &ctx, const std::string &user_key, const std::string &old_value, + const std::string &new_value, uint64_t expire_ms, int *flag); + rocksdb::Status CAD(engine::Context &ctx, const std::string &user_key, const std::string &value, int *flag); + rocksdb::Status LCS(engine::Context &ctx, const std::string &user_key1, const std::string &user_key2, + StringLCSArgs args, StringLCSResult *rst); private: - rocksdb::Status getValue(const std::string &ns_key, std::string *value); - rocksdb::Status getValueAndExpire(const std::string &ns_key, std::string *value, uint64_t *expire_ms); - std::vector getValues(const std::vector &ns_keys, std::vector *values); - rocksdb::Status getRawValue(const std::string &ns_key, std::string *raw_value); - std::vector getRawValues(const std::vector &keys, std::vector *raw_values); - rocksdb::Status updateRawValue(const std::string &ns_key, const std::string &raw_value); + rocksdb::Status getValue(engine::Context &ctx, const std::string &ns_key, std::string *value); + rocksdb::Status getValueAndExpire(engine::Context &ctx, const std::string &ns_key, std::string *value, + uint64_t *expire_ms); + std::vector getValues(engine::Context &ctx, const std::vector &ns_keys, + std::vector *values); + rocksdb::Status getRawValue(engine::Context &ctx, const std::string &ns_key, std::string *raw_value); + std::vector getRawValues(engine::Context &ctx, const std::vector &keys, + std::vector *raw_values); + rocksdb::Status updateRawValue(engine::Context &ctx, const std::string &ns_key, const std::string &raw_value); }; } // namespace redis diff --git a/src/types/redis_zset.cc b/src/types/redis_zset.cc index 4d2d92d1604..2f3a77f0643 100644 --- a/src/types/redis_zset.cc +++ b/src/types/redis_zset.cc @@ -32,18 +32,19 @@ namespace redis { -rocksdb::Status ZSet::GetMetadata(Database::GetOptions get_options, const Slice &ns_key, ZSetMetadata *metadata) { - return Database::GetMetadata(get_options, {kRedisZSet}, ns_key, metadata); +rocksdb::Status ZSet::GetMetadata(engine::Context &ctx, const Slice &ns_key, ZSetMetadata *metadata) { + return Database::GetMetadata(ctx, {kRedisZSet}, ns_key, metadata); } -rocksdb::Status ZSet::Add(const Slice &user_key, ZAddFlags flags, MemberScores *mscores, uint64_t *added_cnt) { +rocksdb::Status ZSet::Add(engine::Context &ctx, const Slice &user_key, ZAddFlags flags, MemberScores *mscores, + uint64_t *added_cnt) { *added_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ZSetMetadata metadata; - rocksdb::Status s = GetMetadata(Database::GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok() && !s.IsNotFound()) return s; int added = 0; @@ -59,7 +60,7 @@ rocksdb::Status ZSet::Add(const Slice &user_key, ZAddFlags flags, MemberScores * std::string member_key = InternalKey(ns_key, it->member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); if (metadata.size > 0) { std::string old_score_bytes; - s = storage_->Get(rocksdb::ReadOptions(), member_key, &old_score_bytes); + s = storage_->Get(ctx, ctx.GetReadOptions(), member_key, &old_score_bytes); if (!s.ok() && !s.IsNotFound()) return s; if (s.ok()) { if (!s.IsNotFound() && flags.HasNX()) { @@ -116,43 +117,44 @@ rocksdb::Status ZSet::Add(const Slice &user_key, ZAddFlags flags, MemberScores * if (flags.HasCH()) { *added_cnt += changed; } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status ZSet::Card(const Slice &user_key, uint64_t *size) { +rocksdb::Status ZSet::Card(engine::Context &ctx, const Slice &user_key, uint64_t *size) { *size = 0; std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; *size = metadata.size; return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Count(const Slice &user_key, const RangeScoreSpec &spec, uint64_t *size) { - return RangeByScore(user_key, spec, nullptr, size); +rocksdb::Status ZSet::Count(engine::Context &ctx, const Slice &user_key, const RangeScoreSpec &spec, uint64_t *size) { + return RangeByScore(ctx, user_key, spec, nullptr, size); } -rocksdb::Status ZSet::IncrBy(const Slice &user_key, const Slice &member, double increment, double *score) { +rocksdb::Status ZSet::IncrBy(engine::Context &ctx, const Slice &user_key, const Slice &member, double increment, + double *score) { uint64_t ret = 0; std::vector mscores; mscores.emplace_back(MemberScore{member.ToString(), increment}); - rocksdb::Status s = Add(user_key, ZAddFlags::Incr(), &mscores, &ret); + rocksdb::Status s = Add(ctx, user_key, ZAddFlags::Incr(), &mscores, &ret); if (!s.ok()) return s; *score = mscores[0].score; return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Pop(const Slice &user_key, int count, bool min, MemberScores *mscores) { +rocksdb::Status ZSet::Pop(engine::Context &ctx, const Slice &user_key, int count, bool min, MemberScores *mscores) { mscores->clear(); std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; if (count <= 0) return rocksdb::Status::OK(); if (count > static_cast(metadata.size)) count = static_cast(metadata.size); @@ -169,15 +171,13 @@ rocksdb::Status ZSet::Pop(const Slice &user_key, int count, bool min, MemberScor WriteBatchLogData log_data(kRedisZSet); batch->PutLogData(log_data.Encode()); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, score_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, score_cf_handle_); iter->Seek(start_key); // see comment in RangeByScore() if (!min && (!iter->Valid() || !iter->key().starts_with(prefix_key))) { @@ -200,11 +200,11 @@ rocksdb::Status ZSet::Pop(const Slice &user_key, int count, bool min, MemberScor metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const RangeRankSpec &spec, MemberScores *mscores, - uint64_t *removed_cnt) { +rocksdb::Status ZSet::RangeByRank(engine::Context &ctx, const Slice &user_key, const RangeRankSpec &spec, + MemberScores *mscores, uint64_t *removed_cnt) { if (mscores) mscores->clear(); uint64_t cnt = 0; @@ -216,8 +216,8 @@ rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const RangeRankSpec &sp std::optional lock_guard; if (spec.with_deletion) lock_guard.emplace(storage_->GetLockManager(), ns_key); ZSetMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; int start = spec.start; @@ -239,15 +239,14 @@ rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const RangeRankSpec &sp InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); int removed_subkey = 0; - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; auto batch = storage_->GetWriteBatchBase(); - auto iter = util::UniqueIterator(storage_, read_options, score_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, score_cf_handle_); iter->Seek(start_key); // see comment in RangeByScore() if (spec.reversed && (!iter->Valid() || !iter->key().starts_with(prefix_key))) { @@ -278,13 +277,13 @@ rocksdb::Status ZSet::RangeByRank(const Slice &user_key, const RangeRankSpec &sp std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } return rocksdb::Status::OK(); } -rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const RangeScoreSpec &spec, MemberScores *mscores, - uint64_t *removed_cnt) { +rocksdb::Status ZSet::RangeByScore(engine::Context &ctx, const Slice &user_key, const RangeScoreSpec &spec, + MemberScores *mscores, uint64_t *removed_cnt) { if (mscores) mscores->clear(); uint64_t cnt = 0; @@ -296,7 +295,7 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const RangeScoreSpec & std::optional lock_guard; if (spec.with_deletion) lock_guard.emplace(storage_->GetLockManager(), ns_key); ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; // let's get familiar with score first: @@ -344,16 +343,14 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const RangeScoreSpec & std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; int pos = 0; - auto iter = util::UniqueIterator(storage_, read_options, score_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, score_cf_handle_); auto batch = storage_->GetWriteBatchBase(); WriteBatchLogData log_data(kRedisZSet); batch->PutLogData(log_data.Encode()); @@ -395,13 +392,13 @@ rocksdb::Status ZSet::RangeByScore(const Slice &user_key, const RangeScoreSpec & std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } return rocksdb::Status::OK(); } -rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const RangeLexSpec &spec, MemberScores *mscores, - uint64_t *removed_cnt) { +rocksdb::Status ZSet::RangeByLex(engine::Context &ctx, const Slice &user_key, const RangeLexSpec &spec, + MemberScores *mscores, uint64_t *removed_cnt) { if (mscores) mscores->clear(); uint64_t cnt = 0; @@ -419,7 +416,7 @@ rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const RangeLexSpec &spec lock_guard.emplace(storage_->GetLockManager(), ns_key); } ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string start_member = spec.reversed ? spec.max : spec.min; @@ -428,16 +425,14 @@ rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const RangeLexSpec &spec std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); read_options.iterate_upper_bound = &upper_bound; rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; int pos = 0; - auto iter = util::UniqueIterator(storage_, read_options); + auto iter = util::UniqueIterator(ctx, read_options); auto batch = storage_->GetWriteBatchBase(); WriteBatchLogData log_data(kRedisZSet); batch->PutLogData(log_data.Encode()); @@ -485,36 +480,33 @@ rocksdb::Status ZSet::RangeByLex(const Slice &user_key, const RangeLexSpec &spec std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Score(const Slice &user_key, const Slice &member, double *score) { +rocksdb::Status ZSet::Score(engine::Context &ctx, const Slice &user_key, const Slice &member, double *score) { std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; - rocksdb::ReadOptions read_options; - LatestSnapShot ss(storage_); - read_options.snapshot = ss.GetSnapShot(); - std::string score_bytes; std::string member_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(read_options, member_key, &score_bytes); + s = storage_->Get(ctx, ctx.GetReadOptions(), member_key, &score_bytes); if (!s.ok()) return s; *score = DecodeDouble(score_bytes.data()); return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Remove(const Slice &user_key, const std::vector &members, uint64_t *removed_cnt) { +rocksdb::Status ZSet::Remove(engine::Context &ctx, const Slice &user_key, const std::vector &members, + uint64_t *removed_cnt) { *removed_cnt = 0; std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; auto batch = storage_->GetWriteBatchBase(); @@ -528,7 +520,7 @@ rocksdb::Status ZSet::Remove(const Slice &user_key, const std::vector &me } std::string member_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string score_bytes; - s = storage_->Get(rocksdb::ReadOptions(), member_key, &score_bytes); + s = storage_->Get(ctx, ctx.GetReadOptions(), member_key, &score_bytes); if (s.ok()) { score_bytes.append(member.data(), member.size()); std::string score_key = InternalKey(ns_key, score_bytes, metadata.version, storage_->IsSlotIdEncoded()).Encode(); @@ -544,25 +536,24 @@ rocksdb::Status ZSet::Remove(const Slice &user_key, const std::vector &me metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); } - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status ZSet::Rank(const Slice &user_key, const Slice &member, bool reversed, int *member_rank, - double *member_score) { +rocksdb::Status ZSet::Rank(engine::Context &ctx, const Slice &user_key, const Slice &member, bool reversed, + int *member_rank, double *member_score) { *member_rank = -1; *member_score = 0.0; std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); std::string score_bytes; std::string member_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); - s = storage_->Get(read_options, member_key, &score_bytes); + s = storage_->Get(ctx, read_options, member_key, &score_bytes); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; double target_score = DecodeDouble(score_bytes.data()); @@ -581,7 +572,7 @@ rocksdb::Status ZSet::Rank(const Slice &user_key, const Slice &member, bool reve rocksdb::Slice lower_bound(prefix_key); read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, score_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, score_cf_handle_); iter->Seek(start_key); // see comment in RangeByScore() if (reversed && (!iter->Valid() || !iter->key().starts_with(prefix_key))) { @@ -601,7 +592,7 @@ rocksdb::Status ZSet::Rank(const Slice &user_key, const Slice &member, bool reve return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Overwrite(const Slice &user_key, const MemberScores &mscores) { +rocksdb::Status ZSet::Overwrite(engine::Context &ctx, const Slice &user_key, const MemberScores &mscores) { std::string ns_key = AppendNamespacePrefix(user_key); LockGuard guard(storage_->GetLockManager(), ns_key); @@ -622,21 +613,21 @@ rocksdb::Status ZSet::Overwrite(const Slice &user_key, const MemberScores &mscor std::string bytes; metadata.Encode(&bytes); batch->Put(metadata_cf_handle_, ns_key, bytes); - return storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + return storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); } -rocksdb::Status ZSet::InterStore(const Slice &dst, const std::vector &keys_weights, +rocksdb::Status ZSet::InterStore(engine::Context &ctx, const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, uint64_t *saved_cnt) { *saved_cnt = 0; std::vector members; - auto s = Inter(keys_weights, aggregate_method, &members); + auto s = Inter(ctx, keys_weights, aggregate_method, &members); if (!s.ok()) return s; *saved_cnt = members.size(); - return Overwrite(dst, members); + return Overwrite(ctx, dst, members); } -rocksdb::Status ZSet::Inter(const std::vector &keys_weights, AggregateMethod aggregate_method, - std::vector *members) { +rocksdb::Status ZSet::Inter(engine::Context &ctx, const std::vector &keys_weights, + AggregateMethod aggregate_method, std::vector *members) { std::vector lock_keys; lock_keys.reserve(keys_weights.size()); for (const auto &key_weight : keys_weights) { @@ -650,7 +641,7 @@ rocksdb::Status ZSet::Inter(const std::vector &keys_weights, Aggregat std::vector target_mscores; uint64_t target_size = 0; RangeScoreSpec spec; - auto s = RangeByScore(keys_weights[0].key, spec, &target_mscores, &target_size); + auto s = RangeByScore(ctx, keys_weights[0].key, spec, &target_mscores, &target_size); if (!s.ok() || target_mscores.empty()) return s; for (const auto &ms : target_mscores) { @@ -661,7 +652,7 @@ rocksdb::Status ZSet::Inter(const std::vector &keys_weights, Aggregat } for (size_t i = 1; i < keys_weights.size(); i++) { - s = RangeByScore(keys_weights[i].key, spec, &target_mscores, &target_size); + s = RangeByScore(ctx, keys_weights[i].key, spec, &target_mscores, &target_size); if (!s.ok() || target_mscores.empty()) return s; for (const auto &ms : target_mscores) { @@ -700,7 +691,8 @@ rocksdb::Status ZSet::Inter(const std::vector &keys_weights, Aggregat return rocksdb::Status::OK(); } -rocksdb::Status ZSet::InterCard(const std::vector &user_keys, uint64_t limit, uint64_t *inter_cnt) { +rocksdb::Status ZSet::InterCard(engine::Context &ctx, const std::vector &user_keys, uint64_t limit, + uint64_t *inter_cnt) { std::vector lock_keys; lock_keys.reserve(user_keys.size()); for (const auto &user_key : user_keys) { @@ -714,7 +706,7 @@ rocksdb::Status ZSet::InterCard(const std::vector &user_keys, uint6 RangeScoreSpec spec; for (const auto &user_key : user_keys) { MemberScores mscores; - auto s = RangeByScore(user_key, spec, &mscores, nullptr); + auto s = RangeByScore(ctx, user_key, spec, &mscores, nullptr); if (!s.ok() || mscores.empty()) return s; mscores_list.emplace_back(std::move(mscores)); } @@ -746,18 +738,18 @@ rocksdb::Status ZSet::InterCard(const std::vector &user_keys, uint6 return rocksdb::Status::OK(); } -rocksdb::Status ZSet::UnionStore(const Slice &dst, const std::vector &keys_weights, +rocksdb::Status ZSet::UnionStore(engine::Context &ctx, const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, uint64_t *saved_cnt) { *saved_cnt = 0; std::vector members; - auto s = Union(keys_weights, aggregate_method, &members); + auto s = Union(ctx, keys_weights, aggregate_method, &members); if (!s.ok()) return s; *saved_cnt = members.size(); - return Overwrite(dst, members); + return Overwrite(ctx, dst, members); } -rocksdb::Status ZSet::Union(const std::vector &keys_weights, AggregateMethod aggregate_method, - std::vector *members) { +rocksdb::Status ZSet::Union(engine::Context &ctx, const std::vector &keys_weights, + AggregateMethod aggregate_method, std::vector *members) { std::vector lock_keys; lock_keys.reserve(keys_weights.size()); for (const auto &key_weight : keys_weights) { @@ -772,7 +764,7 @@ rocksdb::Status ZSet::Union(const std::vector &keys_weights, Aggregat RangeScoreSpec spec; for (const auto &key_weight : keys_weights) { // get all member - auto s = RangeByScore(key_weight.key, spec, &target_mscores, &target_size); + auto s = RangeByScore(ctx, key_weight.key, spec, &target_mscores, &target_size); if (!s.ok() && !s.IsNotFound()) return s; for (const auto &ms : target_mscores) { double score = ms.score * key_weight.weight; @@ -808,12 +800,12 @@ rocksdb::Status ZSet::Union(const std::vector &keys_weights, Aggregat return rocksdb::Status::OK(); } -rocksdb::Status ZSet::Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, +rocksdb::Status ZSet::Scan(engine::Context &ctx, const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &member_prefix, std::vector *members, std::vector *scores) { if (scores != nullptr) { std::vector values; - auto s = SubKeyScanner::Scan(kRedisZSet, user_key, cursor, limit, member_prefix, members, &values); + auto s = SubKeyScanner::Scan(ctx, kRedisZSet, user_key, cursor, limit, member_prefix, members, &values); if (!s.ok()) return s; for (const auto &value : values) { @@ -822,26 +814,24 @@ rocksdb::Status ZSet::Scan(const Slice &user_key, const std::string &cursor, uin } return s; } - return SubKeyScanner::Scan(kRedisZSet, user_key, cursor, limit, member_prefix, members); + return SubKeyScanner::Scan(ctx, kRedisZSet, user_key, cursor, limit, member_prefix, members); } -rocksdb::Status ZSet::MGet(const Slice &user_key, const std::vector &members, +rocksdb::Status ZSet::MGet(engine::Context &ctx, const Slice &user_key, const std::vector &members, std::map *mscores) { mscores->clear(); std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s; - rocksdb::ReadOptions read_options; - read_options.snapshot = ss.GetSnapShot(); std::string score_bytes; for (const auto &member : members) { std::string member_key = InternalKey(ns_key, member, metadata.version, storage_->IsSlotIdEncoded()).Encode(); score_bytes.clear(); - s = storage_->Get(read_options, member_key, &score_bytes); + s = storage_->Get(ctx, ctx.GetReadOptions(), member_key, &score_bytes); if (!s.ok() && !s.IsNotFound()) return s; if (s.IsNotFound()) { continue; @@ -852,27 +842,27 @@ rocksdb::Status ZSet::MGet(const Slice &user_key, const std::vector &memb return rocksdb::Status::OK(); } -rocksdb::Status ZSet::GetAllMemberScores(const Slice &user_key, std::vector *member_scores) { +rocksdb::Status ZSet::GetAllMemberScores(engine::Context &ctx, const Slice &user_key, + std::vector *member_scores) { member_scores->clear(); std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - LatestSnapShot ss(storage_); - rocksdb::Status s = GetMetadata(GetOptions{ss.GetSnapShot()}, ns_key, &metadata); + + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; std::string prefix_key = InternalKey(ns_key, "", metadata.version, storage_->IsSlotIdEncoded()).Encode(); std::string next_version_prefix_key = InternalKey(ns_key, "", metadata.version + 1, storage_->IsSlotIdEncoded()).Encode(); - rocksdb::ReadOptions read_options = storage_->DefaultScanOptions(); - read_options.snapshot = ss.GetSnapShot(); + rocksdb::ReadOptions read_options = ctx.DefaultScanOptions(); rocksdb::Slice upper_bound(next_version_prefix_key); rocksdb::Slice lower_bound(prefix_key); read_options.iterate_upper_bound = &upper_bound; read_options.iterate_lower_bound = &lower_bound; - auto iter = util::UniqueIterator(storage_, read_options, score_cf_handle_); + auto iter = util::UniqueIterator(ctx, read_options, score_cf_handle_); for (iter->Seek(prefix_key); iter->Valid() && iter->key().starts_with(prefix_key); iter->Next()) { InternalKey ikey(iter->key(), storage_->IsSlotIdEncoded()); @@ -885,7 +875,7 @@ rocksdb::Status ZSet::GetAllMemberScores(const Slice &user_key, std::vector *member_scores) { if (command_count == 0) { return rocksdb::Status::OK(); @@ -896,24 +886,24 @@ rocksdb::Status ZSet::RandMember(const Slice &user_key, int64_t command_count, std::string ns_key = AppendNamespacePrefix(user_key); ZSetMetadata metadata(false); - rocksdb::Status s = GetMetadata(GetOptions{}, ns_key, &metadata); + rocksdb::Status s = GetMetadata(ctx, ns_key, &metadata); if (!s.ok()) return s.IsNotFound() ? rocksdb::Status::OK() : s; if (metadata.size == 0) return rocksdb::Status::OK(); return ExtractRandMemberFromSet( unique, count, - [this, user_key](std::vector *scores) -> rocksdb::Status { - return this->GetAllMemberScores(user_key, scores); + [this, user_key, &ctx](std::vector *scores) -> rocksdb::Status { + return this->GetAllMemberScores(ctx, user_key, scores); }, member_scores); } -rocksdb::Status ZSet::Diff(const std::vector &keys, MemberScores *members) { +rocksdb::Status ZSet::Diff(engine::Context &ctx, const std::vector &keys, MemberScores *members) { members->clear(); MemberScores source_member_scores; RangeScoreSpec spec; uint64_t first_element_size = 0; - auto s = RangeByScore(keys[0], spec, &source_member_scores, &first_element_size); + auto s = RangeByScore(ctx, keys[0], spec, &source_member_scores, &first_element_size); if (!s.ok()) return s; if (first_element_size == 0) { @@ -924,7 +914,7 @@ rocksdb::Status ZSet::Diff(const std::vector &keys, MemberScores *members MemberScores target_member_scores; for (size_t i = 1; i < keys.size(); i++) { uint64_t size = 0; - s = RangeByScore(keys[i], spec, &target_member_scores, &size); + s = RangeByScore(ctx, keys[i], spec, &target_member_scores, &size); if (!s.ok()) return s; for (auto &member_score : target_member_scores) { exclude_members.emplace(std::move(member_score.member)); @@ -939,12 +929,13 @@ rocksdb::Status ZSet::Diff(const std::vector &keys, MemberScores *members return rocksdb::Status::OK(); } -rocksdb::Status ZSet::DiffStore(const Slice &dst, const std::vector &keys, uint64_t *stored_count) { +rocksdb::Status ZSet::DiffStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *stored_count) { MemberScores mscores; - auto s = Diff(keys, &mscores); + auto s = Diff(ctx, keys, &mscores); if (!s.ok()) return s; *stored_count = mscores.size(); - return Overwrite(dst, mscores); + return Overwrite(ctx, dst, mscores); } } // namespace redis diff --git a/src/types/redis_zset.h b/src/types/redis_zset.h index a5ea754af5c..3a866e86e61 100644 --- a/src/types/redis_zset.h +++ b/src/types/redis_zset.h @@ -95,41 +95,49 @@ class ZSet : public SubKeyScanner { using Members = std::vector; using MemberScores = std::vector; - rocksdb::Status Add(const Slice &user_key, ZAddFlags flags, MemberScores *mscores, uint64_t *added_cnt); - rocksdb::Status Card(const Slice &user_key, uint64_t *size); - rocksdb::Status IncrBy(const Slice &user_key, const Slice &member, double increment, double *score); - rocksdb::Status Rank(const Slice &user_key, const Slice &member, bool reversed, int *member_rank, - double *member_score); - rocksdb::Status Remove(const Slice &user_key, const std::vector &members, uint64_t *removed_cnt); - rocksdb::Status Pop(const Slice &user_key, int count, bool min, MemberScores *mscores); - rocksdb::Status Score(const Slice &user_key, const Slice &member, double *score); - rocksdb::Status Scan(const Slice &user_key, const std::string &cursor, uint64_t limit, + rocksdb::Status Add(engine::Context &ctx, const Slice &user_key, ZAddFlags flags, MemberScores *mscores, + uint64_t *added_cnt); + rocksdb::Status Card(engine::Context &ctx, const Slice &user_key, uint64_t *size); + rocksdb::Status IncrBy(engine::Context &ctx, const Slice &user_key, const Slice &member, double increment, + double *score); + rocksdb::Status Rank(engine::Context &ctx, const Slice &user_key, const Slice &member, bool reversed, + int *member_rank, double *member_score); + rocksdb::Status Remove(engine::Context &ctx, const Slice &user_key, const std::vector &members, + uint64_t *removed_cnt); + rocksdb::Status Pop(engine::Context &ctx, const Slice &user_key, int count, bool min, MemberScores *mscores); + rocksdb::Status Score(engine::Context &ctx, const Slice &user_key, const Slice &member, double *score); + rocksdb::Status Scan(engine::Context &ctx, const Slice &user_key, const std::string &cursor, uint64_t limit, const std::string &member_prefix, std::vector *members, std::vector *scores = nullptr); - rocksdb::Status Overwrite(const Slice &user_key, const MemberScores &mscores); - rocksdb::Status InterStore(const Slice &dst, const std::vector &keys_weights, + rocksdb::Status Overwrite(engine::Context &ctx, const Slice &user_key, const MemberScores &mscores); + rocksdb::Status InterStore(engine::Context &ctx, const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, uint64_t *saved_cnt); - rocksdb::Status Inter(const std::vector &keys_weights, AggregateMethod aggregate_method, - std::vector *members); - rocksdb::Status InterCard(const std::vector &user_keys, uint64_t limit, uint64_t *inter_cnt); - rocksdb::Status UnionStore(const Slice &dst, const std::vector &keys_weights, + rocksdb::Status Inter(engine::Context &ctx, const std::vector &keys_weights, + AggregateMethod aggregate_method, std::vector *members); + rocksdb::Status InterCard(engine::Context &ctx, const std::vector &user_keys, uint64_t limit, + uint64_t *inter_cnt); + rocksdb::Status UnionStore(engine::Context &ctx, const Slice &dst, const std::vector &keys_weights, AggregateMethod aggregate_method, uint64_t *saved_cnt); - rocksdb::Status Union(const std::vector &keys_weights, AggregateMethod aggregate_method, - std::vector *members); - rocksdb::Status Diff(const std::vector &keys, MemberScores *members); - rocksdb::Status DiffStore(const Slice &dst, const std::vector &keys, uint64_t *stored_count); - rocksdb::Status MGet(const Slice &user_key, const std::vector &members, std::map *scores); - rocksdb::Status GetMetadata(Database::GetOptions get_options, const Slice &ns_key, ZSetMetadata *metadata); - - rocksdb::Status Count(const Slice &user_key, const RangeScoreSpec &spec, uint64_t *size); - rocksdb::Status RangeByRank(const Slice &user_key, const RangeRankSpec &spec, MemberScores *mscores, - uint64_t *removed_cnt); - rocksdb::Status RangeByScore(const Slice &user_key, const RangeScoreSpec &spec, MemberScores *mscores, - uint64_t *removed_cnt); - rocksdb::Status RangeByLex(const Slice &user_key, const RangeLexSpec &spec, MemberScores *mscores, - uint64_t *removed_cnt); - rocksdb::Status GetAllMemberScores(const Slice &user_key, std::vector *member_scores); - rocksdb::Status RandMember(const Slice &user_key, int64_t command_count, std::vector *member_scores); + rocksdb::Status Union(engine::Context &ctx, const std::vector &keys_weights, + AggregateMethod aggregate_method, std::vector *members); + rocksdb::Status Diff(engine::Context &ctx, const std::vector &keys, MemberScores *members); + rocksdb::Status DiffStore(engine::Context &ctx, const Slice &dst, const std::vector &keys, + uint64_t *stored_count); + rocksdb::Status MGet(engine::Context &ctx, const Slice &user_key, const std::vector &members, + std::map *scores); + rocksdb::Status GetMetadata(engine::Context &ctx, const Slice &ns_key, ZSetMetadata *metadata); + + rocksdb::Status Count(engine::Context &ctx, const Slice &user_key, const RangeScoreSpec &spec, uint64_t *size); + rocksdb::Status RangeByRank(engine::Context &ctx, const Slice &user_key, const RangeRankSpec &spec, + MemberScores *mscores, uint64_t *removed_cnt); + rocksdb::Status RangeByScore(engine::Context &ctx, const Slice &user_key, const RangeScoreSpec &spec, + MemberScores *mscores, uint64_t *removed_cnt); + rocksdb::Status RangeByLex(engine::Context &ctx, const Slice &user_key, const RangeLexSpec &spec, + MemberScores *mscores, uint64_t *removed_cnt); + rocksdb::Status GetAllMemberScores(engine::Context &ctx, const Slice &user_key, + std::vector *member_scores); + rocksdb::Status RandMember(engine::Context &ctx, const Slice &user_key, int64_t command_count, + std::vector *member_scores); private: rocksdb::ColumnFamilyHandle *score_cf_handle_; diff --git a/tests/cppunit/cluster_test.cc b/tests/cppunit/cluster_test.cc index e70c3136f62..bc0d80f4285 100644 --- a/tests/cppunit/cluster_test.cc +++ b/tests/cppunit/cluster_test.cc @@ -40,7 +40,16 @@ class ClusterTest : public TestBase { TEST_F(ClusterTest, CluseterSetNodes) { Status s; - Cluster cluster(nullptr, {"127.0.0.1"}, 3002); + + auto config = storage_->GetConfig(); + // don't start workers + config->workers = 0; + Server server(storage_.get(), config); + // we don't need the server resource, so just stop it once it's started + server.Stop(); + server.Join(); + + Cluster cluster(&server, {"127.0.0.1"}, 3002); const std::string invalid_fields = "07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1 30004 " @@ -160,7 +169,16 @@ TEST_F(ClusterTest, CluseterGetSlotInfo) { "slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1\n" "67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1 30002 " "master - 5461-10922"; - Cluster cluster(nullptr, {"127.0.0.1"}, 30002); + + auto config = storage_->GetConfig(); + // don't start workers + config->workers = 0; + Server server(storage_.get(), config); + // we don't need the server resource, so just stop it once it's started + server.Stop(); + server.Join(); + + Cluster cluster(&server, {"127.0.0.1"}, 30002); Status s = cluster.SetClusterNodes(nodes, 1, false); ASSERT_TRUE(s.IsOK()); @@ -184,7 +202,16 @@ TEST_F(ClusterTest, TestDumpAndLoadClusterNodesInfo) { "67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1 30002 " "master - 5461-10922\n" "17ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1 30003 master - 10923-16383"; - Cluster cluster(nullptr, {"127.0.0.1"}, 30002); + + auto config = storage_->GetConfig(); + // don't start workers + config->workers = 0; + Server server(storage_.get(), config); + // we don't need the server resource, so just stop it once it's started + server.Stop(); + server.Join(); + + Cluster cluster(&server, {"127.0.0.1"}, 30002); Status s = cluster.SetClusterNodes(nodes, version, false); ASSERT_TRUE(s.IsOK()); @@ -217,7 +244,16 @@ TEST_F(ClusterTest, TestDumpAndLoadClusterNodesInfo) { TEST_F(ClusterTest, ClusterParseSlotRanges) { Status s; - Cluster cluster(nullptr, {"127.0.0.1"}, 3002); + + auto config = storage_->GetConfig(); + // don't start workers + config->workers = 0; + Server server(storage_.get(), config); + // we don't need the server resource, so just stop it once it's started + server.Stop(); + server.Join(); + + Cluster cluster(&server, {"127.0.0.1"}, 3002); const std::string node_id = "67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1"; int64_t version = 1; diff --git a/tests/cppunit/compact_test.cc b/tests/cppunit/compact_test.cc index 0717fbabb61..9377133e3bc 100644 --- a/tests/cppunit/compact_test.cc +++ b/tests/cppunit/compact_test.cc @@ -41,12 +41,15 @@ TEST(Compact, Filter) { auto hash = std::make_unique(storage.get(), ns); std::string expired_hash_key = "expire_hash_key"; std::string live_hash_key = "live_hash_key"; - hash->Set(expired_hash_key, "f1", "v1", &ret); - hash->Set(expired_hash_key, "f2", "v2", &ret); - auto st = hash->Expire(expired_hash_key, 1); // expired + + engine::Context ctx(storage.get()); + + hash->Set(ctx, expired_hash_key, "f1", "v1", &ret); + hash->Set(ctx, expired_hash_key, "f2", "v2", &ret); + auto st = hash->Expire(ctx, expired_hash_key, 1); // expired usleep(10000); - hash->Set(live_hash_key, "f1", "v1", &ret); - hash->Set(live_hash_key, "f2", "v2", &ret); + hash->Set(ctx, live_hash_key, "f1", "v1", &ret); + hash->Set(ctx, live_hash_key, "f2", "v2", &ret); auto status = storage->Compact(nullptr, nullptr, nullptr); assert(status.ok()); @@ -78,8 +81,8 @@ TEST(Compact, Filter) { auto zset = std::make_unique(storage.get(), ns); std::string expired_zset_key = "expire_zset_key"; std::vector member_scores = {MemberScore{"z1", 1.1}, MemberScore{"z2", 0.4}}; - zset->Add(expired_zset_key, ZAddFlags::Default(), &member_scores, &ret); - st = zset->Expire(expired_zset_key, 1); // expired + zset->Add(ctx, expired_zset_key, ZAddFlags::Default(), &member_scores, &ret); + st = zset->Expire(ctx, expired_zset_key, 1); // expired usleep(10000); // Same as the above compact, need to compact twice here @@ -100,16 +103,16 @@ TEST(Compact, Filter) { } Slice mk_with_ttl = "mk_with_ttl"; - hash->Set(mk_with_ttl, "f1", "v1", &ret); - hash->Set(mk_with_ttl, "f2", "v2", &ret); + hash->Set(ctx, mk_with_ttl, "f1", "v1", &ret); + hash->Set(ctx, mk_with_ttl, "f2", "v2", &ret); int retry = 2; while (retry-- > 0) { status = storage->Compact(nullptr, nullptr, nullptr); ASSERT_TRUE(status.ok()); std::vector fieldvalues; - auto get_res = hash->GetAll(mk_with_ttl, &fieldvalues); - auto s_expire = hash->Expire(mk_with_ttl, 1); // expired immediately.. + auto get_res = hash->GetAll(ctx, mk_with_ttl, &fieldvalues); + auto s_expire = hash->Expire(ctx, mk_with_ttl, 1); // expired immediately.. if (retry == 1) { ASSERT_TRUE(get_res.ok()); // not expired first time diff --git a/tests/cppunit/disk_test.cc b/tests/cppunit/disk_test.cc index a4cfc0df7a4..60085d5938d 100644 --- a/tests/cppunit/disk_test.cc +++ b/tests/cppunit/disk_test.cc @@ -40,7 +40,6 @@ class RedisDiskTest : public TestBase { protected: explicit RedisDiskTest() = default; ~RedisDiskTest() override = default; - double estimation_factor_ = 0.1; }; @@ -49,12 +48,12 @@ TEST_F(RedisDiskTest, StringDisk) { std::unique_ptr string = std::make_unique(storage_.get(), "disk_ns_string"); std::unique_ptr disk = std::make_unique(storage_.get(), "disk_ns_string"); std::vector value_size{1024 * 1024}; - EXPECT_TRUE(string->Set(key_, std::string(value_size[0], 'a')).ok()); + EXPECT_TRUE(string->Set(*ctx_, key_, std::string(value_size[0], 'a')).ok()); uint64_t result = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisString, &result).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisString, &result).ok()); EXPECT_GE(result, value_size[0] * estimation_factor_); EXPECT_LE(result, value_size[0] / estimation_factor_); - auto s = string->Del(key_); + auto s = string->Del(*ctx_, key_); } TEST_F(RedisDiskTest, HashDisk) { @@ -71,14 +70,14 @@ TEST_F(RedisDiskTest, HashDisk) { values[i] = std::string(value_size[i], static_cast('a' + i)); values_[i] = values[i]; approximate_size += key_.size() + 8 + fields_[i].size() + values_[i].size(); - rocksdb::Status s = hash->Set(key_, fields_[i], values_[i], &ret); + rocksdb::Status s = hash->Set(*ctx_, key_, fields_[i], values_[i], &ret); EXPECT_TRUE(s.ok() && ret == 1); } uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisHash, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisHash, &key_size).ok()); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - auto s = hash->Del(key_); + auto s = hash->Del(*ctx_, key_); } TEST_F(RedisDiskTest, SetDisk) { @@ -95,15 +94,15 @@ TEST_F(RedisDiskTest, SetDisk) { values_[i] = values[i]; approximate_size += key_.size() + values_[i].size() + 8; } - rocksdb::Status s = set->Add(key_, values_, &ret); + rocksdb::Status s = set->Add(*ctx_, key_, values_, &ret); EXPECT_TRUE(s.ok() && ret == 5); uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisSet, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisSet, &key_size).ok()); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - s = set->Del(key_); + s = set->Del(*ctx_, key_); } TEST_F(RedisDiskTest, ListDisk) { @@ -120,13 +119,13 @@ TEST_F(RedisDiskTest, ListDisk) { approximate_size += key_.size() + values_[i].size() + 8 + 8; } uint64_t ret = 0; - rocksdb::Status s = list->Push(key_, values_, false, &ret); + rocksdb::Status s = list->Push(*ctx_, key_, values_, false, &ret); EXPECT_TRUE(s.ok() && ret == 5); uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisList, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisList, &key_size).ok()); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - s = list->Del(key_); + s = list->Del(*ctx_, key_); } TEST_F(RedisDiskTest, ZsetDisk) { @@ -142,13 +141,13 @@ TEST_F(RedisDiskTest, ZsetDisk) { mscores[i].score = 1.0; approximate_size += (key_.size() + 8 + mscores[i].member.size() + 8) * 2; } - rocksdb::Status s = zset->Add(key_, ZAddFlags::Default(), &mscores, &ret); + rocksdb::Status s = zset->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_TRUE(s.ok() && ret == 5); uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisZSet, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisZSet, &key_size).ok()); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - s = zset->Del(key_); + s = zset->Del(*ctx_, key_); } TEST_F(RedisDiskTest, BitmapDisk) { @@ -158,14 +157,16 @@ TEST_F(RedisDiskTest, BitmapDisk) { bool bit = false; uint64_t approximate_size = 0; for (int i = 0; i < 1024 * 8 * 100000; i += 1024 * 8) { - EXPECT_TRUE(bitmap->SetBit(key_, i, true, &bit).ok()); + EXPECT_TRUE(bitmap->SetBit(*ctx_, key_, i, true, &bit).ok()); + ctx_->RefreshLatestSnapshot(); approximate_size += key_.size() + 8 + std::to_string(i / 1024 / 8).size(); } uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisBitmap, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisBitmap, &key_size).ok()); + ctx_->RefreshLatestSnapshot(); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - auto s = bitmap->Del(key_); + auto s = bitmap->Del(*ctx_, key_); } TEST_F(RedisDiskTest, BitmapDisk2) { @@ -175,34 +176,36 @@ TEST_F(RedisDiskTest, BitmapDisk2) { std::unique_ptr bitmap = std::make_unique(storage_.get(), "disk_ns_bitmap2"); std::unique_ptr disk = std::make_unique(storage_.get(), "disk_ns_bitmap2"); key_ = "bitmapdisk_key2"; - auto s = bitmap->Del(key_); + auto s = bitmap->Del(*ctx_, key_); bool bit = false; for (size_t i = 0; i < num_bits; i += kGroupSize) { // Set all first bit of group to `!set_op` - EXPECT_TRUE(bitmap->SetBit(key_, i, !set_op, &bit).ok()); + EXPECT_TRUE(bitmap->SetBit(*ctx_, key_, i, !set_op, &bit).ok()); // Set all last bit of group to `set_op`. - EXPECT_TRUE(bitmap->SetBit(key_, i + kGroupSize - 1, set_op, &bit).ok()); + EXPECT_TRUE(bitmap->SetBit(*ctx_, key_, i + kGroupSize - 1, set_op, &bit).ok()); + ctx_->RefreshLatestSnapshot(); } auto bit_not_dest_key = "bit_op_not_dest_key"; int64_t len = 0; - EXPECT_TRUE(bitmap->BitOp(BitOpFlags::kBitOpNot, "NOT", bit_not_dest_key, {key_}, &len).ok()); + EXPECT_TRUE(bitmap->BitOp(*ctx_, BitOpFlags::kBitOpNot, "NOT", bit_not_dest_key, {key_}, &len).ok()); for (size_t i = 0; i < num_bits; i += kGroupSize) { bool result = false; // Check all first bit of group is `set_op` - EXPECT_TRUE(bitmap->GetBit(bit_not_dest_key, i, &result).ok()); + EXPECT_TRUE(bitmap->GetBit(*ctx_, bit_not_dest_key, i, &result).ok()); EXPECT_EQ(set_op, result); // Check all last bit of group is `!set_op` - EXPECT_TRUE(bitmap->GetBit(bit_not_dest_key, i + kGroupSize - 1, &result).ok()); + EXPECT_TRUE(bitmap->GetBit(*ctx_, bit_not_dest_key, i + kGroupSize - 1, &result).ok()); EXPECT_EQ(!set_op, result); // Check bit in group between (first, last) is "1". for (size_t j = i + 1; j < i + kGroupSize - 1; ++j) { - EXPECT_TRUE(bitmap->GetBit(bit_not_dest_key, j, &result).ok()); + EXPECT_TRUE(bitmap->GetBit(*ctx_, bit_not_dest_key, j, &result).ok()); EXPECT_TRUE(result) << j << " is not true"; } + ctx_->RefreshLatestSnapshot(); } } } @@ -215,14 +218,16 @@ TEST_F(RedisDiskTest, SortedintDisk) { uint64_t ret = 0; uint64_t approximate_size = 0; for (int i = 0; i < 100000; i++) { - EXPECT_TRUE(sortedint->Add(key_, std::vector{uint64_t(i)}, &ret).ok() && ret == 1); + EXPECT_TRUE(sortedint->Add(*ctx_, key_, std::vector{uint64_t(i)}, &ret).ok() && ret == 1); approximate_size += key_.size() + 8 + 8; + ctx_->RefreshLatestSnapshot(); } uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisSortedint, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisSortedint, &key_size).ok()); + ctx_->RefreshLatestSnapshot(); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - auto s = sortedint->Del(key_); + auto s = sortedint->Del(*ctx_, key_); } TEST_F(RedisDiskTest, StreamDisk) { @@ -235,13 +240,15 @@ TEST_F(RedisDiskTest, StreamDisk) { uint64_t approximate_size = 0; for (int i = 0; i < 100000; i++) { std::vector values = {"key" + std::to_string(i), "val" + std::to_string(i)}; - auto s = stream->Add(key_, options, values, &id); + auto s = stream->Add(*ctx_, key_, options, values, &id); EXPECT_TRUE(s.ok()); + ctx_->RefreshLatestSnapshot(); approximate_size += key_.size() + 8 + 8 + values[0].size() + values[1].size(); } uint64_t key_size = 0; - EXPECT_TRUE(disk->GetKeySize(key_, kRedisStream, &key_size).ok()); + EXPECT_TRUE(disk->GetKeySize(*ctx_, key_, kRedisStream, &key_size).ok()); + ctx_->RefreshLatestSnapshot(); EXPECT_GE(key_size, approximate_size * estimation_factor_); EXPECT_LE(key_size, approximate_size / estimation_factor_); - auto s = stream->Del(key_); + auto s = stream->Del(*ctx_, key_); } diff --git a/tests/cppunit/hnsw_index_test.cc b/tests/cppunit/hnsw_index_test.cc index 3162c88f012..ebeb18c9286 100644 --- a/tests/cppunit/hnsw_index_test.cc +++ b/tests/cppunit/hnsw_index_test.cc @@ -40,22 +40,22 @@ auto GetVectorKeys(const std::vector& keys_by_dist) -> s return result; } -void InsertEntryIntoHnswIndex(std::string_view key, const kqir::NumericArray& vector, uint16_t target_level, - redis::HnswIndex* hnsw_index, engine::Storage* storage) { +void InsertEntryIntoHnswIndex(engine::Context& ctx, std::string_view key, const kqir::NumericArray& vector, + uint16_t target_level, redis::HnswIndex* hnsw_index, engine::Storage* storage) { auto batch = storage->GetWriteBatchBase(); - auto s = hnsw_index->InsertVectorEntryInternal(key, vector, batch, target_level); + auto s = hnsw_index->InsertVectorEntryInternal(ctx, key, vector, batch, target_level); ASSERT_TRUE(s.IsOK()); - auto status = storage->Write(storage->DefaultWriteOptions(), batch->GetWriteBatch()); + auto status = storage->Write(ctx, storage->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(status.ok()); } -void VerifyNodeMetadataAndNeighbours(redis::HnswNode* node, redis::HnswIndex* hnsw_index, +void VerifyNodeMetadataAndNeighbours(engine::Context& ctx, redis::HnswNode* node, redis::HnswIndex* hnsw_index, const std::unordered_set& expected_set) { - auto s = node->DecodeMetadata(hnsw_index->search_key, hnsw_index->storage); + auto s = node->DecodeMetadata(ctx, hnsw_index->search_key); ASSERT_TRUE(s.IsOK()); auto node_meta = s.GetValue(); EXPECT_EQ(node_meta.num_neighbours, static_cast(expected_set.size())); - node->DecodeNeighbours(hnsw_index->search_key, hnsw_index->storage); + node->DecodeNeighbours(ctx, hnsw_index->search_key); std::unordered_set actual_set = {(node->neighbours).begin(), (node->neighbours).end()}; EXPECT_EQ(actual_set, expected_set); } @@ -165,7 +165,8 @@ TEST_F(HnswIndexTest, RandomizeLayer) { } TEST_F(HnswIndexTest, DefaultEntryPointNotFound) { - auto initial_result = hnsw_index->DefaultEntryPoint(0); + engine::Context ctx(storage_.get()); + auto initial_result = hnsw_index->DefaultEntryPoint(ctx, 0); ASSERT_EQ(initial_result.GetCode(), Status::NotFound); } @@ -187,13 +188,13 @@ TEST_F(HnswIndexTest, DecodeNodesToVectorItems) { node1.PutMetadata(&metadata1, hnsw_index->search_key, hnsw_index->storage, batch.Get()); node2.PutMetadata(&metadata2, hnsw_index->search_key, hnsw_index->storage, batch.Get()); node3.PutMetadata(&metadata3, hnsw_index->search_key, hnsw_index->storage, batch.Get()); - auto s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + engine::Context ctx(storage_.get()); + auto s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(s.ok()); std::vector keys = {node_key1, node_key2, node_key3}; - auto s1 = hnsw_index->DecodeNodesToVectorItems(keys, layer, hnsw_index->search_key, hnsw_index->storage, - hnsw_index->metadata); + auto s1 = hnsw_index->DecodeNodesToVectorItems(ctx, keys, layer, hnsw_index->search_key, hnsw_index->metadata); ASSERT_TRUE(s1.IsOK()); auto vector_items = s1.GetValue(); ASSERT_EQ(vector_items.size(), 3); @@ -294,28 +295,29 @@ TEST_F(HnswIndexTest, SearchLayer) { node3.PutMetadata(&metadata3, hnsw_index->search_key, hnsw_index->storage, batch.Get()); node4.PutMetadata(&metadata4, hnsw_index->search_key, hnsw_index->storage, batch.Get()); node5.PutMetadata(&metadata5, hnsw_index->search_key, hnsw_index->storage, batch.Get()); - auto s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + engine::Context ctx(storage_.get()); + auto s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(s.ok()); // Add Neighbours batch = storage_->GetWriteBatchBase(); - auto s1 = node1.AddNeighbour("node2", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s1 = node1.AddNeighbour(ctx, "node2", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s1.IsOK()); - auto s2 = node1.AddNeighbour("node4", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s2 = node1.AddNeighbour(ctx, "node4", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s2.IsOK()); - auto s3 = node2.AddNeighbour("node1", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s3 = node2.AddNeighbour(ctx, "node1", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s3.IsOK()); - auto s4 = node2.AddNeighbour("node3", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s4 = node2.AddNeighbour(ctx, "node3", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s1.IsOK()); - auto s5 = node3.AddNeighbour("node2", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s5 = node3.AddNeighbour(ctx, "node2", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s5.IsOK()); - auto s6 = node3.AddNeighbour("node5", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s6 = node3.AddNeighbour(ctx, "node5", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s6.IsOK()); - auto s7 = node4.AddNeighbour("node1", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s7 = node4.AddNeighbour(ctx, "node1", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s7.IsOK()); - auto s8 = node5.AddNeighbour("node3", hnsw_index->search_key, hnsw_index->storage, batch.Get()); + auto s8 = node5.AddNeighbour(ctx, "node3", hnsw_index->search_key, batch.Get()); ASSERT_TRUE(s8.IsOK()); - s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(s.ok()); redis::VectorItem target_vector; @@ -326,7 +328,7 @@ TEST_F(HnswIndexTest, SearchLayer) { std::vector entry_points = {"node3", "node2"}; uint32_t ef_runtime = 3; - auto s9 = hnsw_index->SearchLayer(layer, target_vector, ef_runtime, entry_points); + auto s9 = hnsw_index->SearchLayer(ctx, layer, target_vector, ef_runtime, entry_points); ASSERT_TRUE(s9.IsOK()); auto candidates = s9.GetValue(); @@ -337,7 +339,7 @@ TEST_F(HnswIndexTest, SearchLayer) { // Test with a single entry point entry_points = {"node5"}; - auto s10 = hnsw_index->SearchLayer(layer, target_vector, ef_runtime, entry_points); + auto s10 = hnsw_index->SearchLayer(ctx, layer, target_vector, ef_runtime, entry_points); ASSERT_TRUE(s10.IsOK()); candidates = s10.GetValue(); @@ -348,7 +350,7 @@ TEST_F(HnswIndexTest, SearchLayer) { // Test with different ef_runtime ef_runtime = 10; - auto s11 = hnsw_index->SearchLayer(layer, target_vector, ef_runtime, entry_points); + auto s11 = hnsw_index->SearchLayer(ctx, layer, target_vector, ef_runtime, entry_points); ASSERT_TRUE(s11.IsOK()); candidates = s11.GetValue(); @@ -373,13 +375,14 @@ TEST_F(HnswIndexTest, InsertAndDeleteVectorEntry) { std::string key4 = "n4"; std::string key5 = "n5"; + engine::Context ctx(storage_.get()); // Insert uint16_t target_level = 1; - InsertEntryIntoHnswIndex(key1, vec1, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key1, vec1, target_level, hnsw_index.get(), storage_.get()); rocksdb::PinnableSlice value; auto index_meta_key = hnsw_index->search_key.ConstructFieldMeta(); - auto s = storage_->Get(rocksdb::ReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), + auto s = storage_->Get(ctx, ctx.GetReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, &value); ASSERT_TRUE(s.ok()); redis::HnswVectorFieldMetadata decoded_metadata; @@ -387,118 +390,119 @@ TEST_F(HnswIndexTest, InsertAndDeleteVectorEntry) { ASSERT_TRUE(decoded_metadata.num_levels == 2); redis::HnswNode node1_layer0(key1, 0); - VerifyNodeMetadataAndNeighbours(&node1_layer0, hnsw_index.get(), {}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer0, hnsw_index.get(), {}); redis::HnswNode node1_layer1(key1, 1); - VerifyNodeMetadataAndNeighbours(&node1_layer1, hnsw_index.get(), {}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer1, hnsw_index.get(), {}); // Insert target_level = 3; - InsertEntryIntoHnswIndex(key2, vec2, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key2, vec2, target_level, hnsw_index.get(), storage_.get()); index_meta_key = hnsw_index->search_key.ConstructFieldMeta(); - s = storage_->Get(rocksdb::ReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, + s = storage_->Get(ctx, ctx.GetReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, &value); ASSERT_TRUE(s.ok()); decoded_metadata.Decode(&value); ASSERT_TRUE(decoded_metadata.num_levels == 4); - VerifyNodeMetadataAndNeighbours(&node1_layer0, hnsw_index.get(), {"n2"}); - VerifyNodeMetadataAndNeighbours(&node1_layer1, hnsw_index.get(), {"n2"}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer0, hnsw_index.get(), {"n2"}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer1, hnsw_index.get(), {"n2"}); redis::HnswNode node2_layer0(key2, 0); - VerifyNodeMetadataAndNeighbours(&node2_layer0, hnsw_index.get(), {"n1"}); + VerifyNodeMetadataAndNeighbours(ctx, &node2_layer0, hnsw_index.get(), {"n1"}); redis::HnswNode node2_layer1(key2, 1); - VerifyNodeMetadataAndNeighbours(&node2_layer1, hnsw_index.get(), {"n1"}); + VerifyNodeMetadataAndNeighbours(ctx, &node2_layer1, hnsw_index.get(), {"n1"}); redis::HnswNode node2_layer2(key2, 2); - VerifyNodeMetadataAndNeighbours(&node2_layer2, hnsw_index.get(), {}); + VerifyNodeMetadataAndNeighbours(ctx, &node2_layer2, hnsw_index.get(), {}); redis::HnswNode node2_layer3(key2, 3); - VerifyNodeMetadataAndNeighbours(&node2_layer3, hnsw_index.get(), {}); + VerifyNodeMetadataAndNeighbours(ctx, &node2_layer3, hnsw_index.get(), {}); // Insert target_level = 2; - InsertEntryIntoHnswIndex(key3, vec3, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key3, vec3, target_level, hnsw_index.get(), storage_.get()); index_meta_key = hnsw_index->search_key.ConstructFieldMeta(); - s = storage_->Get(rocksdb::ReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, + s = storage_->Get(ctx, ctx.GetReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, &value); ASSERT_TRUE(s.ok()); decoded_metadata.Decode(&value); ASSERT_TRUE(decoded_metadata.num_levels == 4); redis::HnswNode node3_layer2(key3, target_level); - VerifyNodeMetadataAndNeighbours(&node3_layer2, hnsw_index.get(), {"n2"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer2, hnsw_index.get(), {"n2"}); redis::HnswNode node3_layer1(key3, 1); - VerifyNodeMetadataAndNeighbours(&node3_layer1, hnsw_index.get(), {"n1", "n2"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer1, hnsw_index.get(), {"n1", "n2"}); // Insert target_level = 1; - InsertEntryIntoHnswIndex(key4, vec4, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key4, vec4, target_level, hnsw_index.get(), storage_.get()); redis::HnswNode node4_layer0(key4, 0); - auto s1 = node4_layer0.DecodeMetadata(hnsw_index->search_key, hnsw_index->storage); + auto s1 = node4_layer0.DecodeMetadata(ctx, hnsw_index->search_key); ASSERT_TRUE(s1.IsOK()); redis::HnswNodeFieldMetadata node4_layer0_meta = s1.GetValue(); EXPECT_EQ(node4_layer0_meta.num_neighbours, 3); - VerifyNodeMetadataAndNeighbours(&node1_layer1, hnsw_index.get(), {"n2", "n3", "n4"}); - VerifyNodeMetadataAndNeighbours(&node2_layer1, hnsw_index.get(), {"n1", "n3", "n4"}); - VerifyNodeMetadataAndNeighbours(&node3_layer1, hnsw_index.get(), {"n1", "n2", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer1, hnsw_index.get(), {"n2", "n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node2_layer1, hnsw_index.get(), {"n1", "n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer1, hnsw_index.get(), {"n1", "n2", "n4"}); // Insert n5 into layer 1 - InsertEntryIntoHnswIndex(key5, vec5, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key5, vec5, target_level, hnsw_index.get(), storage_.get()); - VerifyNodeMetadataAndNeighbours(&node2_layer1, hnsw_index.get(), {"n1", "n4", "n5"}); - VerifyNodeMetadataAndNeighbours(&node3_layer1, hnsw_index.get(), {"n1", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node2_layer1, hnsw_index.get(), {"n1", "n4", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer1, hnsw_index.get(), {"n1", "n5"}); redis::HnswNode node4_layer1(key4, 1); - VerifyNodeMetadataAndNeighbours(&node4_layer1, hnsw_index.get(), {"n1", "n2", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node4_layer1, hnsw_index.get(), {"n1", "n2", "n5"}); redis::HnswNode node5_layer1(key5, 1); - VerifyNodeMetadataAndNeighbours(&node5_layer1, hnsw_index.get(), {"n2", "n3", "n4"}); - VerifyNodeMetadataAndNeighbours(&node1_layer0, hnsw_index.get(), {"n2", "n3", "n4", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node5_layer1, hnsw_index.get(), {"n2", "n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer0, hnsw_index.get(), {"n2", "n3", "n4", "n5"}); redis::HnswNode node5_layer0(key5, 0); - VerifyNodeMetadataAndNeighbours(&node5_layer0, hnsw_index.get(), {"n1", "n2", "n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node5_layer0, hnsw_index.get(), {"n1", "n2", "n3", "n4"}); // Delete n2 auto batch = storage_->GetWriteBatchBase(); - auto s2 = hnsw_index->DeleteVectorEntry(key2, batch); + auto s2 = hnsw_index->DeleteVectorEntry(ctx, key2, batch); ASSERT_TRUE(s2.IsOK()); - s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(s.ok()); index_meta_key = hnsw_index->search_key.ConstructFieldMeta(); - s = storage_->Get(rocksdb::ReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, + s = storage_->Get(ctx, ctx.GetReadOptions(), hnsw_index->storage->GetCFHandle(ColumnFamilyID::Search), index_meta_key, &value); ASSERT_TRUE(s.ok()); decoded_metadata.Decode(&value); ASSERT_TRUE(decoded_metadata.num_levels == 3); - auto s3 = node2_layer3.DecodeMetadata(hnsw_index->search_key, hnsw_index->storage); + auto s3 = node2_layer3.DecodeMetadata(ctx, hnsw_index->search_key); EXPECT_TRUE(!s3.IsOK()); - auto s4 = node2_layer2.DecodeMetadata(hnsw_index->search_key, hnsw_index->storage); + auto s4 = node2_layer2.DecodeMetadata(ctx, hnsw_index->search_key); EXPECT_TRUE(!s4.IsOK()); - auto s5 = node2_layer1.DecodeMetadata(hnsw_index->search_key, hnsw_index->storage); + auto s5 = node2_layer1.DecodeMetadata(ctx, hnsw_index->search_key); EXPECT_TRUE(!s5.IsOK()); - auto s6 = node2_layer0.DecodeMetadata(hnsw_index->search_key, hnsw_index->storage); + auto s6 = node2_layer0.DecodeMetadata(ctx, hnsw_index->search_key); EXPECT_TRUE(!s6.IsOK()); - VerifyNodeMetadataAndNeighbours(&node3_layer2, hnsw_index.get(), {}); - VerifyNodeMetadataAndNeighbours(&node1_layer1, hnsw_index.get(), {"n3", "n4"}); - VerifyNodeMetadataAndNeighbours(&node3_layer1, hnsw_index.get(), {"n1", "n5"}); - VerifyNodeMetadataAndNeighbours(&node4_layer1, hnsw_index.get(), {"n1", "n5"}); - VerifyNodeMetadataAndNeighbours(&node5_layer1, hnsw_index.get(), {"n3", "n4"}); - VerifyNodeMetadataAndNeighbours(&node1_layer0, hnsw_index.get(), {"n3", "n4", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer2, hnsw_index.get(), {}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer1, hnsw_index.get(), {"n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer1, hnsw_index.get(), {"n1", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node4_layer1, hnsw_index.get(), {"n1", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node5_layer1, hnsw_index.get(), {"n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node1_layer0, hnsw_index.get(), {"n3", "n4", "n5"}); redis::HnswNode node3_layer0(key3, 0); - VerifyNodeMetadataAndNeighbours(&node3_layer0, hnsw_index.get(), {"n1", "n4", "n5"}); - VerifyNodeMetadataAndNeighbours(&node4_layer0, hnsw_index.get(), {"n1", "n3", "n5"}); - VerifyNodeMetadataAndNeighbours(&node5_layer0, hnsw_index.get(), {"n1", "n3", "n4"}); + VerifyNodeMetadataAndNeighbours(ctx, &node3_layer0, hnsw_index.get(), {"n1", "n4", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node4_layer0, hnsw_index.get(), {"n1", "n3", "n5"}); + VerifyNodeMetadataAndNeighbours(ctx, &node5_layer0, hnsw_index.get(), {"n1", "n3", "n4"}); } TEST_F(HnswIndexTest, SearchKnnAndRange) { hnsw_index->metadata->m = 3; std::vector query_vector = {31.0, 32.0, 23.0}; uint32_t k = 3; - auto s1 = hnsw_index->KnnSearch(query_vector, k); + engine::Context ctx(storage_.get()); + auto s1 = hnsw_index->KnnSearch(ctx, query_vector, k); ASSERT_FALSE(s1.IsOK()); EXPECT_EQ(s1.GetCode(), Status::NotFound); @@ -529,34 +533,34 @@ TEST_F(HnswIndexTest, SearchKnnAndRange) { std::string key12 = "key12"; uint16_t target_level = 1; - InsertEntryIntoHnswIndex(key1, vec1, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key1, vec1, target_level, hnsw_index.get(), storage_.get()); // Search when HNSW graph contains less than k nodes - auto s2 = hnsw_index->KnnSearch(query_vector, k); + auto s2 = hnsw_index->KnnSearch(ctx, query_vector, k); ASSERT_TRUE(s2.IsOK()); auto key_strs = GetVectorKeys(s2.GetValue()); std::vector expected = {"key1"}; EXPECT_EQ(key_strs, expected); target_level = 2; - InsertEntryIntoHnswIndex(key2, vec2, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key2, vec2, target_level, hnsw_index.get(), storage_.get()); target_level = 0; - InsertEntryIntoHnswIndex(key3, vec3, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key3, vec3, target_level, hnsw_index.get(), storage_.get()); // Search when HNSW graph contains exactly k nodes - auto s3 = hnsw_index->KnnSearch(query_vector, k); + auto s3 = hnsw_index->KnnSearch(ctx, query_vector, k); ASSERT_TRUE(s3.IsOK()); key_strs = GetVectorKeys(s3.GetValue()); expected = {"key3", "key2", "key1"}; EXPECT_EQ(key_strs, expected); target_level = 1; - InsertEntryIntoHnswIndex(key4, vec4, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key4, vec4, target_level, hnsw_index.get(), storage_.get()); target_level = 0; - InsertEntryIntoHnswIndex(key5, vec5, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key5, vec5, target_level, hnsw_index.get(), storage_.get()); // Search when HNSW graph contains more than k nodes - auto s4 = hnsw_index->KnnSearch(query_vector, k); + auto s4 = hnsw_index->KnnSearch(ctx, query_vector, k); ASSERT_TRUE(s4.IsOK()); key_strs = GetVectorKeys(s4.GetValue()); expected = {"key5", "key3", "key2"}; @@ -564,7 +568,7 @@ TEST_F(HnswIndexTest, SearchKnnAndRange) { // Edge case: If ef_runtime is smaller than k, enlarge ef_runtime equal to k hnsw_index->metadata->ef_runtime = 1; - auto s5 = hnsw_index->KnnSearch(query_vector, k); + auto s5 = hnsw_index->KnnSearch(ctx, query_vector, k); ASSERT_TRUE(s5.IsOK()); auto result = s5.GetValue(); key_strs = GetVectorKeys(result); @@ -572,25 +576,25 @@ TEST_F(HnswIndexTest, SearchKnnAndRange) { EXPECT_EQ(key_strs, expected); hnsw_index->metadata->ef_runtime = 5; - InsertEntryIntoHnswIndex(key6, vec6, target_level, hnsw_index.get(), storage_.get()); - InsertEntryIntoHnswIndex(key7, vec7, target_level, hnsw_index.get(), storage_.get()); - InsertEntryIntoHnswIndex(key8, vec8, target_level, hnsw_index.get(), storage_.get()); - InsertEntryIntoHnswIndex(key9, vec9, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key6, vec6, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key7, vec7, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key8, vec8, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key9, vec9, target_level, hnsw_index.get(), storage_.get()); target_level = 1; - InsertEntryIntoHnswIndex(key10, vec10, target_level, hnsw_index.get(), storage_.get()); - InsertEntryIntoHnswIndex(key11, vec11, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key10, vec10, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key11, vec11, target_level, hnsw_index.get(), storage_.get()); target_level = 2; - InsertEntryIntoHnswIndex(key12, vec12, target_level, hnsw_index.get(), storage_.get()); + InsertEntryIntoHnswIndex(ctx, key12, vec12, target_level, hnsw_index.get(), storage_.get()); std::unordered_set visited{key_strs.begin(), key_strs.end()}; - auto s6 = hnsw_index->ExpandSearchScope(query_vector, std::move(result), visited); + auto s6 = hnsw_index->ExpandSearchScope(ctx, query_vector, std::move(result), visited); ASSERT_TRUE(s6.IsOK()); result = s6.GetValue(); key_strs = GetVectorKeys(result); expected = {"key8", "key9", "key10", "key4", "key1", "key6", "key7", "key12"}; EXPECT_EQ(key_strs, expected); - auto s7 = hnsw_index->ExpandSearchScope(query_vector, std::move(result), visited); + auto s7 = hnsw_index->ExpandSearchScope(ctx, query_vector, std::move(result), visited); ASSERT_TRUE(s7.IsOK()); key_strs = GetVectorKeys(s7.GetValue()); expected = {"key11"}; diff --git a/tests/cppunit/hnsw_node_test.cc b/tests/cppunit/hnsw_node_test.cc index 5fadf9927a5..23cfadb0809 100644 --- a/tests/cppunit/hnsw_node_test.cc +++ b/tests/cppunit/hnsw_node_test.cc @@ -56,20 +56,21 @@ TEST_F(NodeTest, PutAndDecodeMetadata) { node1.PutMetadata(&metadata1, search_key, storage_.get(), batch.Get()); node2.PutMetadata(&metadata2, search_key, storage_.get(), batch.Get()); node3.PutMetadata(&metadata3, search_key, storage_.get(), batch.Get()); - auto s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + engine::Context ctx(storage_.get()); + auto s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(s.ok()); - auto decoded_metadata1 = node1.DecodeMetadata(search_key, storage_.get()); + auto decoded_metadata1 = node1.DecodeMetadata(ctx, search_key); ASSERT_TRUE(decoded_metadata1.IsOK()); ASSERT_EQ(decoded_metadata1.GetValue().num_neighbours, 0); ASSERT_EQ(decoded_metadata1.GetValue().vector, std::vector({1, 2, 3})); - auto decoded_metadata2 = node2.DecodeMetadata(search_key, storage_.get()); + auto decoded_metadata2 = node2.DecodeMetadata(ctx, search_key); ASSERT_TRUE(decoded_metadata2.IsOK()); ASSERT_EQ(decoded_metadata2.GetValue().num_neighbours, 0); ASSERT_EQ(decoded_metadata2.GetValue().vector, std::vector({4, 5, 6})); - auto decoded_metadata3 = node3.DecodeMetadata(search_key, storage_.get()); + auto decoded_metadata3 = node3.DecodeMetadata(ctx, search_key); ASSERT_TRUE(decoded_metadata3.IsOK()); ASSERT_EQ(decoded_metadata3.GetValue().num_neighbours, 0); ASSERT_EQ(decoded_metadata3.GetValue().vector, std::vector({7, 8, 9})); @@ -85,20 +86,20 @@ TEST_F(NodeTest, PutAndDecodeMetadata) { batch->Put(storage_->GetCFHandle(ColumnFamilyID::Search), edge2, Slice()); batch->Put(storage_->GetCFHandle(ColumnFamilyID::Search), edge3, Slice()); batch->Put(storage_->GetCFHandle(ColumnFamilyID::Search), edge4, Slice()); - s = storage_->Write(storage_->DefaultWriteOptions(), batch->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch->GetWriteBatch()); ASSERT_TRUE(s.ok()); - node1.DecodeNeighbours(search_key, storage_.get()); + node1.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node1.neighbours.size(), 1); EXPECT_EQ(node1.neighbours[0], "node2"); - node2.DecodeNeighbours(search_key, storage_.get()); + node2.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node2.neighbours.size(), 2); std::unordered_set expected_neighbours = {"node1", "node3"}; std::unordered_set actual_neighbours(node2.neighbours.begin(), node2.neighbours.end()); EXPECT_EQ(actual_neighbours, expected_neighbours); - node3.DecodeNeighbours(search_key, storage_.get()); + node3.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node3.neighbours.size(), 1); EXPECT_EQ(node3.neighbours[0], "node2"); } @@ -121,45 +122,46 @@ TEST_F(NodeTest, ModifyNeighbours) { node2.PutMetadata(&metadata2, search_key, storage_.get(), batch1.Get()); node3.PutMetadata(&metadata3, search_key, storage_.get(), batch1.Get()); node4.PutMetadata(&metadata4, search_key, storage_.get(), batch1.Get()); - auto s = storage_->Write(storage_->DefaultWriteOptions(), batch1->GetWriteBatch()); + engine::Context ctx(storage_.get()); + auto s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch1->GetWriteBatch()); ASSERT_TRUE(s.ok()); // Add Edges auto batch2 = storage_->GetWriteBatchBase(); - auto s1 = node1.AddNeighbour("node2", search_key, storage_.get(), batch2.Get()); + auto s1 = node1.AddNeighbour(ctx, "node2", search_key, batch2.Get()); ASSERT_TRUE(s1.IsOK()); - auto s2 = node2.AddNeighbour("node1", search_key, storage_.get(), batch2.Get()); + auto s2 = node2.AddNeighbour(ctx, "node1", search_key, batch2.Get()); ASSERT_TRUE(s2.IsOK()); - auto s3 = node2.AddNeighbour("node3", search_key, storage_.get(), batch2.Get()); + auto s3 = node2.AddNeighbour(ctx, "node3", search_key, batch2.Get()); ASSERT_TRUE(s3.IsOK()); - auto s4 = node3.AddNeighbour("node2", search_key, storage_.get(), batch2.Get()); + auto s4 = node3.AddNeighbour(ctx, "node2", search_key, batch2.Get()); ASSERT_TRUE(s4.IsOK()); - s = storage_->Write(storage_->DefaultWriteOptions(), batch2->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch2->GetWriteBatch()); ASSERT_TRUE(s.ok()); - node1.DecodeNeighbours(search_key, storage_.get()); + node1.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node1.neighbours.size(), 1); EXPECT_EQ(node1.neighbours[0], "node2"); - node2.DecodeNeighbours(search_key, storage_.get()); + node2.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node2.neighbours.size(), 2); std::unordered_set expected_neighbours = {"node1", "node3"}; std::unordered_set actual_neighbours(node2.neighbours.begin(), node2.neighbours.end()); EXPECT_EQ(actual_neighbours, expected_neighbours); - node3.DecodeNeighbours(search_key, storage_.get()); + node3.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node3.neighbours.size(), 1); EXPECT_EQ(node3.neighbours[0], "node2"); // Remove Edges auto batch3 = storage_->GetWriteBatchBase(); - auto s5 = node2.RemoveNeighbour("node3", search_key, storage_.get(), batch3.Get()); + auto s5 = node2.RemoveNeighbour(ctx, "node3", search_key, batch3.Get()); ASSERT_TRUE(s5.IsOK()); - s = storage_->Write(storage_->DefaultWriteOptions(), batch3->GetWriteBatch()); + s = storage_->Write(ctx, storage_->DefaultWriteOptions(), batch3->GetWriteBatch()); ASSERT_TRUE(s.ok()); - node2.DecodeNeighbours(search_key, storage_.get()); + node2.DecodeNeighbours(ctx, search_key); EXPECT_EQ(node2.neighbours.size(), 1); EXPECT_EQ(node2.neighbours[0], "node1"); } diff --git a/tests/cppunit/indexer_test.cc b/tests/cppunit/indexer_test.cc index f6e1e64da86..4e5ea3fce8d 100644 --- a/tests/cppunit/indexer_test.cc +++ b/tests/cppunit/indexer_test.cc @@ -77,7 +77,7 @@ TEST_F(IndexerTest, HashTag) { auto cfhandler = storage_->GetCFHandle(ColumnFamilyID::Search); { - auto s = indexer.Record("no_exist", ns); + auto s = indexer.Record(*ctx_, "no_exist", ns); ASSERT_TRUE(s.Is()); } @@ -85,80 +85,80 @@ TEST_F(IndexerTest, HashTag) { auto idxname = "hashtest"; { - auto s = indexer.Record(key1, ns); + auto s = indexer.Record(*ctx_, key1, ns); ASSERT_EQ(s.Msg(), Status::ok_msg); ASSERT_EQ(s->updater.info->name, idxname); ASSERT_TRUE(s->fields.empty()); uint64_t cnt = 0; - db.Set(key1, "x", "food,kitChen,Beauty", &cnt); + db.Set(*ctx_, key1, "x", "food,kitChen,Beauty", &cnt); ASSERT_EQ(cnt, 1); - auto s2 = indexer.Update(*s); + auto s2 = indexer.Update(*ctx_, *s); ASSERT_TRUE(s2); auto key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("food", key1); std::string val; - auto s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + auto s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("kitchen", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("beauty", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); } { - auto s = indexer.Record(key1, ns); + auto s = indexer.Record(*ctx_, key1, ns); ASSERT_TRUE(s); ASSERT_EQ(s->updater.info->name, idxname); ASSERT_EQ(s->fields.size(), 1); ASSERT_EQ(s->fields["x"], T("food,kitChen,Beauty")); uint64_t cnt = 0; - auto s_set = db.Set(key1, "x", "Clothing,FOOD,sport", &cnt); + auto s_set = db.Set(*ctx_, key1, "x", "Clothing,FOOD,sport", &cnt); ASSERT_EQ(cnt, 0); ASSERT_TRUE(s_set.ok()); - auto s2 = indexer.Update(*s); + auto s2 = indexer.Update(*ctx_, *s); ASSERT_TRUE(s2); auto key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("food", key1); std::string val; - auto s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + auto s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("clothing", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("sport", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("kitchen", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.IsNotFound()); key = redis::SearchKey(ns, idxname, "x").ConstructTagFieldData("beauty", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.IsNotFound()); } } @@ -168,7 +168,7 @@ TEST_F(IndexerTest, JsonTag) { auto cfhandler = storage_->GetCFHandle(ColumnFamilyID::Search); { - auto s = indexer.Record("no_exist", ns); + auto s = indexer.Record(*ctx_, "no_exist", ns); ASSERT_TRUE(s.Is()); } @@ -176,77 +176,77 @@ TEST_F(IndexerTest, JsonTag) { auto idxname = "jsontest"; { - auto s = indexer.Record(key1, ns); + auto s = indexer.Record(*ctx_, key1, ns); ASSERT_TRUE(s); ASSERT_EQ(s->updater.info->name, idxname); ASSERT_TRUE(s->fields.empty()); - auto s_set = db.Set(key1, "$", R"({"x": "food,kitChen,Beauty"})"); + auto s_set = db.Set(*ctx_, key1, "$", R"({"x": "food,kitChen,Beauty"})"); ASSERT_TRUE(s_set.ok()); - auto s2 = indexer.Update(*s); + auto s2 = indexer.Update(*ctx_, *s); ASSERT_TRUE(s2); auto key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("food", key1); std::string val; - auto s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + auto s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("kitchen", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("beauty", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); } { - auto s = indexer.Record(key1, ns); + auto s = indexer.Record(*ctx_, key1, ns); ASSERT_TRUE(s); ASSERT_EQ(s->updater.info->name, idxname); ASSERT_EQ(s->fields.size(), 1); ASSERT_EQ(s->fields["$.x"], T("food,kitChen,Beauty")); - auto s_set = db.Set(key1, "$.x", "\"Clothing,FOOD,sport\""); + auto s_set = db.Set(*ctx_, key1, "$.x", "\"Clothing,FOOD,sport\""); ASSERT_TRUE(s_set.ok()); - auto s2 = indexer.Update(*s); + auto s2 = indexer.Update(*ctx_, *s); ASSERT_TRUE(s2); auto key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("food", key1); std::string val; - auto s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + auto s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("clothing", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("sport", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("kitchen", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.IsNotFound()); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("beauty", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.IsNotFound()); } } @@ -259,28 +259,28 @@ TEST_F(IndexerTest, JsonTagBuildIndex) { auto idxname = "jsontest"; { - auto s_set = db.Set(key1, "$", R"({"x": "food,kitChen,Beauty"})"); + auto s_set = db.Set(*ctx_, key1, "$", R"({"x": "food,kitChen,Beauty"})"); ASSERT_TRUE(s_set.ok()); - auto s2 = indexer.updater_list[1].Build(); + auto s2 = indexer.updater_list[1].Build(*ctx_); ASSERT_EQ(s2.Msg(), Status::ok_msg); auto key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("food", key1); std::string val; - auto s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + auto s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("kitchen", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); key = redis::SearchKey(ns, idxname, "$.x").ConstructTagFieldData("beauty", key1); - s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, key, &val); + s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, key, &val); ASSERT_TRUE(s3.ok()); ASSERT_EQ(val, ""); } @@ -291,7 +291,7 @@ TEST_F(IndexerTest, JsonHnswVector) { auto cfhandler = storage_->GetCFHandle(ColumnFamilyID::Search); { - auto s = indexer.Record("no_exist", ns); + auto s = indexer.Record(*ctx_, "no_exist", ns); ASSERT_TRUE(s.Is()); } @@ -299,21 +299,21 @@ TEST_F(IndexerTest, JsonHnswVector) { auto idxname = "jsontest"; { - auto s = indexer.Record(key3, ns); + auto s = indexer.Record(*ctx_, key3, ns); ASSERT_TRUE(s); ASSERT_EQ(s->updater.info->name, idxname); ASSERT_TRUE(s->fields.empty()); - auto s_set = db.Set(key3, "$", R"({"z": [1,2,3]})"); + auto s_set = db.Set(*ctx_, key3, "$", R"({"z": [1,2,3]})"); ASSERT_TRUE(s_set.ok()); - auto s2 = indexer.Update(*s); + auto s2 = indexer.Update(*ctx_, *s); EXPECT_EQ(s2.Msg(), Status::ok_msg); auto search_key = redis::SearchKey(ns, idxname, "$.z").ConstructHnswNode(0, key3); std::string val; - auto s3 = storage_->Get(storage_->DefaultMultiGetOptions(), cfhandler, search_key, &val); + auto s3 = storage_->Get(*ctx_, ctx_->DefaultMultiGetOptions(), cfhandler, search_key, &val); ASSERT_TRUE(s3.ok()); redis::HnswNodeFieldMetadata node_meta; diff --git a/tests/cppunit/iterator_test.cc b/tests/cppunit/iterator_test.cc index 08705d7719c..183edcdde57 100644 --- a/tests/cppunit/iterator_test.cc +++ b/tests/cppunit/iterator_test.cc @@ -41,38 +41,38 @@ class DBIteratorTest : public TestBase { void SetUp() override { { // string redis::String string(storage_.get(), "test_ns0"); - string.Set("a", "1"); - string.Set("b", "2"); - string.Set("c", "3"); + string.Set(*ctx_, "a", "1"); + string.Set(*ctx_, "b", "2"); + string.Set(*ctx_, "c", "3"); // Make sure the key "c" is expired - auto s = string.Expire("c", 1); + auto s = string.Expire(*ctx_, "c", 1); ASSERT_TRUE(s.ok()); - string.Set("d", "4"); + string.Set(*ctx_, "d", "4"); } { // hash uint64_t ret = 0; redis::Hash hash(storage_.get(), "test_ns1"); - hash.MSet("hash-1", {{"f0", "v0"}, {"f1", "v1"}, {"f2", "v2"}, {"f3", "v3"}}, false, &ret); + hash.MSet(*ctx_, "hash-1", {{"f0", "v0"}, {"f1", "v1"}, {"f2", "v2"}, {"f3", "v3"}}, false, &ret); } { // set uint64_t ret = 0; redis::Set set(storage_.get(), "test_ns2"); - set.Add("set-1", {"e0", "e1", "e2"}, &ret); + set.Add(*ctx_, "set-1", {"e0", "e1", "e2"}, &ret); } { // sorted set uint64_t ret = 0; redis::ZSet zset(storage_.get(), "test_ns3"); auto mscores = std::vector{{"z0", 0}, {"z1", 1}, {"z2", 2}}; - zset.Add("zset-1", ZAddFlags(), &mscores, &ret); + zset.Add(*ctx_, "zset-1", ZAddFlags(), &mscores, &ret); } { // list uint64_t ret = 0; redis::List list(storage_.get(), "test_ns4"); - list.Push("list-1", {"l0", "l1", "l2"}, false, &ret); + list.Push(*ctx_, "list-1", {"l0", "l1", "l2"}, false, &ret); } { // stream @@ -80,27 +80,27 @@ class DBIteratorTest : public TestBase { redis::StreamEntryID ret; redis::StreamAddOptions options; options.next_id_strategy = std::make_unique(); - stream.Add("stream-1", options, {"x0"}, &ret); - stream.Add("stream-1", options, {"x1"}, &ret); - stream.Add("stream-1", options, {"x2"}, &ret); + stream.Add(*ctx_, "stream-1", options, {"x0"}, &ret); + stream.Add(*ctx_, "stream-1", options, {"x1"}, &ret); + stream.Add(*ctx_, "stream-1", options, {"x2"}, &ret); // TODO(@git-hulk): add stream group after it's finished } { // bitmap redis::Bitmap bitmap(storage_.get(), "test_ns6"); bool ret = false; - bitmap.SetBit("bitmap-1", 0, true, &ret); - bitmap.SetBit("bitmap-1", 8 * 1024, true, &ret); - bitmap.SetBit("bitmap-1", 2 * 8 * 1024, true, &ret); + bitmap.SetBit(*ctx_, "bitmap-1", 0, true, &ret); + bitmap.SetBit(*ctx_, "bitmap-1", 8 * 1024, true, &ret); + bitmap.SetBit(*ctx_, "bitmap-1", 2 * 8 * 1024, true, &ret); } { // json redis::Json json(storage_.get(), "test_ns7"); - json.Set("json-1", "$", "{\"a\": 1, \"b\": 2}"); - json.Set("json-2", "$", "{\"a\": 1, \"b\": 2}"); - json.Set("json-3", "$", "{\"a\": 1, \"b\": 2}"); - json.Set("json-4", "$", "{\"a\": 1, \"b\": 2}"); - auto s = json.Expire("json-4", 1); + json.Set(*ctx_, "json-1", "$", "{\"a\": 1, \"b\": 2}"); + json.Set(*ctx_, "json-2", "$", "{\"a\": 1, \"b\": 2}"); + json.Set(*ctx_, "json-3", "$", "{\"a\": 1, \"b\": 2}"); + json.Set(*ctx_, "json-4", "$", "{\"a\": 1, \"b\": 2}"); + auto s = json.Expire(*ctx_, "json-4", 1); ASSERT_TRUE(s.ok()); } @@ -108,13 +108,13 @@ class DBIteratorTest : public TestBase { // sorted integer redis::Sortedint sortedint(storage_.get(), "test_ns8"); uint64_t ret = 0; - sortedint.Add("sortedint-1", {1, 2, 3}, &ret); + sortedint.Add(*ctx_, "sortedint-1", {1, 2, 3}, &ret); } } }; TEST_F(DBIteratorTest, AllKeys) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); std::vector live_keys = {"a", "b", "d", "hash-1", "set-1", "zset-1", "list-1", "stream-1", "bitmap-1", "json-1", "json-2", "json-3", "sortedint-1"}; std::reverse(live_keys.begin(), live_keys.end()); @@ -128,7 +128,7 @@ TEST_F(DBIteratorTest, AllKeys) { } TEST_F(DBIteratorTest, BasicString) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); std::vector expected_keys = {"a", "b", "d"}; std::reverse(expected_keys.begin(), expected_keys.end()); @@ -150,7 +150,7 @@ TEST_F(DBIteratorTest, BasicString) { } TEST_F(DBIteratorTest, BasicHash) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns1", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { ASSERT_EQ(kRedisHash, iter.Type()); @@ -173,7 +173,7 @@ TEST_F(DBIteratorTest, BasicHash) { } TEST_F(DBIteratorTest, BasicSet) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns2", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { ASSERT_EQ(kRedisSet, iter.Type()); @@ -196,7 +196,7 @@ TEST_F(DBIteratorTest, BasicSet) { } TEST_F(DBIteratorTest, BasicZSet) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns3", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { ASSERT_EQ(kRedisZSet, iter.Type()); @@ -219,7 +219,7 @@ TEST_F(DBIteratorTest, BasicZSet) { } TEST_F(DBIteratorTest, BasicList) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns4", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { ASSERT_EQ(kRedisList, iter.Type()); @@ -242,7 +242,7 @@ TEST_F(DBIteratorTest, BasicList) { } TEST_F(DBIteratorTest, BasicStream) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns5", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { ASSERT_EQ(kRedisStream, iter.Type()); @@ -268,7 +268,7 @@ TEST_F(DBIteratorTest, BasicStream) { } TEST_F(DBIteratorTest, BasicBitmap) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns6", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { ASSERT_EQ(kRedisBitmap, iter.Type()); @@ -290,7 +290,7 @@ TEST_F(DBIteratorTest, BasicBitmap) { } TEST_F(DBIteratorTest, BasicJSON) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); std::vector expected_keys = {"json-1", "json-2", "json-3"}; std::reverse(expected_keys.begin(), expected_keys.end()); @@ -312,7 +312,7 @@ TEST_F(DBIteratorTest, BasicJSON) { } TEST_F(DBIteratorTest, BasicSortedInt) { - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions()); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions()); auto prefix = ComposeNamespaceKey("test_ns8", "", storage_->IsSlotIdEncoded()); for (iter.Seek(prefix); iter.Valid() && iter.Key().starts_with(prefix); iter.Next()) { @@ -347,7 +347,7 @@ TEST_F(SlotIteratorTest, LiveKeys) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); std::vector keys = {"{x}a", "{x}b", "{y}c", "{y}d", "{x}e"}; for (const auto &key : keys) { - string.Set(key, "1"); + string.Set(*ctx_, key, "1"); } std::set same_slot_keys; @@ -357,7 +357,7 @@ TEST_F(SlotIteratorTest, LiveKeys) { same_slot_keys.insert(key); } } - engine::DBIterator iter(storage_.get(), rocksdb::ReadOptions(), slot_id); + engine::DBIterator iter(*ctx_, rocksdb::ReadOptions(), slot_id); int count = 0; for (iter.Seek(); iter.Valid(); iter.Next()) { auto [_, user_key] = iter.UserKey(); @@ -389,9 +389,9 @@ class WALIteratorTest : public TestBase { TEST_F(WALIteratorTest, BasicString) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); redis::String string(storage_.get(), "test_ns0"); - string.Set("a", "1"); - string.MSet({{"b", "2"}, {"c", "3"}}, 0); - ASSERT_TRUE(string.Del("b").ok()); + string.Set(*ctx_, "a", "1"); + string.MSet(*ctx_, {{"b", "2"}, {"c", "3"}}, 0); + ASSERT_TRUE(string.Del(*ctx_, "b").ok()); std::vector put_keys, delete_keys; auto expected_put_keys = {"a", "b", "c"}; @@ -434,9 +434,9 @@ TEST_F(WALIteratorTest, BasicHash) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); redis::Hash hash(storage_.get(), "test_ns1"); uint64_t ret = 0; - hash.MSet("hash-1", {{"f0", "v0"}, {"f1", "v1"}, {"f2", "v2"}, {"f3", "v3"}}, false, &ret); + hash.MSet(*ctx_, "hash-1", {{"f0", "v0"}, {"f1", "v1"}, {"f2", "v2"}, {"f3", "v3"}}, false, &ret); uint64_t deleted_cnt = 0; - hash.Delete("hash-1", {"f0"}, &deleted_cnt); + hash.Delete(*ctx_, "hash-1", {"f0"}, &deleted_cnt); // Delete will put meta key again auto expected_put_keys = {"hash-1", "hash-1"}; @@ -489,9 +489,9 @@ TEST_F(WALIteratorTest, BasicSet) { uint64_t ret = 0; redis::Set set(storage_.get(), "test_ns2"); - set.Add("set-1", {"e0", "e1", "e2"}, &ret); + set.Add(*ctx_, "set-1", {"e0", "e1", "e2"}, &ret); uint64_t removed_cnt = 0; - set.Remove("set-1", {"e0", "e1"}, &removed_cnt); + set.Remove(*ctx_, "set-1", {"e0", "e1"}, &removed_cnt); auto expected_put_keys = {"set-1", "set-1"}; auto expected_put_members = {"e0", "e1", "e2"}; @@ -543,9 +543,9 @@ TEST_F(WALIteratorTest, BasicZSet) { uint64_t ret = 0; redis::ZSet zset(storage_.get(), "test_ns3"); auto mscores = std::vector{{"z0", 0}, {"z1", 1}, {"z2", 2}}; - zset.Add("zset-1", ZAddFlags(), &mscores, &ret); + zset.Add(*ctx_, "zset-1", ZAddFlags(), &mscores, &ret); uint64_t removed_cnt = 0; - zset.Remove("zset-1", {"z0"}, &removed_cnt); + zset.Remove(*ctx_, "zset-1", {"z0"}, &removed_cnt); auto expected_put_keys = {"zset-1", "zset-1"}; auto expected_put_members = {"z2", "z1", "z0"}; @@ -595,8 +595,8 @@ TEST_F(WALIteratorTest, BasicList) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); uint64_t ret = 0; redis::List list(storage_.get(), "test_ns4"); - list.Push("list-1", {"l0", "l1", "l2", "l3", "l4"}, false, &ret); - ASSERT_TRUE(list.Trim("list-1", 2, 4).ok()); + list.Push(*ctx_, "list-1", {"l0", "l1", "l2", "l3", "l4"}, false, &ret); + ASSERT_TRUE(list.Trim(*ctx_, "list-1", 2, 4).ok()); auto expected_put_keys = {"list-1", "list-1"}; auto expected_put_values = {"l0", "l1", "l2", "l3", "l4"}; @@ -646,11 +646,11 @@ TEST_F(WALIteratorTest, BasicStream) { redis::StreamEntryID ret; redis::StreamAddOptions options; options.next_id_strategy = std::make_unique(); - stream.Add("stream-1", options, {"x0"}, &ret); - stream.Add("stream-1", options, {"x1"}, &ret); - stream.Add("stream-1", options, {"x2"}, &ret); + stream.Add(*ctx_, "stream-1", options, {"x0"}, &ret); + stream.Add(*ctx_, "stream-1", options, {"x1"}, &ret); + stream.Add(*ctx_, "stream-1", options, {"x2"}, &ret); uint64_t deleted = 0; - ASSERT_TRUE(stream.DeleteEntries("stream-1", {ret}, &deleted).ok()); + ASSERT_TRUE(stream.DeleteEntries(*ctx_, "stream-1", {ret}, &deleted).ok()); auto expected_put_keys = {"stream-1", "stream-1", "stream-1", "stream-1"}; auto expected_put_values = {"x0", "x1", "x2"}; @@ -702,9 +702,9 @@ TEST_F(WALIteratorTest, BasicBitmap) { redis::Bitmap bitmap(storage_.get(), "test_ns6"); bool ret = false; - bitmap.SetBit("bitmap-1", 0, true, &ret); - bitmap.SetBit("bitmap-1", 8 * 1024, true, &ret); - bitmap.SetBit("bitmap-1", 2 * 8 * 1024, true, &ret); + bitmap.SetBit(*ctx_, "bitmap-1", 0, true, &ret); + bitmap.SetBit(*ctx_, "bitmap-1", 8 * 1024, true, &ret); + bitmap.SetBit(*ctx_, "bitmap-1", 2 * 8 * 1024, true, &ret); auto expected_put_values = {"\x1", "\x1", "\x1"}; std::vector put_values; @@ -737,12 +737,12 @@ TEST_F(WALIteratorTest, BasicBitmap) { TEST_F(WALIteratorTest, BasicJSON) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); redis::Json json(storage_.get(), "test_ns7"); - json.Set("json-1", "$", "{\"a\": 1, \"b\": 2}"); - json.Set("json-2", "$", "{\"a\": 1, \"b\": 2}"); - json.Set("json-3", "$", "{\"a\": 1, \"b\": 2}"); + json.Set(*ctx_, "json-1", "$", "{\"a\": 1, \"b\": 2}"); + json.Set(*ctx_, "json-2", "$", "{\"a\": 1, \"b\": 2}"); + json.Set(*ctx_, "json-3", "$", "{\"a\": 1, \"b\": 2}"); size_t result = 0; - ASSERT_TRUE(json.Del("json-3", "$", &result).ok()); + ASSERT_TRUE(json.Del(*ctx_, "json-3", "$", &result).ok()); auto expected_put_keys = {"json-1", "json-2", "json-3"}; auto expected_delete_keys = {"json-3"}; @@ -788,9 +788,9 @@ TEST_F(WALIteratorTest, BasicSortedInt) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); redis::Sortedint sortedint(storage_.get(), "test_ns8"); uint64_t ret = 0; - sortedint.Add("sortedint-1", {1, 2, 3}, &ret); + sortedint.Add(*ctx_, "sortedint-1", {1, 2, 3}, &ret); uint64_t removed_cnt = 0; - sortedint.Remove("sortedint-1", {2}, &removed_cnt); + sortedint.Remove(*ctx_, "sortedint-1", {2}, &removed_cnt); std::vector expected_values = {1, 2, 3}, put_values; std::vector expected_delete_values = {2}, delete_values; @@ -837,11 +837,11 @@ TEST_F(WALIteratorTest, NextSequence) { auto start_seq = storage_->GetDB()->GetLatestSequenceNumber(); uint64_t ret = 0; redis::List list(storage_.get(), "test_ns2"); - list.Push("list-1", {"l0", "l1", "l2", "l3", "l4"}, false, &ret); + list.Push(*ctx_, "list-1", {"l0", "l1", "l2", "l3", "l4"}, false, &ret); expected_next_sequences.emplace_back(storage_->GetDB()->GetLatestSequenceNumber() + 1); - list.Push("list-2", {"l0", "l1", "l2"}, false, &ret); + list.Push(*ctx_, "list-2", {"l0", "l1", "l2"}, false, &ret); expected_next_sequences.emplace_back(storage_->GetDB()->GetLatestSequenceNumber() + 1); - ASSERT_TRUE(list.Trim("list-1", 2, 4).ok()); + ASSERT_TRUE(list.Trim(*ctx_, "list-1", 2, 4).ok()); expected_next_sequences.emplace_back(storage_->GetDB()->GetLatestSequenceNumber() + 1); engine::WALIterator iter(storage_.get()); diff --git a/tests/cppunit/metadata_test.cc b/tests/cppunit/metadata_test.cc index bd7282052e4..ffbaa88ba34 100644 --- a/tests/cppunit/metadata_test.cc +++ b/tests/cppunit/metadata_test.cc @@ -88,13 +88,13 @@ TEST_F(RedisTypeTest, GetMetadata) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); HashMetadata metadata; std::string ns_key = redis_->AppendNamespacePrefix(key_); - s = redis_->GetMetadata(redis::Database::GetOptions{}, {kRedisHash}, ns_key, &metadata); + s = redis_->GetMetadata(*ctx_, {kRedisHash}, ns_key, &metadata); EXPECT_EQ(fvs.size(), metadata.size); - s = redis_->Del(key_); + s = redis_->Del(*ctx_, key_); EXPECT_TRUE(s.ok()); } @@ -104,16 +104,16 @@ TEST_F(RedisTypeTest, Expire) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); int64_t now = 0; rocksdb::Env::Default()->GetCurrentTime(&now); - s = redis_->Expire(key_, now * 1000 + 2000); + s = redis_->Expire(*ctx_, key_, now * 1000 + 2000); int64_t ttl = 0; - s = redis_->TTL(key_, &ttl); + s = redis_->TTL(*ctx_, key_, &ttl); ASSERT_GT(ttl, 0); ASSERT_LE(ttl, 2000); - s = redis_->Del(key_); + s = redis_->Del(*ctx_, key_); } TEST_F(RedisTypeTest, ExpireTime) { @@ -122,23 +122,23 @@ TEST_F(RedisTypeTest, ExpireTime) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); int64_t now = 0; rocksdb::Env::Default()->GetCurrentTime(&now); uint64_t ms_offset = 2314; uint64_t expire_timestamp_ms = now * 1000 + ms_offset; - s = redis_->Expire(key_, expire_timestamp_ms); + s = redis_->Expire(*ctx_, key_, expire_timestamp_ms); EXPECT_TRUE(s.ok()); uint64_t timestamp = 0; - s = redis_->GetExpireTime(key_, ×tamp); + s = redis_->GetExpireTime(*ctx_, key_, ×tamp); EXPECT_TRUE(s.ok() && timestamp != 0); if (METADATA_ENCODING_VERSION != 0) { EXPECT_EQ(timestamp, expire_timestamp_ms); } else { EXPECT_EQ(timestamp, Metadata::ExpireMsToS(expire_timestamp_ms) * 1000); } - s = redis_->Del(key_); + s = redis_->Del(*ctx_, key_); } TEST_F(RedisTypeTest, ExpireTimeKeyNoExpireTime) { @@ -147,12 +147,12 @@ TEST_F(RedisTypeTest, ExpireTimeKeyNoExpireTime) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); uint64_t timestamp = 0; - s = redis_->GetExpireTime(key_, ×tamp); + s = redis_->GetExpireTime(*ctx_, key_, ×tamp); EXPECT_TRUE(s.ok() && timestamp == 0); - s = redis_->Del(key_); + s = redis_->Del(*ctx_, key_); } TEST_F(RedisTypeTest, ExpireTimeKeyExpired) { @@ -161,19 +161,19 @@ TEST_F(RedisTypeTest, ExpireTimeKeyExpired) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); int64_t now = 0; rocksdb::Env::Default()->GetCurrentTime(&now); uint64_t ms_offset = 1120; uint64_t expire_timestamp_ms = now * 1000 + ms_offset; - s = redis_->Expire(key_, expire_timestamp_ms); + s = redis_->Expire(*ctx_, key_, expire_timestamp_ms); EXPECT_TRUE(s.ok()); std::this_thread::sleep_for(std::chrono::milliseconds(2000)); uint64_t timestamp = 0; - s = redis_->GetExpireTime(key_, ×tamp); + s = redis_->GetExpireTime(*ctx_, key_, ×tamp); EXPECT_TRUE(s.IsNotFound() && timestamp == 0); - s = redis_->Del(key_); + s = redis_->Del(*ctx_, key_); } TEST_F(RedisTypeTest, ExpireTimeKeyNotExisted) { @@ -182,13 +182,13 @@ TEST_F(RedisTypeTest, ExpireTimeKeyNotExisted) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); uint64_t timestamp = 0; - s = redis_->GetExpireTime(key_ + "test", ×tamp); + s = redis_->GetExpireTime(*ctx_, key_ + "test", ×tamp); EXPECT_TRUE(s.IsNotFound() && timestamp == 0); - s = redis_->Del(key_); + s = redis_->Del(*ctx_, key_); } TEST(Metadata, MetadataDecodingBackwardCompatibleSimpleKey) { diff --git a/tests/cppunit/plan_executor_test.cc b/tests/cppunit/plan_executor_test.cc index 91c8cd2d4cb..3524c14393e 100644 --- a/tests/cppunit/plan_executor_test.cc +++ b/tests/cppunit/plan_executor_test.cc @@ -309,16 +309,16 @@ class PlanExecutorTestC : public TestBase { }; TEST_F(PlanExecutorTestC, FullIndexScan) { - json_->Set("test1:a", "$", "{}"); - json_->Set("test1:b", "$", "{}"); - json_->Set("test2:c", "$", "{\"f3\": 6}"); - json_->Set("test3:d", "$", "{}"); - json_->Set("test4:e", "$", "{\"f3\": 7}"); - json_->Set("test4:f", "$", "{\"f3\": 2}"); - json_->Set("test4:g", "$", "{\"f3\": 8}"); - json_->Set("test5:h", "$", "{}"); - json_->Set("test5:i", "$", "{}"); - json_->Set("test5:g", "$", "{}"); + json_->Set(*ctx_, "test1:a", "$", "{}"); + json_->Set(*ctx_, "test1:b", "$", "{}"); + json_->Set(*ctx_, "test2:c", "$", "{\"f3\": 6}"); + json_->Set(*ctx_, "test3:d", "$", "{}"); + json_->Set(*ctx_, "test4:e", "$", "{\"f3\": 7}"); + json_->Set(*ctx_, "test4:f", "$", "{\"f3\": 2}"); + json_->Set(*ctx_, "test4:g", "$", "{\"f3\": 8}"); + json_->Set(*ctx_, "test5:h", "$", "{}"); + json_->Set(*ctx_, "test5:i", "$", "{}"); + json_->Set(*ctx_, "test5:g", "$", "{}"); { auto op = std::make_unique(std::make_unique("ia", IndexI())); @@ -346,18 +346,19 @@ TEST_F(PlanExecutorTestC, FullIndexScan) { } struct ScopedUpdate { + engine::Context* db_ctx; redis::GlobalIndexer::RecordResult rr; std::string_view key; std::string ns; - static auto Create(redis::GlobalIndexer& indexer, std::string_view key, const std::string& ns) { - auto s = indexer.Record(key, ns); + static auto Create(engine::Context& ctx, redis::GlobalIndexer& indexer, std::string_view key, const std::string& ns) { + auto s = indexer.Record(ctx, key, ns); EXPECT_EQ(s.Msg(), Status::ok_msg); return *s; } - ScopedUpdate(redis::GlobalIndexer& indexer, std::string_view key, const std::string& ns) - : rr(Create(indexer, key, ns)), key(key), ns(ns) {} + ScopedUpdate(engine::Context* ctx, redis::GlobalIndexer& indexer, std::string_view key, const std::string& ns) + : db_ctx(ctx), rr(Create(*ctx, indexer, key, ns)), key(key), ns(ns) {} ScopedUpdate(const ScopedUpdate&) = delete; ScopedUpdate(ScopedUpdate&&) = delete; @@ -365,19 +366,19 @@ struct ScopedUpdate { ScopedUpdate& operator=(ScopedUpdate&&) = delete; ~ScopedUpdate() { - auto s = redis::GlobalIndexer::Update(rr); + auto s = redis::GlobalIndexer::Update(*db_ctx, rr); EXPECT_EQ(s.Msg(), Status::ok_msg); } }; -std::vector> ScopedUpdates(redis::GlobalIndexer& indexer, +std::vector> ScopedUpdates(engine::Context& ctx, redis::GlobalIndexer& indexer, const std::vector& keys, const std::string& ns) { std::vector> sus; sus.reserve(keys.size()); for (auto key : keys) { - sus.emplace_back(std::make_unique(indexer, key, ns)); + sus.emplace_back(std::make_unique(&ctx, indexer, key, ns)); } return sus; @@ -388,15 +389,16 @@ TEST_F(PlanExecutorTestC, NumericFieldScan) { indexer.Add(redis::IndexUpdater(IndexI())); { - auto updates = ScopedUpdates(indexer, {"test2:a", "test2:b", "test2:c", "test2:d", "test2:e", "test2:f", "test2:g"}, - "search_ns"); - json_->Set("test2:a", "$", "{\"f2\": 6}"); - json_->Set("test2:b", "$", "{\"f2\": 3}"); - json_->Set("test2:c", "$", "{\"f2\": 8}"); - json_->Set("test2:d", "$", "{\"f2\": 14}"); - json_->Set("test2:e", "$", "{\"f2\": 1}"); - json_->Set("test2:f", "$", "{\"f2\": 3}"); - json_->Set("test2:g", "$", "{\"f2\": 9}"); + engine::Context ctx(storage_.get()); + auto updates = ScopedUpdates( + *ctx_, indexer, {"test2:a", "test2:b", "test2:c", "test2:d", "test2:e", "test2:f", "test2:g"}, "search_ns"); + json_->Set(*ctx_, "test2:a", "$", "{\"f2\": 6}"); + json_->Set(*ctx_, "test2:b", "$", "{\"f2\": 3}"); + json_->Set(*ctx_, "test2:c", "$", "{\"f2\": 8}"); + json_->Set(*ctx_, "test2:d", "$", "{\"f2\": 14}"); + json_->Set(*ctx_, "test2:e", "$", "{\"f2\": 1}"); + json_->Set(*ctx_, "test2:f", "$", "{\"f2\": 3}"); + json_->Set(*ctx_, "test2:g", "$", "{\"f2\": 9}"); } { @@ -429,15 +431,16 @@ TEST_F(PlanExecutorTestC, TagFieldScan) { indexer.Add(redis::IndexUpdater(IndexI())); { - auto updates = ScopedUpdates(indexer, {"test2:a", "test2:b", "test2:c", "test2:d", "test2:e", "test2:f", "test2:g"}, - "search_ns"); - json_->Set("test2:a", "$", "{\"f1\": \"c,cpp,java\"}"); - json_->Set("test2:b", "$", "{\"f1\": \"python,c\"}"); - json_->Set("test2:c", "$", "{\"f1\": \"java,scala\"}"); - json_->Set("test2:d", "$", "{\"f1\": \"rust,python,perl\"}"); - json_->Set("test2:e", "$", "{\"f1\": \"python,cpp\"}"); - json_->Set("test2:f", "$", "{\"f1\": \"c,cpp\"}"); - json_->Set("test2:g", "$", "{\"f1\": \"cpp,rust\"}"); + engine::Context ctx(storage_.get()); + auto updates = ScopedUpdates( + *ctx_, indexer, {"test2:a", "test2:b", "test2:c", "test2:d", "test2:e", "test2:f", "test2:g"}, "search_ns"); + json_->Set(*ctx_, "test2:a", "$", "{\"f1\": \"c,cpp,java\"}"); + json_->Set(*ctx_, "test2:b", "$", "{\"f1\": \"python,c\"}"); + json_->Set(*ctx_, "test2:c", "$", "{\"f1\": \"java,scala\"}"); + json_->Set(*ctx_, "test2:d", "$", "{\"f1\": \"rust,python,perl\"}"); + json_->Set(*ctx_, "test2:e", "$", "{\"f1\": \"python,cpp\"}"); + json_->Set(*ctx_, "test2:f", "$", "{\"f1\": \"c,cpp\"}"); + json_->Set(*ctx_, "test2:g", "$", "{\"f1\": \"cpp,rust\"}"); } { @@ -467,24 +470,24 @@ TEST_F(PlanExecutorTestC, HnswVectorFieldScans) { indexer.Add(redis::IndexUpdater(IndexI())); { - auto updates = ScopedUpdates(indexer, + auto updates = ScopedUpdates(*ctx_, indexer, {"test2:a", "test2:b", "test2:c", "test2:d", "test2:e", "test2:f", "test2:g", "test2:h", "test2:i", "test2:j", "test2:k", "test2:l", "test2:m", "test2:n"}, "search_ns"); - json_->Set("test2:a", "$", "{\"f4\": [1,2,3]}"); - json_->Set("test2:b", "$", "{\"f4\": [4,5,6]}"); - json_->Set("test2:c", "$", "{\"f4\": [7,8,9]}"); - json_->Set("test2:d", "$", "{\"f4\": [10,11,12]}"); - json_->Set("test2:e", "$", "{\"f4\": [13,14,15]}"); - json_->Set("test2:f", "$", "{\"f4\": [23,24,25]}"); - json_->Set("test2:g", "$", "{\"f4\": [26,27,28]}"); - json_->Set("test2:h", "$", "{\"f4\": [77,78,79]}"); - json_->Set("test2:i", "$", "{\"f4\": [80,81,82]}"); - json_->Set("test2:j", "$", "{\"f4\": [83,84,85]}"); - json_->Set("test2:k", "$", "{\"f4\": [86,87,88]}"); - json_->Set("test2:l", "$", "{\"f4\": [89,90,91]}"); - json_->Set("test2:m", "$", "{\"f4\": [1026,1027,1028]}"); - json_->Set("test2:n", "$", "{\"f4\": [2226,2227,2228]}"); + json_->Set(*ctx_, "test2:a", "$", "{\"f4\": [1,2,3]}"); + json_->Set(*ctx_, "test2:b", "$", "{\"f4\": [4,5,6]}"); + json_->Set(*ctx_, "test2:c", "$", "{\"f4\": [7,8,9]}"); + json_->Set(*ctx_, "test2:d", "$", "{\"f4\": [10,11,12]}"); + json_->Set(*ctx_, "test2:e", "$", "{\"f4\": [13,14,15]}"); + json_->Set(*ctx_, "test2:f", "$", "{\"f4\": [23,24,25]}"); + json_->Set(*ctx_, "test2:g", "$", "{\"f4\": [26,27,28]}"); + json_->Set(*ctx_, "test2:h", "$", "{\"f4\": [77,78,79]}"); + json_->Set(*ctx_, "test2:i", "$", "{\"f4\": [80,81,82]}"); + json_->Set(*ctx_, "test2:j", "$", "{\"f4\": [83,84,85]}"); + json_->Set(*ctx_, "test2:k", "$", "{\"f4\": [86,87,88]}"); + json_->Set(*ctx_, "test2:l", "$", "{\"f4\": [89,90,91]}"); + json_->Set(*ctx_, "test2:m", "$", "{\"f4\": [1026,1027,1028]}"); + json_->Set(*ctx_, "test2:n", "$", "{\"f4\": [2226,2227,2228]}"); } { diff --git a/tests/cppunit/rdb_test.cc b/tests/cppunit/rdb_test.cc index 87df1587c2a..018812b8579 100644 --- a/tests/cppunit/rdb_test.cc +++ b/tests/cppunit/rdb_test.cc @@ -56,14 +56,14 @@ class RDBTest : public TestBase { ASSERT_TRUE(s.IsOK()); RDB rdb(storage_.get(), ns_, std::move(stream_ptr)); - s = rdb.LoadRdb(0); + s = rdb.LoadRdb(*ctx_, 0); ASSERT_TRUE(s.IsOK()); } void stringCheck(const std::string &key, const std::string &expect) { redis::String string_db(storage_.get(), ns_); std::string value; - auto s = string_db.Get(key, &value); + auto s = string_db.Get(*ctx_, key, &value); ASSERT_TRUE(s.ok()); ASSERT_TRUE(expect == value); } @@ -71,8 +71,7 @@ class RDBTest : public TestBase { void setCheck(const std::string &key, const std::vector &expect) { redis::Set set_db(storage_.get(), ns_); std::vector members; - auto s = set_db.Members(key, &members); - + auto s = set_db.Members(*ctx_, key, &members); ASSERT_TRUE(s.ok()); ASSERT_TRUE(expect == members); } @@ -80,7 +79,7 @@ class RDBTest : public TestBase { void hashCheck(const std::string &key, const std::map &expect) { redis::Hash hash_db(storage_.get(), ns_); std::vector field_values; - auto s = hash_db.GetAll(key, &field_values); + auto s = hash_db.GetAll(*ctx_, key, &field_values); ASSERT_TRUE(s.ok()); // size check @@ -97,7 +96,7 @@ class RDBTest : public TestBase { void listCheck(const std::string &key, const std::vector &expect) { redis::List list_db(storage_.get(), ns_); std::vector values; - auto s = list_db.Range(key, 0, -1, &values); + auto s = list_db.Range(*ctx_, key, 0, -1, &values); ASSERT_TRUE(s.ok()); ASSERT_TRUE(expect == values); } @@ -107,7 +106,7 @@ class RDBTest : public TestBase { std::vector member_scores; RangeRankSpec spec; - auto s = zset_db.RangeByRank(key, spec, &member_scores, nullptr); + auto s = zset_db.RangeByRank(*ctx_, key, spec, &member_scores, nullptr); ASSERT_TRUE(s.ok()); ASSERT_TRUE(expect.size() == member_scores.size()); for (size_t i = 0; i < expect.size(); ++i) { @@ -118,12 +117,12 @@ class RDBTest : public TestBase { rocksdb::Status keyExist(const std::string &key) { redis::Database redis(storage_.get(), ns_); - return redis.KeyExist(key); + return redis.KeyExist(*ctx_, key); } void flushDB() { redis::Database redis(storage_.get(), ns_); - auto s = redis.FlushDB(); + auto s = redis.FlushDB(*ctx_); ASSERT_TRUE(s.ok()); } diff --git a/tests/cppunit/storage_test.cc b/tests/cppunit/storage_test.cc index a6bcd4c875c..503d2515c4a 100644 --- a/tests/cppunit/storage_test.cc +++ b/tests/cppunit/storage_test.cc @@ -39,11 +39,13 @@ TEST(Storage, CreateBackup) { auto s = storage->Open(); ASSERT_TRUE(s.IsOK()); + auto ctx = engine::Context(storage.get()); + constexpr int cnt = 10; for (int i = 0; i < cnt; i++) { rocksdb::WriteBatch batch; batch.Put("k", "v"); - ASSERT_TRUE(storage->Write(rocksdb::WriteOptions(), &batch).ok()); + ASSERT_TRUE(storage->Write(ctx, rocksdb::WriteOptions(), &batch).ok()); } uint64_t sequence_number = 0; s = storage->CreateBackup(&sequence_number); diff --git a/tests/cppunit/test_base.h b/tests/cppunit/test_base.h index 16b7837bb49..fd691e59bba 100644 --- a/tests/cppunit/test_base.h +++ b/tests/cppunit/test_base.h @@ -51,8 +51,10 @@ class TestFixture { // NOLINT std::cout << "Failed to open the storage, encounter error: " << s.Msg() << std::endl; assert(s.IsOK()); } + ctx_ = std::make_unique(storage_.get()); } ~TestFixture() { + ctx_.reset(); storage_.reset(); std::error_code ec; @@ -69,6 +71,7 @@ class TestFixture { // NOLINT std::string key_; std::vector fields_; std::vector values_; + std::unique_ptr ctx_; }; class TestBase : public TestFixture, public ::testing::Test {}; diff --git a/tests/cppunit/types/bitmap_test.cc b/tests/cppunit/types/bitmap_test.cc index 6ec2d9e39a1..4685e378084 100644 --- a/tests/cppunit/types/bitmap_test.cc +++ b/tests/cppunit/types/bitmap_test.cc @@ -38,12 +38,12 @@ class RedisBitmapTest : public TestFixture, public ::testing::TestWithParamSet(key_, ""); + string_->Set(*ctx_, key_, ""); } } void TearDown() override { - [[maybe_unused]] auto s = bitmap_->Del(key_); - s = string_->Del(key_); + [[maybe_unused]] auto s = bitmap_->Del(*ctx_, key_); + s = string_->Del(*ctx_, key_); } std::unique_ptr bitmap_; @@ -56,84 +56,84 @@ TEST_P(RedisBitmapTest, GetAndSetBit) { uint32_t offsets[] = {0, 123, 1024 * 8, 1024 * 8 + 1, 3 * 1024 * 8, 3 * 1024 * 8 + 1}; for (const auto &offset : offsets) { bool bit = false; - bitmap_->GetBit(key_, offset, &bit); + bitmap_->GetBit(*ctx_, key_, offset, &bit); EXPECT_FALSE(bit); - bitmap_->SetBit(key_, offset, true, &bit); - bitmap_->GetBit(key_, offset, &bit); + bitmap_->SetBit(*ctx_, key_, offset, true, &bit); + bitmap_->GetBit(*ctx_, key_, offset, &bit); EXPECT_TRUE(bit); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitCount) { uint32_t offsets[] = {0, 123, 1024 * 8, 1024 * 8 + 1, 3 * 1024 * 8, 3 * 1024 * 8 + 1}; for (const auto &offset : offsets) { bool bit = false; - bitmap_->SetBit(key_, offset, true, &bit); + bitmap_->SetBit(*ctx_, key_, offset, true, &bit); } uint32_t cnt = 0; - bitmap_->BitCount(key_, 0, 4 * 1024, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 4 * 1024, false, &cnt); EXPECT_EQ(cnt, 6); - bitmap_->BitCount(key_, 0, -1, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, -1, false, &cnt); EXPECT_EQ(cnt, 6); - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitCountNegative) { { bool bit = false; - bitmap_->SetBit(key_, 0, true, &bit); + bitmap_->SetBit(*ctx_, key_, 0, true, &bit); EXPECT_FALSE(bit); } uint32_t cnt = 0; - bitmap_->BitCount(key_, 0, 4 * 1024, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 4 * 1024, false, &cnt); EXPECT_EQ(cnt, 1); - bitmap_->BitCount(key_, 0, 0, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 0, false, &cnt); EXPECT_EQ(cnt, 1); - bitmap_->BitCount(key_, 0, -1, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, -1, false, &cnt); EXPECT_EQ(cnt, 1); - bitmap_->BitCount(key_, -1, -1, false, &cnt); + bitmap_->BitCount(*ctx_, key_, -1, -1, false, &cnt); EXPECT_EQ(cnt, 1); - bitmap_->BitCount(key_, 1, 1, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 1, 1, false, &cnt); EXPECT_EQ(cnt, 0); - bitmap_->BitCount(key_, -10000, -10000, false, &cnt); + bitmap_->BitCount(*ctx_, key_, -10000, -10000, false, &cnt); EXPECT_EQ(cnt, 1); { bool bit = false; - bitmap_->SetBit(key_, 5, true, &bit); + bitmap_->SetBit(*ctx_, key_, 5, true, &bit); EXPECT_FALSE(bit); } - bitmap_->BitCount(key_, -10000, -10000, false, &cnt); + bitmap_->BitCount(*ctx_, key_, -10000, -10000, false, &cnt); EXPECT_EQ(cnt, 2); { bool bit = false; - bitmap_->SetBit(key_, 8 * 1024 - 1, true, &bit); + bitmap_->SetBit(*ctx_, key_, 8 * 1024 - 1, true, &bit); EXPECT_FALSE(bit); - bitmap_->SetBit(key_, 8 * 1024, true, &bit); + bitmap_->SetBit(*ctx_, key_, 8 * 1024, true, &bit); EXPECT_FALSE(bit); } - bitmap_->BitCount(key_, 0, 1024, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 1024, false, &cnt); EXPECT_EQ(cnt, 4); - bitmap_->BitCount(key_, 0, 1023, false, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 1023, false, &cnt); EXPECT_EQ(cnt, 3); - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitCountBITOption) { std::set offsets = {0, 100, 1024 * 8, 1024 * 8 + 1, 3 * 1024 * 8, 3 * 1024 * 8 + 1}; for (const auto &offset : offsets) { bool bit = false; - bitmap_->SetBit(key_, offset, true, &bit); + bitmap_->SetBit(*ctx_, key_, offset, true, &bit); } for (uint32_t bit_offset = 0; bit_offset <= 3 * 1024 * 8 + 10; ++bit_offset) { uint32_t cnt = 0; - EXPECT_TRUE(bitmap_->BitCount(key_, bit_offset, bit_offset, true, &cnt).ok()); + EXPECT_TRUE(bitmap_->BitCount(*ctx_, key_, bit_offset, bit_offset, true, &cnt).ok()); if (offsets.count(bit_offset) > 0) { ASSERT_EQ(1, cnt) << "bit_offset: " << bit_offset; } else { @@ -142,25 +142,25 @@ TEST_P(RedisBitmapTest, BitCountBITOption) { } uint32_t cnt = 0; - bitmap_->BitCount(key_, 0, 4 * 1024 * 8, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 4 * 1024 * 8, true, &cnt); EXPECT_EQ(cnt, 6); - bitmap_->BitCount(key_, 0, -1, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, -1, true, &cnt); EXPECT_EQ(cnt, 6); - bitmap_->BitCount(key_, 0, 3 * 1024 * 8 + 1, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 3 * 1024 * 8 + 1, true, &cnt); EXPECT_EQ(cnt, 6); - bitmap_->BitCount(key_, 1, 3 * 1024 * 8 + 1, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 1, 3 * 1024 * 8 + 1, true, &cnt); EXPECT_EQ(cnt, 5); - bitmap_->BitCount(key_, 0, 0, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 0, true, &cnt); EXPECT_EQ(cnt, 1); - bitmap_->BitCount(key_, 0, 100, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 0, 100, true, &cnt); EXPECT_EQ(cnt, 2); - bitmap_->BitCount(key_, 100, 1024 * 8, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 100, 1024 * 8, true, &cnt); EXPECT_EQ(cnt, 2); - bitmap_->BitCount(key_, 100, 3 * 1024 * 8, true, &cnt); + bitmap_->BitCount(*ctx_, key_, 100, 3 * 1024 * 8, true, &cnt); EXPECT_EQ(cnt, 4); - bitmap_->BitCount(key_, -1, -1, true, &cnt); + bitmap_->BitCount(*ctx_, key_, -1, -1, true, &cnt); EXPECT_EQ(cnt, 0); // NOTICE: the min storage unit is byte, the result is the same as Redis. - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitPosClearBit) { @@ -179,58 +179,60 @@ TEST_P(RedisBitmapTest, BitPosClearBit) { /// /// String will set a empty string value when initializing, so, when first /// querying, it should return -1. - bitmap_->BitPos(key_, false, 0, -1, /*stop_given=*/false, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, 0, -1, /*stop_given=*/false, &pos, /*bit_index=*/false); if (i == 0 && !use_bitmap) { EXPECT_EQ(pos, -1); } else { EXPECT_EQ(pos, i); } - bitmap_->SetBit(key_, i, true, &old_bit); + bitmap_->SetBit(*ctx_, key_, i, true, &old_bit); EXPECT_FALSE(old_bit); + ctx_->RefreshLatestSnapshot(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitPosSetBit) { uint32_t offsets[] = {0, 123, 1024 * 8, 1024 * 8 + 16, 3 * 1024 * 8, 3 * 1024 * 8 + 16}; for (const auto &offset : offsets) { bool bit = false; - bitmap_->SetBit(key_, offset, true, &bit); + bitmap_->SetBit(*ctx_, key_, offset, true, &bit); } int64_t pos = 0; int start_indexes[] = {0, 1, 124, 1025, 1027, 3 * 1024 + 1}; for (size_t i = 0; i < sizeof(start_indexes) / sizeof(start_indexes[0]); i++) { - bitmap_->BitPos(key_, true, start_indexes[i], -1, true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, true, start_indexes[i], -1, true, &pos, /*bit_index=*/false); EXPECT_EQ(pos, offsets[i]); + ctx_->RefreshLatestSnapshot(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitPosNegative) { { bool bit = false; - bitmap_->SetBit(key_, 8 * 1024 - 1, true, &bit); + bitmap_->SetBit(*ctx_, key_, 8 * 1024 - 1, true, &bit); EXPECT_FALSE(bit); } int64_t pos = 0; // First bit is negative - bitmap_->BitPos(key_, false, 0, -1, true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, 0, -1, true, &pos, /*bit_index=*/false); EXPECT_EQ(0, pos); // 8 * 1024 - 1 bit is positive - bitmap_->BitPos(key_, true, 0, -1, true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, true, 0, -1, true, &pos, /*bit_index=*/false); EXPECT_EQ(8 * 1024 - 1, pos); // First bit in 1023 byte is negative - bitmap_->BitPos(key_, false, -1, -1, true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, -1, -1, true, &pos, /*bit_index=*/false); EXPECT_EQ(8 * 1023, pos); // Last Bit in 1023 byte is positive - bitmap_->BitPos(key_, true, -1, -1, true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, true, -1, -1, true, &pos, /*bit_index=*/false); EXPECT_EQ(8 * 1024 - 1, pos); // Large negative number will be normalized. - bitmap_->BitPos(key_, false, -10000, -10000, true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, -10000, -10000, true, &pos, /*bit_index=*/false); EXPECT_EQ(0, pos); - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } // When `stop_given` is true, even searching for 0, @@ -238,27 +240,27 @@ TEST_P(RedisBitmapTest, BitPosNegative) { TEST_P(RedisBitmapTest, BitPosStopGiven) { for (int i = 0; i < 8; ++i) { bool bit = true; - bitmap_->SetBit(key_, i, true, &bit); + bitmap_->SetBit(*ctx_, key_, i, true, &bit); EXPECT_FALSE(bit); } int64_t pos = 0; - bitmap_->BitPos(key_, false, 0, 0, /*stop_given=*/true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, 0, 0, /*stop_given=*/true, &pos, /*bit_index=*/false); EXPECT_EQ(-1, pos); - bitmap_->BitPos(key_, false, 0, 0, /*stop_given=*/false, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, 0, 0, /*stop_given=*/false, &pos, /*bit_index=*/false); EXPECT_EQ(8, pos); // Set a bit at 8 not affect that { bool bit = true; - bitmap_->SetBit(key_, 8, true, &bit); + bitmap_->SetBit(*ctx_, key_, 8, true, &bit); EXPECT_FALSE(bit); } - bitmap_->BitPos(key_, false, 0, 0, /*stop_given=*/true, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, 0, 0, /*stop_given=*/true, &pos, /*bit_index=*/false); EXPECT_EQ(-1, pos); - bitmap_->BitPos(key_, false, 0, 1, /*stop_given=*/false, &pos, /*bit_index=*/false); + bitmap_->BitPos(*ctx_, key_, false, 0, 1, /*stop_given=*/false, &pos, /*bit_index=*/false); EXPECT_EQ(9, pos); - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitfieldGetSetTest) { @@ -272,7 +274,7 @@ TEST_P(RedisBitmapTest, BitfieldGetSetTest) { op.offset = 114514; op.value = magic; - EXPECT_TRUE(bitmap_->Bitfield(key_, {op}, &rets).ok()); + EXPECT_TRUE(bitmap_->Bitfield(*ctx_, key_, {op}, &rets).ok()); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); @@ -282,13 +284,13 @@ TEST_P(RedisBitmapTest, BitfieldGetSetTest) { // bitfield is stored in big-endian. for (int i = 31; i != -1; --i) { - EXPECT_TRUE(bitmap_->Bitfield(key_, {op}, &rets).ok()); + EXPECT_TRUE(bitmap_->Bitfield(*ctx_, key_, {op}, &rets).ok()); EXPECT_EQ((magic >> i) & 1, rets[0].value()); rets.clear(); op.offset++; } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, UnsignedBitfieldTest) { @@ -304,20 +306,20 @@ TEST_P(RedisBitmapTest, UnsignedBitfieldTest) { op.offset = 8189; // the two bitmap segments divide the bitfield op.value = 0; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); for (uint64_t i = 1; i <= max; ++i) { op.value = int64_t(i); - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(i - 1, rets[0].value()); rets.clear(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, SignedBitfieldTest) { @@ -333,19 +335,20 @@ TEST_P(RedisBitmapTest, SignedBitfieldTest) { op.offset = 8189; // the two bitmap segments divide the bitfield op.value = min; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); for (int64_t i = min + 1; i <= max; ++i) { op.value = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(i - 1, rets[0].value()); rets.clear(); + ctx_->RefreshLatestSnapshot(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, SignedBitfieldWrapSetTest) { @@ -362,25 +365,25 @@ TEST_P(RedisBitmapTest, SignedBitfieldWrapSetTest) { op.offset = 0; op.value = max; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); op.type = BitfieldOperation::Type::kIncrBy; op.value = 1; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(min, rets[0].value()); rets.clear(); op.value = loopback; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(min, rets[0].value()); rets.clear(); - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, UnsignedBitfieldWrapSetTest) { @@ -397,25 +400,25 @@ TEST_P(RedisBitmapTest, UnsignedBitfieldWrapSetTest) { op.offset = 0; op.value = max; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); op.type = BitfieldOperation::Type::kIncrBy; op.value = 1; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); op.value = loopback; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, SignedBitfieldSatSetTest) { @@ -431,13 +434,13 @@ TEST_P(RedisBitmapTest, SignedBitfieldSatSetTest) { op.offset = 0; op.value = max * 2; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); op.type = BitfieldOperation::Type::kGet; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(max, rets[0].value()); rets.clear(); @@ -445,13 +448,14 @@ TEST_P(RedisBitmapTest, SignedBitfieldSatSetTest) { op.type = BitfieldOperation::Type::kIncrBy; for (int64_t i = 0; i <= max + 10; ++i) { op.value = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(max, rets[0].value()); rets.clear(); + ctx_->RefreshLatestSnapshot(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, UnsignedBitfieldSatSetTest) { @@ -468,13 +472,13 @@ TEST_P(RedisBitmapTest, UnsignedBitfieldSatSetTest) { op.offset = 0; op.value = max * 2; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); op.type = BitfieldOperation::Type::kGet; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(max, rets[0].value()); rets.clear(); @@ -482,13 +486,14 @@ TEST_P(RedisBitmapTest, UnsignedBitfieldSatSetTest) { op.type = BitfieldOperation::Type::kIncrBy; for (int64_t i = 0; i <= int64_t(max) + 10; ++i) { op.value = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(max, rets[0].value()); rets.clear(); + ctx_->RefreshLatestSnapshot(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, SignedBitfieldFailSetTest) { @@ -504,13 +509,13 @@ TEST_P(RedisBitmapTest, SignedBitfieldFailSetTest) { op.offset = 0; op.value = max * 2; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_FALSE(rets[0].has_value()); rets.clear(); op.value = max; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); @@ -518,13 +523,14 @@ TEST_P(RedisBitmapTest, SignedBitfieldFailSetTest) { op.type = BitfieldOperation::Type::kIncrBy; for (int64_t i = 1; i <= max; ++i) { op.value = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_FALSE(rets[0].has_value()); rets.clear(); + ctx_->RefreshLatestSnapshot(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, UnsignedBitfieldFailSetTest) { @@ -540,13 +546,13 @@ TEST_P(RedisBitmapTest, UnsignedBitfieldFailSetTest) { op.offset = 0; op.value = max * 2; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_FALSE(rets[0].has_value()); rets.clear(); op.value = max; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); @@ -554,13 +560,13 @@ TEST_P(RedisBitmapTest, UnsignedBitfieldFailSetTest) { op.type = BitfieldOperation::Type::kIncrBy; for (int64_t i = 1; i <= max; ++i) { op.value = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_FALSE(rets[0].has_value()); rets.clear(); } - auto s = bitmap_->Del(key_); + auto s = bitmap_->Del(*ctx_, key_); } TEST_P(RedisBitmapTest, BitfieldStringGetSetTest) { @@ -568,7 +574,7 @@ TEST_P(RedisBitmapTest, BitfieldStringGetSetTest) { GTEST_SKIP() << "skip bitmap test for BitfieldStringGetSetTest"; } std::string str = "dan yuan ren chang jiu, qian li gong chan juan."; - string_->Set(key_, str); + string_->Set(*ctx_, key_, str); std::vector> rets; @@ -579,7 +585,7 @@ TEST_P(RedisBitmapTest, BitfieldStringGetSetTest) { int i = 0; for (auto ch : str) { op.offset = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(ch, rets[0].value()); rets.clear(); @@ -588,7 +594,7 @@ TEST_P(RedisBitmapTest, BitfieldStringGetSetTest) { for (; static_cast(i) <= str.size() + 10; i += 8) { op.offset = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(0, rets[0].value()); rets.clear(); @@ -599,14 +605,14 @@ TEST_P(RedisBitmapTest, BitfieldStringGetSetTest) { for (int l = 0, r = static_cast(str.size() - 1); l < r; ++l, --r) { op.offset = l * 8; op.value = str[r]; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(str[l], rets[0].value()); rets.clear(); op.offset = r * 8; op.value = str[l]; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(str[r], rets[0].value()); rets.clear(); @@ -618,7 +624,7 @@ TEST_P(RedisBitmapTest, BitfieldStringGetSetTest) { op.type = BitfieldOperation::Type::kGet; for (auto ch : str) { op.offset = i; - bitmap_->Bitfield(key_, {op}, &rets); + bitmap_->Bitfield(*ctx_, key_, {op}, &rets); EXPECT_EQ(1, rets.size()); EXPECT_EQ(ch, rets[0].value()); rets.clear(); diff --git a/tests/cppunit/types/bloom_chain_test.cc b/tests/cppunit/types/bloom_chain_test.cc index f99df13a806..bf804801485 100644 --- a/tests/cppunit/types/bloom_chain_test.cc +++ b/tests/cppunit/types/bloom_chain_test.cc @@ -41,43 +41,43 @@ TEST_F(RedisBloomChainTest, Reserve) { double error_rate = 0.02; uint16_t expansion = 0; - auto s = sb_chain_->Reserve(key_, capacity, error_rate, expansion); + auto s = sb_chain_->Reserve(*ctx_, key_, capacity, error_rate, expansion); EXPECT_TRUE(s.ok()); // return false because the key is already exists; - s = sb_chain_->Reserve(key_, capacity, error_rate, expansion); + s = sb_chain_->Reserve(*ctx_, key_, capacity, error_rate, expansion); EXPECT_FALSE(s.ok()); EXPECT_EQ(s.ToString(), "Invalid argument: the key already exists"); - s = sb_chain_->Del(key_); + s = sb_chain_->Del(*ctx_, key_); } TEST_F(RedisBloomChainTest, BasicAddAndTest) { redis::BloomFilterAddResult ret = redis::BloomFilterAddResult::kOk; bool exist = false; - auto s = sb_chain_->Exists("no_exist_key", "test_item", &exist); + auto s = sb_chain_->Exists(*ctx_, "no_exist_key", "test_item", &exist); EXPECT_EQ(exist, 0); - s = sb_chain_->Del("no_exist_key"); + s = sb_chain_->Del(*ctx_, "no_exist_key"); std::string insert_items[] = {"item1", "item2", "item3", "item101", "item202", "303"}; for (const auto& insert_item : insert_items) { - s = sb_chain_->Add(key_, insert_item, &ret); + s = sb_chain_->Add(*ctx_, key_, insert_item, &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(ret, redis::BloomFilterAddResult::kOk); } for (const auto& insert_item : insert_items) { - s = sb_chain_->Exists(key_, insert_item, &exist); + s = sb_chain_->Exists(*ctx_, key_, insert_item, &exist); EXPECT_TRUE(s.ok()); EXPECT_EQ(exist, true); } std::string no_insert_items[] = {"item303", "item404", "1", "2", "3"}; for (const auto& no_insert_item : no_insert_items) { - s = sb_chain_->Exists(key_, no_insert_item, &exist); + s = sb_chain_->Exists(*ctx_, key_, no_insert_item, &exist); EXPECT_TRUE(s.ok()); EXPECT_EQ(exist, false); } - s = sb_chain_->Del(key_); + s = sb_chain_->Del(*ctx_, key_); } diff --git a/tests/cppunit/types/geo_test.cc b/tests/cppunit/types/geo_test.cc index 32041f0fc40..03803dc9192 100644 --- a/tests/cppunit/types/geo_test.cc +++ b/tests/cppunit/types/geo_test.cc @@ -53,16 +53,16 @@ TEST_F(RedisGeoTest, Add) { for (size_t i = 0; i < fields_.size(); i++) { geo_points.emplace_back(GeoPoint{longitudes_[i], latitudes_[i], fields_[i].ToString()}); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(fields_.size(), ret); std::vector geo_hashes; - geo_->Hash(key_, fields_, &geo_hashes); + geo_->Hash(*ctx_, key_, fields_, &geo_hashes); for (size_t i = 0; i < fields_.size(); i++) { EXPECT_EQ(geo_hashes[i], geo_hashes_[i]); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(ret, 0); - auto s = geo_->Del(key_); + auto s = geo_->Del(*ctx_, key_); } TEST_F(RedisGeoTest, Dist) { @@ -71,12 +71,12 @@ TEST_F(RedisGeoTest, Dist) { for (size_t i = 0; i < fields_.size(); i++) { geo_points.emplace_back(GeoPoint{longitudes_[i], latitudes_[i], fields_[i].ToString()}); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(fields_.size(), ret); double dist = 0.0; - geo_->Dist(key_, fields_[2], fields_[3], &dist); + geo_->Dist(*ctx_, key_, fields_[2], fields_[3], &dist); EXPECT_EQ(ceilf(dist), 194102); - auto s = geo_->Del(key_); + auto s = geo_->Del(*ctx_, key_); } TEST_F(RedisGeoTest, Hash) { @@ -85,14 +85,14 @@ TEST_F(RedisGeoTest, Hash) { for (size_t i = 0; i < fields_.size(); i++) { geo_points.emplace_back(GeoPoint{longitudes_[i], latitudes_[i], fields_[i].ToString()}); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); std::vector geo_hashes; - geo_->Hash(key_, fields_, &geo_hashes); + geo_->Hash(*ctx_, key_, fields_, &geo_hashes); for (size_t i = 0; i < fields_.size(); i++) { EXPECT_EQ(geo_hashes[i], geo_hashes_[i]); } - auto s = geo_->Del(key_); + auto s = geo_->Del(*ctx_, key_); } TEST_F(RedisGeoTest, Pos) { @@ -101,16 +101,16 @@ TEST_F(RedisGeoTest, Pos) { for (size_t i = 0; i < fields_.size(); i++) { geo_points.emplace_back(GeoPoint{longitudes_[i], latitudes_[i], fields_[i].ToString()}); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); std::map gps; - geo_->Pos(key_, fields_, &gps); + geo_->Pos(*ctx_, key_, fields_, &gps); for (size_t i = 0; i < fields_.size(); i++) { EXPECT_EQ(gps[fields_[i].ToString()].member, fields_[i].ToString()); EXPECT_EQ(geo_->EncodeGeoHash(gps[fields_[i].ToString()].longitude, gps[fields_[i].ToString()].latitude), geo_hashes_[i]); } - auto s = geo_->Del(key_); + auto s = geo_->Del(*ctx_, key_); } TEST_F(RedisGeoTest, Radius) { @@ -119,16 +119,16 @@ TEST_F(RedisGeoTest, Radius) { for (size_t i = 0; i < fields_.size(); i++) { geo_points.emplace_back(GeoPoint{longitudes_[i], latitudes_[i], fields_[i].ToString()}); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); std::vector gps; - geo_->Radius(key_, longitudes_[0], latitudes_[0], 100000000, 100, kSortASC, std::string(), false, 1, &gps); + geo_->Radius(*ctx_, key_, longitudes_[0], latitudes_[0], 100000000, 100, kSortASC, std::string(), false, 1, &gps); EXPECT_EQ(gps.size(), fields_.size()); for (size_t i = 0; i < gps.size(); i++) { EXPECT_EQ(gps[i].member, fields_[i].ToString()); EXPECT_EQ(geo_->EncodeGeoHash(gps[i].longitude, gps[i].latitude), geo_hashes_[i]); } - auto s = geo_->Del(key_); + auto s = geo_->Del(*ctx_, key_); } TEST_F(RedisGeoTest, RadiusByMember) { @@ -137,14 +137,14 @@ TEST_F(RedisGeoTest, RadiusByMember) { for (size_t i = 0; i < fields_.size(); i++) { geo_points.emplace_back(GeoPoint{longitudes_[i], latitudes_[i], fields_[i].ToString()}); } - geo_->Add(key_, &geo_points, &ret); + geo_->Add(*ctx_, key_, &geo_points, &ret); EXPECT_EQ(fields_.size(), ret); std::vector gps; - geo_->RadiusByMember(key_, fields_[0], 100000000, 100, kSortASC, std::string(), false, 1, &gps); + geo_->RadiusByMember(*ctx_, key_, fields_[0], 100000000, 100, kSortASC, std::string(), false, 1, &gps); EXPECT_EQ(gps.size(), fields_.size()); for (size_t i = 0; i < gps.size(); i++) { EXPECT_EQ(gps[i].member, fields_[i].ToString()); EXPECT_EQ(geo_->EncodeGeoHash(gps[i].longitude, gps[i].latitude), geo_hashes_[i]); } - auto s = geo_->Del(key_); + auto s = geo_->Del(*ctx_, key_); } diff --git a/tests/cppunit/types/hash_test.cc b/tests/cppunit/types/hash_test.cc index 5116f5ee338..d6fa542f138 100644 --- a/tests/cppunit/types/hash_test.cc +++ b/tests/cppunit/types/hash_test.cc @@ -48,18 +48,18 @@ class RedisHashTest : public TestBase { TEST_F(RedisHashTest, GetAndSet) { uint64_t ret = 0; for (size_t i = 0; i < fields_.size(); i++) { - auto s = hash_->Set(key_, fields_[i], values_[i], &ret); + auto s = hash_->Set(*ctx_, key_, fields_[i], values_[i], &ret); EXPECT_TRUE(s.ok() && ret == 1); } for (size_t i = 0; i < fields_.size(); i++) { std::string got; - auto s = hash_->Get(key_, fields_[i], &got); + auto s = hash_->Get(*ctx_, key_, fields_[i], &got); EXPECT_EQ(s.ToString(), "OK"); EXPECT_EQ(values_[i], got); } - auto s = hash_->Delete(key_, fields_, &ret); + auto s = hash_->Delete(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, MGetAndMSet) { @@ -68,22 +68,22 @@ TEST_F(RedisHashTest, MGetAndMSet) { for (size_t i = 0; i < fields_.size(); i++) { fvs.emplace_back(fields_[i].ToString(), values_[i].ToString()); } - auto s = hash_->MSet(key_, fvs, false, &ret); + auto s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && fvs.size() == ret); - s = hash_->MSet(key_, fvs, false, &ret); + s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(ret, 0); std::vector values; std::vector statuses; - s = hash_->MGet(key_, fields_, &values, &statuses); + s = hash_->MGet(*ctx_, key_, fields_, &values, &statuses); EXPECT_TRUE(s.ok()); for (size_t i = 0; i < fields_.size(); i++) { EXPECT_EQ(values[i], values_[i].ToString()); } - s = hash_->Delete(key_, fields_, &ret); + s = hash_->Delete(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(static_cast(fields_.size()), ret); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, MSetAndDeleteRepeated) { @@ -95,138 +95,138 @@ TEST_F(RedisHashTest, MSetAndDeleteRepeated) { } uint64_t ret = 0; - rocksdb::Status s = hash_->MSet(key_, fvs, false, &ret); + rocksdb::Status s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok() && static_cast(fvs.size() - 1) == ret); std::string got; - s = hash_->Get(key_, "f1", &got); + s = hash_->Get(*ctx_, key_, "f1", &got); EXPECT_EQ("v11", got); - s = hash_->Size(key_, &ret); + s = hash_->Size(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && ret == static_cast(fvs.size() - 1)); std::vector fields_to_delete{"f1", "f2", "f2"}; - s = hash_->Delete(key_, fields_to_delete, &ret); + s = hash_->Delete(*ctx_, key_, fields_to_delete, &ret); EXPECT_TRUE(s.ok() && ret == static_cast(fields_to_delete.size() - 1)); - s = hash_->Size(key_, &ret); + s = hash_->Size(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && ret == 1); - s = hash_->Get(key_, "f3", &got); + s = hash_->Get(*ctx_, key_, "f3", &got); EXPECT_EQ("v3", got); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, MSetSingleFieldAndNX) { uint64_t ret = 0; std::vector values = {{"field-one", "value-one"}}; - auto s = hash_->MSet(key_, values, true, &ret); + auto s = hash_->MSet(*ctx_, key_, values, true, &ret); EXPECT_TRUE(s.ok() && ret == 1); std::string field2 = "field-two"; std::string initial_value = "value-two"; - s = hash_->Set(key_, field2, initial_value, &ret); + s = hash_->Set(*ctx_, key_, field2, initial_value, &ret); EXPECT_TRUE(s.ok() && ret == 1); values = {{field2, "value-two-changed"}}; - s = hash_->MSet(key_, values, true, &ret); + s = hash_->MSet(*ctx_, key_, values, true, &ret); EXPECT_TRUE(s.ok() && ret == 0); std::string final_value; - s = hash_->Get(key_, field2, &final_value); + s = hash_->Get(*ctx_, key_, field2, &final_value); EXPECT_TRUE(s.ok()); EXPECT_EQ(initial_value, final_value); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, MSetMultipleFieldsAndNX) { uint64_t ret = 0; std::vector values = {{"field-one", "value-one"}, {"field-two", "value-two"}}; - auto s = hash_->MSet(key_, values, true, &ret); + auto s = hash_->MSet(*ctx_, key_, values, true, &ret); EXPECT_TRUE(s.ok() && ret == 2); values = {{"field-one", "value-one"}, {"field-two", "value-two-changed"}, {"field-three", "value-three"}}; - s = hash_->MSet(key_, values, true, &ret); + s = hash_->MSet(*ctx_, key_, values, true, &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(ret, 1); std::string value; - s = hash_->Get(key_, "field-one", &value); + s = hash_->Get(*ctx_, key_, "field-one", &value); EXPECT_TRUE(s.ok() && value == "value-one"); - s = hash_->Get(key_, "field-two", &value); + s = hash_->Get(*ctx_, key_, "field-two", &value); EXPECT_TRUE(s.ok() && value == "value-two"); - s = hash_->Get(key_, "field-three", &value); + s = hash_->Get(*ctx_, key_, "field-three", &value); EXPECT_TRUE(s.ok() && value == "value-three"); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, HGetAll) { uint64_t ret = 0; for (size_t i = 0; i < fields_.size(); i++) { - auto s = hash_->Set(key_, fields_[i], values_[i], &ret); + auto s = hash_->Set(*ctx_, key_, fields_[i], values_[i], &ret); EXPECT_TRUE(s.ok() && ret == 1); } std::vector fvs; - auto s = hash_->GetAll(key_, &fvs); + auto s = hash_->GetAll(*ctx_, key_, &fvs); EXPECT_TRUE(s.ok() && fvs.size() == fields_.size()); - s = hash_->Delete(key_, fields_, &ret); + s = hash_->Delete(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, HIncr) { int64_t value = 0; Slice field("hash-incrby-invalid-field"); for (int i = 0; i < 32; i++) { - auto s = hash_->IncrBy(key_, field, 1, &value); + auto s = hash_->IncrBy(*ctx_, key_, field, 1, &value); EXPECT_TRUE(s.ok()); } std::string bytes; - hash_->Get(key_, field, &bytes); + hash_->Get(*ctx_, key_, field, &bytes); auto parse_result = ParseInt(bytes, 10); if (!parse_result) { FAIL(); } EXPECT_EQ(32, *parse_result); - auto s = hash_->Del(key_); + auto s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, HIncrInvalid) { uint64_t ret = 0; int64_t value = 0; Slice field("hash-incrby-invalid-field"); - auto s = hash_->IncrBy(key_, field, 1, &value); + auto s = hash_->IncrBy(*ctx_, key_, field, 1, &value); EXPECT_TRUE(s.ok() && value == 1); - s = hash_->IncrBy(key_, field, LLONG_MAX, &value); + s = hash_->IncrBy(*ctx_, key_, field, LLONG_MAX, &value); EXPECT_TRUE(s.IsInvalidArgument()); - hash_->Set(key_, field, "abc", &ret); - s = hash_->IncrBy(key_, field, 1, &value); + hash_->Set(*ctx_, key_, field, "abc", &ret); + s = hash_->IncrBy(*ctx_, key_, field, 1, &value); EXPECT_TRUE(s.IsInvalidArgument()); - hash_->Set(key_, field, "-1", &ret); - s = hash_->IncrBy(key_, field, -1, &value); + hash_->Set(*ctx_, key_, field, "-1", &ret); + s = hash_->IncrBy(*ctx_, key_, field, -1, &value); EXPECT_TRUE(s.ok()); - s = hash_->IncrBy(key_, field, LLONG_MIN, &value); + s = hash_->IncrBy(*ctx_, key_, field, LLONG_MIN, &value); EXPECT_TRUE(s.IsInvalidArgument()); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, HIncrByFloat) { double value = 0.0; Slice field("hash-incrbyfloat-invalid-field"); for (int i = 0; i < 32; i++) { - auto s = hash_->IncrByFloat(key_, field, 1.2, &value); + auto s = hash_->IncrByFloat(*ctx_, key_, field, 1.2, &value); EXPECT_TRUE(s.ok()); } std::string bytes; - hash_->Get(key_, field, &bytes); + hash_->Get(*ctx_, key_, field, &bytes); value = std::stof(bytes); EXPECT_FLOAT_EQ(32 * 1.2, value); - auto s = hash_->Del(key_); + auto s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, HRangeByLex) { @@ -244,9 +244,9 @@ TEST_F(RedisHashTest, HRangeByLex) { std::vector tmp(fvs); for (size_t i = 0; i < 100; i++) { std::shuffle(tmp.begin(), tmp.end(), g); - auto s = hash_->MSet(key_, tmp, false, &ret); + auto s = hash_->MSet(*ctx_, key_, tmp, false, &ret); EXPECT_TRUE(s.ok() && tmp.size() == ret); - s = hash_->MSet(key_, fvs, false, &ret); + s = hash_->MSet(*ctx_, key_, fvs, false, &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(ret, 0); std::vector result; @@ -255,17 +255,17 @@ TEST_F(RedisHashTest, HRangeByLex) { spec.count = INT_MAX; spec.min = "key0"; spec.max = "key3"; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(4, result.size()); EXPECT_EQ("key0", result[0].field); EXPECT_EQ("key1", result[1].field); EXPECT_EQ("key2", result[2].field); EXPECT_EQ("key3", result[3].field); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } - auto s = hash_->MSet(key_, tmp, false, &ret); + auto s = hash_->MSet(*ctx_, key_, tmp, false, &ret); EXPECT_TRUE(s.ok() && tmp.size() == ret); // use offset and count std::vector result; @@ -275,7 +275,7 @@ TEST_F(RedisHashTest, HRangeByLex) { spec.min = "key0"; spec.max = "key3"; spec.offset = 1; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(3, result.size()); EXPECT_EQ("key1", result[0].field); @@ -284,27 +284,27 @@ TEST_F(RedisHashTest, HRangeByLex) { spec.offset = 1; spec.count = 1; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(1, result.size()); EXPECT_EQ("key1", result[0].field); spec.offset = 0; spec.count = 0; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(0, result.size()); spec.offset = 1000; spec.count = 1000; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(0, result.size()); // exclusive range spec.offset = 0; spec.count = -1; spec.minex = true; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(3, result.size()); EXPECT_EQ("key1", result[0].field); @@ -315,7 +315,7 @@ TEST_F(RedisHashTest, HRangeByLex) { spec.count = -1; spec.maxex = true; spec.minex = false; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(3, result.size()); EXPECT_EQ("key0", result[0].field); @@ -326,7 +326,7 @@ TEST_F(RedisHashTest, HRangeByLex) { spec.count = -1; spec.maxex = true; spec.minex = true; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(2, result.size()); EXPECT_EQ("key1", result[0].field); @@ -339,14 +339,14 @@ TEST_F(RedisHashTest, HRangeByLex) { spec.max = "+"; spec.max_infinite = true; spec.reversed = true; - s = hash_->RangeByLex(key_, spec, &result); + s = hash_->RangeByLex(*ctx_, key_, spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(4 + 26, result.size()); EXPECT_EQ("key3", result[0].field); EXPECT_EQ("key2", result[1].field); EXPECT_EQ("key1", result[2].field); EXPECT_EQ("key0", result[3].field); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } TEST_F(RedisHashTest, HRangeByLexNonExistingKey) { @@ -356,7 +356,7 @@ TEST_F(RedisHashTest, HRangeByLexNonExistingKey) { spec.count = INT_MAX; spec.min = "any-start-key"; spec.max = "any-end-key"; - auto s = hash_->RangeByLex("non-existing-key", spec, &result); + auto s = hash_->RangeByLex(*ctx_, "non-existing-key", spec, &result); EXPECT_TRUE(s.ok()); EXPECT_EQ(result.size(), 0); } @@ -364,30 +364,30 @@ TEST_F(RedisHashTest, HRangeByLexNonExistingKey) { TEST_F(RedisHashTest, HRandField) { uint64_t ret = 0; for (size_t i = 0; i < fields_.size(); i++) { - auto s = hash_->Set(key_, fields_[i], values_[i], &ret); + auto s = hash_->Set(*ctx_, key_, fields_[i], values_[i], &ret); EXPECT_TRUE(s.ok() && ret == 1); } auto size = static_cast(fields_.size()); std::vector fvs; // Case 1: Negative count, randomly select elements fvs.clear(); - auto s = hash_->RandField(key_, -(size + 10), &fvs); + auto s = hash_->RandField(*ctx_, key_, -(size + 10), &fvs); EXPECT_TRUE(s.ok() && fvs.size() == (fields_.size() + 10)); // Case 2: Requested count is greater than or equal to the number of elements inside the hash fvs.clear(); - s = hash_->RandField(key_, size + 1, &fvs); + s = hash_->RandField(*ctx_, key_, size + 1, &fvs); EXPECT_TRUE(s.ok() && fvs.size() == fields_.size()); // Case 3: Requested count is less than the number of elements inside the hash fvs.clear(); - s = hash_->RandField(key_, size - 1, &fvs); + s = hash_->RandField(*ctx_, key_, size - 1, &fvs); EXPECT_TRUE(s.ok() && fvs.size() == fields_.size() - 1); // hrandfield key 0 fvs.clear(); - s = hash_->RandField(key_, 0, &fvs); + s = hash_->RandField(*ctx_, key_, 0, &fvs); EXPECT_TRUE(s.ok() && fvs.size() == 0); - s = hash_->Del(key_); + s = hash_->Del(*ctx_, key_); } diff --git a/tests/cppunit/types/hyperloglog_test.cc b/tests/cppunit/types/hyperloglog_test.cc index 234b688e8ba..02a52383ac3 100644 --- a/tests/cppunit/types/hyperloglog_test.cc +++ b/tests/cppunit/types/hyperloglog_test.cc @@ -34,17 +34,17 @@ class RedisHyperLogLogTest : public TestBase { void SetUp() override { TestBase::SetUp(); - [[maybe_unused]] auto s = hll_->Del("hll"); + [[maybe_unused]] auto s = hll_->Del(*ctx_, "hll"); for (int x = 1; x <= 3; x++) { - s = hll_->Del("hll" + std::to_string(x)); + s = hll_->Del(*ctx_, "hll" + std::to_string(x)); } } void TearDown() override { TestBase::SetUp(); - [[maybe_unused]] auto s = hll_->Del("hll"); + [[maybe_unused]] auto s = hll_->Del(*ctx_, "hll"); for (int x = 1; x <= 3; x++) { - s = hll_->Del("hll" + std::to_string(x)); + s = hll_->Del(*ctx_, "hll" + std::to_string(x)); } } @@ -62,88 +62,88 @@ class RedisHyperLogLogTest : public TestBase { TEST_F(RedisHyperLogLogTest, PFADD) { uint64_t ret = 0; - ASSERT_TRUE(hll_->Add("hll", {}, &ret).ok() && ret == 0); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", {}, &ret).ok() && ret == 0); // Approximated cardinality after creation is zero - ASSERT_TRUE(hll_->Count("hll", &ret).ok() && ret == 0); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok() && ret == 0); // PFADD returns 1 when at least 1 reg was modified - ASSERT_TRUE(hll_->Add("hll", computeHashes({"a", "b", "c"}), &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", computeHashes({"a", "b", "c"}), &ret).ok()); ASSERT_EQ(1, ret); - ASSERT_TRUE(hll_->Count("hll", &ret).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok()); ASSERT_EQ(3, ret); // PFADD returns 0 when no reg was modified - ASSERT_TRUE(hll_->Add("hll", computeHashes({"a", "b", "c"}), &ret).ok() && ret == 0); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", computeHashes({"a", "b", "c"}), &ret).ok() && ret == 0); // PFADD works with empty string - ASSERT_TRUE(hll_->Add("hll", computeHashes({""}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", computeHashes({""}), &ret).ok() && ret == 1); // PFADD works with similar hash, which is likely to be in the same bucket - ASSERT_TRUE(hll_->Add("hll", {1, 2, 3, 2, 1}, &ret).ok() && ret == 1); - ASSERT_TRUE(hll_->Count("hll", &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", {1, 2, 3, 2, 1}, &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok()); ASSERT_EQ(7, ret); } TEST_F(RedisHyperLogLogTest, PFCOUNT_returns_approximated_cardinality_of_set) { uint64_t ret = 0; // pf add "1" to "5" - ASSERT_TRUE(hll_->Add("hll", computeHashes({"1", "2", "3", "4", "5"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", computeHashes({"1", "2", "3", "4", "5"}), &ret).ok() && ret == 1); // pf count is 5 - ASSERT_TRUE(hll_->Count("hll", &ret).ok() && ret == 5); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok() && ret == 5); // pf add "6" to "10" - ASSERT_TRUE(hll_->Add("hll", computeHashes({"6", "7", "8", "8", "9", "10"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Add(*ctx_, "hll", computeHashes({"6", "7", "8", "8", "9", "10"}), &ret).ok() && ret == 1); // pf count is 10 - ASSERT_TRUE(hll_->Count("hll", &ret).ok() && ret == 10); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok() && ret == 10); } TEST_F(RedisHyperLogLogTest, PFMERGE_results_on_the_cardinality_of_union_of_sets) { uint64_t ret = 0; // pf add hll1 a b c - ASSERT_TRUE(hll_->Add("hll1", computeHashes({"a", "b", "c"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Add(*ctx_, "hll1", computeHashes({"a", "b", "c"}), &ret).ok() && ret == 1); // pf add hll2 b c d - ASSERT_TRUE(hll_->Add("hll2", computeHashes({"b", "c", "d"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Add(*ctx_, "hll2", computeHashes({"b", "c", "d"}), &ret).ok() && ret == 1); // pf add hll3 c d e - ASSERT_TRUE(hll_->Add("hll3", computeHashes({"c", "d", "e"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Add(*ctx_, "hll3", computeHashes({"c", "d", "e"}), &ret).ok() && ret == 1); // pf merge hll hll1 hll2 hll3 - ASSERT_TRUE(hll_->Merge("hll", {"hll1", "hll2", "hll3"}).ok()); + ASSERT_TRUE(hll_->Merge(*ctx_, "hll", {"hll1", "hll2", "hll3"}).ok()); // pf count hll is 5 - ASSERT_TRUE(hll_->Count("hll", &ret).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok()); ASSERT_EQ(5, ret); } TEST_F(RedisHyperLogLogTest, PFCOUNT_multiple) { uint64_t ret = 0; - ASSERT_TRUE(hll_->CountMultiple({"hll1", "hll2", "hll3"}, &ret).ok()); + ASSERT_TRUE(hll_->CountMultiple(*ctx_, {"hll1", "hll2", "hll3"}, &ret).ok()); ASSERT_EQ(0, ret); // pf add hll1 a b c - ASSERT_TRUE(hll_->Add("hll1", computeHashes({"a", "b", "c"}), &ret).ok() && ret == 1); - ASSERT_TRUE(hll_->Count("hll1", &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll1", computeHashes({"a", "b", "c"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->Count(*ctx_, "hll1", &ret).ok()); ASSERT_EQ(3, ret); - ASSERT_TRUE(hll_->CountMultiple({"hll1", "hll2", "hll3"}, &ret).ok()); + ASSERT_TRUE(hll_->CountMultiple(*ctx_, {"hll1", "hll2", "hll3"}, &ret).ok()); ASSERT_EQ(3, ret); // pf add hll2 b c d - ASSERT_TRUE(hll_->Add("hll2", computeHashes({"b", "c", "d"}), &ret).ok() && ret == 1); - ASSERT_TRUE(hll_->CountMultiple({"hll1", "hll2", "hll3"}, &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll2", computeHashes({"b", "c", "d"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->CountMultiple(*ctx_, {"hll1", "hll2", "hll3"}, &ret).ok()); ASSERT_EQ(4, ret); // pf add hll3 c d e - ASSERT_TRUE(hll_->Add("hll3", computeHashes({"c", "d", "e"}), &ret).ok() && ret == 1); - ASSERT_TRUE(hll_->CountMultiple({"hll1", "hll2", "hll3"}, &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll3", computeHashes({"c", "d", "e"}), &ret).ok() && ret == 1); + ASSERT_TRUE(hll_->CountMultiple(*ctx_, {"hll1", "hll2", "hll3"}, &ret).ok()); ASSERT_EQ(5, ret); // pf merge hll hll1 hll2 hll3 - ASSERT_TRUE(hll_->Merge("hll", {"hll1", "hll2", "hll3"}).ok()); + ASSERT_TRUE(hll_->Merge(*ctx_, "hll", {"hll1", "hll2", "hll3"}).ok()); // pf count hll is 5 - ASSERT_TRUE(hll_->Count("hll", &ret).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll", &ret).ok()); ASSERT_EQ(5, ret); - ASSERT_TRUE(hll_->CountMultiple({"hll1", "hll2", "hll3", "hll"}, &ret).ok()); + ASSERT_TRUE(hll_->CountMultiple(*ctx_, {"hll1", "hll2", "hll3", "hll"}, &ret).ok()); ASSERT_EQ(5, ret); } TEST_F(RedisHyperLogLogTest, PFCOUNT_multiple_keys_merge_returns_cardinality_of_union_1) { for (int x = 1; x < 1000; x++) { uint64_t ret = 0; - ASSERT_TRUE(hll_->Add("hll0", computeHashes({"foo-" + std::to_string(x)}), &ret).ok()); - ASSERT_TRUE(hll_->Add("hll1", computeHashes({"bar-" + std::to_string(x)}), &ret).ok()); - ASSERT_TRUE(hll_->Add("hll2", computeHashes({"zap-" + std::to_string(x)}), &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll0", computeHashes({"foo-" + std::to_string(x)}), &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll1", computeHashes({"bar-" + std::to_string(x)}), &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll2", computeHashes({"zap-" + std::to_string(x)}), &ret).ok()); std::vector cards(3); - ASSERT_TRUE(hll_->Count("hll0", &cards[0]).ok()); - ASSERT_TRUE(hll_->Count("hll1", &cards[1]).ok()); - ASSERT_TRUE(hll_->Count("hll2", &cards[2]).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll0", &cards[0]).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll1", &cards[1]).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll2", &cards[2]).ok()); auto card = static_cast(cards[0] + cards[1] + cards[2]); double realcard = x * 3; // assert the ABS of 'card' and 'realcart' is within 5% of the cardinality @@ -160,14 +160,14 @@ TEST_F(RedisHyperLogLogTest, PFCOUNT_multiple_keys_merge_returns_cardinality_of_ for (auto j = 0; j < 3; j++) { uint64_t ret = 0; int rint = std::rand() % 20000; - ASSERT_TRUE(hll_->Add("hll" + std::to_string(j), computeHashes({std::to_string(rint)}), &ret).ok()); + ASSERT_TRUE(hll_->Add(*ctx_, "hll" + std::to_string(j), computeHashes({std::to_string(rint)}), &ret).ok()); realcard_vec.push_back(rint); } } std::vector cards(3); - ASSERT_TRUE(hll_->Count("hll0", &cards[0]).ok()); - ASSERT_TRUE(hll_->Count("hll1", &cards[1]).ok()); - ASSERT_TRUE(hll_->Count("hll2", &cards[2]).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll0", &cards[0]).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll1", &cards[1]).ok()); + ASSERT_TRUE(hll_->Count(*ctx_, "hll2", &cards[2]).ok()); auto card = static_cast(cards[0] + cards[1] + cards[2]); auto realcard = static_cast(realcard_vec.size()); double left = std::abs(card - realcard); diff --git a/tests/cppunit/types/json_test.cc b/tests/cppunit/types/json_test.cc index 30d6f60ef53..893939e48e8 100644 --- a/tests/cppunit/types/json_test.cc +++ b/tests/cppunit/types/json_test.cc @@ -41,93 +41,93 @@ class RedisJsonTest : public TestBase { using ::testing::MatchesRegex; TEST_F(RedisJsonTest, Set) { - ASSERT_THAT(json_->Set(key_, "$[0]", "1").ToString(), MatchesRegex(".*created at the root")); - ASSERT_THAT(json_->Set(key_, "$.a", "1").ToString(), MatchesRegex(".*created at the root")); + ASSERT_THAT(json_->Set(*ctx_, key_, "$[0]", "1").ToString(), MatchesRegex(".*created at the root")); + ASSERT_THAT(json_->Set(*ctx_, key_, "$.a", "1").ToString(), MatchesRegex(".*created at the root")); - ASSERT_THAT(json_->Set(key_, "$", "invalid").ToString(), MatchesRegex(".*syntax_error.*")); - ASSERT_THAT(json_->Set(key_, "$", "{").ToString(), MatchesRegex(".*Unexpected end of file.*")); + ASSERT_THAT(json_->Set(*ctx_, key_, "$", "invalid").ToString(), MatchesRegex(".*syntax_error.*")); + ASSERT_THAT(json_->Set(*ctx_, key_, "$", "{").ToString(), MatchesRegex(".*Unexpected end of file.*")); - ASSERT_TRUE(json_->Set(key_, "$", " \t{\n } ").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", " \t{\n } ").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{}"); - ASSERT_TRUE(json_->Set(key_, "$", "1").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "1").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "1"); - ASSERT_TRUE(json_->Set(key_, "$", "[1, 2, 3]").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "[1, 2, 3]").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "[1,2,3]"); - ASSERT_TRUE(json_->Set(key_, "$[1]", "233").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$[1]", "233").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "[1,233,3]"); - ASSERT_TRUE(json_->Set(key_, "$", "[[1,2],[3,4],[5,6]]").ok()); - ASSERT_TRUE(json_->Set(key_, "$[*][1]", R"("x")").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "[[1,2],[3,4],[5,6]]").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$[*][1]", R"("x")").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([[1,"x"],[3,"x"],[5,"x"]])"); - ASSERT_TRUE(json_->Set(key_, "$", R"({"x":1,"y":2, "z":3})").ok()); - ASSERT_TRUE(json_->Set(key_, "$.x", "[1,2,3]").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"x":1,"y":2, "z":3})").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$.x", "[1,2,3]").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":[1,2,3],"y":2,"z":3})"); - ASSERT_TRUE(json_->Set(key_, "$.y", R"({"a":"xxx","x":2})").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$.y", R"({"a":"xxx","x":2})").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":[1,2,3],"y":{"a":"xxx","x":2},"z":3})"); - ASSERT_TRUE(json_->Set(key_, "$..x", "true").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$..x", "true").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":true,"y":{"a":"xxx","x":true},"z":3})"); - ASSERT_THAT(json_->Set(key_, "...", "1").ToString(), MatchesRegex("Invalid.*")); - ASSERT_THAT(json_->Set(key_, "[", "1").ToString(), MatchesRegex("Invalid.*")); + ASSERT_THAT(json_->Set(*ctx_, key_, "...", "1").ToString(), MatchesRegex("Invalid.*")); + ASSERT_THAT(json_->Set(*ctx_, key_, "[", "1").ToString(), MatchesRegex("Invalid.*")); - ASSERT_TRUE(json_->Set(key_, "$", "[[1,2],[[5,6],4]] ").ok()); - ASSERT_TRUE(json_->Set(key_, "$..[0]", "{}").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "[[1,2],[[5,6],4]] ").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$..[0]", "{}").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([{},[{},4]])"); size_t result = 0; - ASSERT_TRUE(json_->Del(key_, "$", &result).ok()); - ASSERT_TRUE(json_->Set(key_, "$", "[{ }, [ ]]").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$", &result).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "[{ }, [ ]]").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "[{},[]]"); - ASSERT_THAT(json_->Set(key_, "$[1]", "invalid").ToString(), MatchesRegex(".*syntax_error.*")); - ASSERT_TRUE(json_->Del(key_, "$", &result).ok()); + ASSERT_THAT(json_->Set(*ctx_, key_, "$[1]", "invalid").ToString(), MatchesRegex(".*syntax_error.*")); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$", &result).ok()); - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":1})").ok()); - ASSERT_TRUE(json_->Set(key_, "$.b", "2").ok()); - ASSERT_TRUE(json_->Set(key_, "$.c", R"({"x":3})").ok()); - ASSERT_TRUE(json_->Set(key_, "$.c.y", "4").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":1})").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$.b", "2").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$.c", R"({"x":3})").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$.c.y", "4").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.value, jsoncons::json::parse(R"({"a":1,"b":2,"c":{"x":3,"y":4}})")); } TEST_F(RedisJsonTest, Get) { - ASSERT_TRUE(json_->Set(key_, "$", R"({"x":[1,2,{"z":3}],"y":[]})").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"x":[1,2,{"z":3}],"y":[]})").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":[1,2,{"z":3}],"y":[]})"); - ASSERT_TRUE(json_->Get(key_, {"$"}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([{"x":[1,2,{"z":3}],"y":[]}])"); - ASSERT_TRUE(json_->Get(key_, {"$.y"}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$.y"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([[]])"); - ASSERT_TRUE(json_->Get(key_, {"$.y[0]"}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$.y[0]"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([])"); - ASSERT_TRUE(json_->Get(key_, {"$.z"}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$.z"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([])"); - ASSERT_THAT(json_->Get(key_, {"[[["}, &json_val_).ToString(), MatchesRegex("Invalid.*")); + ASSERT_THAT(json_->Get(*ctx_, key_, {"[[["}, &json_val_).ToString(), MatchesRegex("Invalid.*")); - ASSERT_TRUE(json_->Set(key_, "$", R"([[[1,2],[3]],[4,5]])").ok()); - ASSERT_TRUE(json_->Get(key_, {"$..[0]"}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"([[[1,2],[3]],[4,5]])").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$..[0]"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"([[[1,2],[3]],[1,2],1,3,4])"); - ASSERT_TRUE(json_->Get(key_, {"$[0][1][0]", "$[1][1]"}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$[0][1][0]", "$[1][1]"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"$[0][1][0]":[3],"$[1][1]":[5]})"); - ASSERT_TRUE(json_->Set(key_, "$", R"({"x":{"y":1},"y":[2,{"z":3}],"z":{"a":{"x":4}}})").ok()); - ASSERT_TRUE(json_->Get(key_, {"$..x", "$..y", "$..z"}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"x":{"y":1},"y":[2,{"z":3}],"z":{"a":{"x":4}}})").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {"$..x", "$..y", "$..z"}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"$..x":[{"y":1},4],"$..y":[[2,{"z":3}],1],"$..z":[{"a":{"x":4}},3]})"); } @@ -152,40 +152,40 @@ TEST_F(RedisJsonTest, Print) { TEST_F(RedisJsonTest, ArrAppend) { Optionals res; - ASSERT_FALSE(json_->ArrAppend(key_, "$", {"1"}, &res).ok()); + ASSERT_FALSE(json_->ArrAppend(*ctx_, key_, "$", {"1"}, &res).ok()); - ASSERT_TRUE(json_->Set(key_, "$", R"({"x":1,"y":[]})").ok()); - ASSERT_TRUE(json_->ArrAppend(key_, "$.x", {"1"}, &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"x":1,"y":[]})").ok()); + ASSERT_TRUE(json_->ArrAppend(*ctx_, key_, "$.x", {"1"}, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], std::nullopt); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":1,"y":[]})"); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"x":[1,2,{"z":3}],"y":[]})").ok()); - ASSERT_TRUE(json_->ArrAppend(key_, "$.x", {"1"}, &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"x":[1,2,{"z":3}],"y":[]})").ok()); + ASSERT_TRUE(json_->ArrAppend(*ctx_, key_, "$.x", {"1"}, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 4); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":[1,2,{"z":3},1],"y":[]})"); res.clear(); - ASSERT_TRUE(json_->ArrAppend(key_, "$..y", {"1", "2", "3"}, &res).ok()); + ASSERT_TRUE(json_->ArrAppend(*ctx_, key_, "$..y", {"1", "2", "3"}, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 3); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":[1,2,{"z":3},1],"y":[1,2,3]})"); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$.x[2]", R"({"x":[1,2,{"z":3,"y":[]}],"y":[{"y":1}]})").ok()); - ASSERT_TRUE(json_->ArrAppend(key_, "$..y", {"1", "2", "3"}, &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$.x[2]", R"({"x":[1,2,{"z":3,"y":[]}],"y":[{"y":1}]})").ok()); + ASSERT_TRUE(json_->ArrAppend(*ctx_, key_, "$..y", {"1", "2", "3"}, &res).ok()); ASSERT_EQ(res.size(), 4); std::sort(res.begin(), res.end()); ASSERT_EQ(res[0], std::nullopt); ASSERT_EQ(res[1], 3); ASSERT_EQ(res[2], 4); ASSERT_EQ(res[3], 6); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"x":[1,2,{"x":[1,2,{"y":[1,2,3],"z":3}],"y":[{"y":1},1,2,3]},1],"y":[1,2,3,1,2,3]})"); res.clear(); @@ -194,35 +194,35 @@ TEST_F(RedisJsonTest, ArrAppend) { TEST_F(RedisJsonTest, Merge) { bool result = false; - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":2})").ok()); - ASSERT_TRUE(json_->Merge(key_, "$.a", "3", result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":2})").ok()); + ASSERT_TRUE(json_->Merge(*ctx_, key_, "$.a", "3", result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{\"a\":3}"); ASSERT_EQ(result, true); - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":2})").ok()); - ASSERT_TRUE(json_->Merge(key_, "$.b", "3", result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":2})").ok()); + ASSERT_TRUE(json_->Merge(*ctx_, key_, "$.b", "3", result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{\"a\":2,\"b\":3}"); ASSERT_EQ(result, true); - ASSERT_TRUE(json_->Set(key_, "$", R"({"v": {"b": "cc"}})").ok()); - ASSERT_TRUE(json_->Merge(key_, "$.v.b", "null", result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"v": {"b": "cc"}})").ok()); + ASSERT_TRUE(json_->Merge(*ctx_, key_, "$.v.b", "null", result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{\"v\":{}}"); ASSERT_EQ(result, true); - ASSERT_TRUE(json_->Set(key_, "$", R"({"arr":[2,4,6,8]})").ok()); - ASSERT_TRUE(json_->Merge(key_, "$.arr", "[10,12]", result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"arr":[2,4,6,8]})").ok()); + ASSERT_TRUE(json_->Merge(*ctx_, key_, "$.arr", "[10,12]", result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{\"arr\":[10,12]}"); ASSERT_EQ(result, true); - ASSERT_TRUE(json_->Set(key_, "$", R"({"f1": {"a":1}, "f2":{"a":2}})").ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"f1": {"a":1}, "f2":{"a":2}})").ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{\"f1\":{\"a\":1},\"f2\":{\"a\":2}}"); - ASSERT_TRUE(json_->Merge(key_, "$", R"({"f1": null, "f2":{"a":3, "b":4}, "f3":[2,4,6]})", result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Merge(*ctx_, key_, "$", R"({"f1": null, "f2":{"a":3, "b":4}, "f3":[2,4,6]})", result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{\"f2\":{\"a\":3,\"b\":4},\"f3\":[2,4,6]}"); ASSERT_EQ(result, true); } @@ -232,145 +232,146 @@ TEST_F(RedisJsonTest, Clear) { ASSERT_TRUE( json_ - ->Set(key_, "$", + ->Set(*ctx_, key_, "$", R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})") .ok()); - ASSERT_TRUE(json_->Clear(key_, "$", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Clear(*ctx_, key_, "$", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "{}"); ASSERT_EQ(result, 1); ASSERT_TRUE( json_ - ->Set(key_, "$", + ->Set(*ctx_, key_, "$", R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})") .ok()); - ASSERT_TRUE(json_->Clear(key_, "$.obj", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Clear(*ctx_, key_, "$.obj", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"arr":[1,2,3],"bool":true,"float":3.14,"int":42,"obj":{},"str":"foo"})"); ASSERT_EQ(result, 1); - ASSERT_TRUE(json_->Clear(key_, "$.arr", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Clear(*ctx_, key_, "$.arr", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"arr":[],"bool":true,"float":3.14,"int":42,"obj":{},"str":"foo"})"); ASSERT_EQ(result, 1); ASSERT_TRUE( json_ - ->Set(key_, "$", + ->Set(*ctx_, key_, "$", R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})") .ok()); - ASSERT_TRUE(json_->Clear(key_, "$.*", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Clear(*ctx_, key_, "$.*", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"arr":[],"bool":true,"float":0,"int":0,"obj":{},"str":"foo"})"); ASSERT_EQ(result, 4); - ASSERT_TRUE(json_->Clear(key_, "$.some", &result).ok()); + ASSERT_TRUE(json_->Clear(*ctx_, key_, "$.some", &result).ok()); ASSERT_EQ(result, 0); } TEST_F(RedisJsonTest, ArrLen) { - ASSERT_TRUE( - json_->Set(key_, "$", R"({"a1":[1,2],"a2":[[1,5,7],[8],[9]],"i":1,"d":1.0,"s":"string","o":{"a3":[1,1,1]}})") - .ok()); + ASSERT_TRUE(json_ + ->Set(*ctx_, key_, "$", + R"({"a1":[1,2],"a2":[[1,5,7],[8],[9]],"i":1,"d":1.0,"s":"string","o":{"a3":[1,1,1]}})") + .ok()); // 1. simple array Optionals res; - ASSERT_TRUE(json_->ArrLen(key_, "$.a1", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.a1", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 2); res.clear(); // 2. nested array - ASSERT_TRUE(json_->ArrLen(key_, "$.a2", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.a2", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 3); res.clear(); - ASSERT_TRUE(json_->ArrLen(key_, "$.a2[0]", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.a2[0]", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 3); res.clear(); // 3.non-array type - ASSERT_TRUE(json_->ArrLen(key_, "$.i", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.i", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], std::nullopt); res.clear(); - ASSERT_TRUE(json_->ArrLen(key_, "$.d", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.d", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], std::nullopt); res.clear(); - ASSERT_TRUE(json_->ArrLen(key_, "$.s", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.s", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], std::nullopt); res.clear(); // 4. object - ASSERT_TRUE(json_->ArrLen(key_, "$.o", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.o", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], std::nullopt); res.clear(); - ASSERT_TRUE(json_->ArrLen(key_, "$.o.a3", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.o.a3", &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 3); res.clear(); // 5. key/path is not found - ASSERT_FALSE(json_->ArrLen("not_exists", "$.*", &res).ok()); - ASSERT_TRUE(json_->ArrLen(key_, "$.not_exists", &res).ok()); + ASSERT_FALSE(json_->ArrLen(*ctx_, "not_exists", "$.*", &res).ok()); + ASSERT_TRUE(json_->ArrLen(*ctx_, key_, "$.not_exists", &res).ok()); ASSERT_TRUE(res.empty()); } TEST_F(RedisJsonTest, Toggle) { Optionals res; - ASSERT_TRUE(json_->Set(key_, "$", "true").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "true").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "false"); ASSERT_EQ(res.size(), 1); ASSERT_THAT(res, testing::ElementsAre(false)); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"bool":true})").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$.bool", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"bool":true})").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$.bool", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":false})"); ASSERT_EQ(res.size(), 1); ASSERT_THAT(res, testing::ElementsAre(false)); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"bool":true,"bools":{"bool":true}})").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$.bool", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"bool":true,"bools":{"bool":true}})").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$.bool", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":false,"bools":{"bool":true}})"); ASSERT_EQ(res.size(), 1); ASSERT_THAT(res, testing::ElementsAre(false)); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"bool":true,"bools":{"bool":true}})").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$..bool", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"bool":true,"bools":{"bool":true}})").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$..bool", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":false,"bools":{"bool":false}})"); ASSERT_EQ(res.size(), 2); ASSERT_THAT(res, testing::ElementsAre(false, false)); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"bool":false,"bools":{"bool":true}})").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$..bool", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"bool":false,"bools":{"bool":true}})").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$..bool", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":true,"bools":{"bool":false}})"); ASSERT_EQ(res.size(), 2); ASSERT_THAT(res, testing::ElementsAre(true, false)); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"bool":false,"bools":{"bool":true},"incorrectbool":{"bool":88}})").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$..bool", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"bool":false,"bools":{"bool":true},"incorrectbool":{"bool":88}})").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$..bool", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":true,"bools":{"bool":false},"incorrectbool":{"bool":88}})"); ASSERT_EQ(res.size(), 3); ASSERT_THAT(res, testing::ElementsAre(true, false, std::nullopt)); res.clear(); - ASSERT_TRUE(json_->Set(key_, "$", "[true,true,99]").ok()); - ASSERT_TRUE(json_->Toggle(key_, "$..*", &res).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "[true,true,99]").ok()); + ASSERT_TRUE(json_->Toggle(*ctx_, key_, "$..*", &res).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), "[false,false,99]"); ASSERT_EQ(res.size(), 3); ASSERT_THAT(res, testing::ElementsAre(false, false, std::nullopt)); @@ -380,59 +381,59 @@ TEST_F(RedisJsonTest, ArrPop) { Optionals res; // Array - ASSERT_TRUE(json_->Set(key_, "$", R"([3,"str",2.1,{},[5,6]])").ok()); - ASSERT_TRUE(json_->ArrPop(key_, "$", -1, &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"([3,"str",2.1,{},[5,6]])").ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$", -1, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_TRUE(res[0].has_value()); ASSERT_EQ(res[0]->Dump().GetValue(), "[5,6]"); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$", -2, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$", -2, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_TRUE(res[0].has_value()); ASSERT_EQ(res[0]->Dump().GetValue(), "2.1"); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$", 3, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$", 3, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_TRUE(res[0].has_value()); ASSERT_EQ(res[0]->Dump().GetValue(), "{}"); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$", 1, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$", 1, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_TRUE(res[0].has_value()); ASSERT_EQ(res[0]->Dump().GetValue(), R"("str")"); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$", 0, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$", 0, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_TRUE(res[0].has_value()); ASSERT_EQ(res[0]->Dump().GetValue(), "3"); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$", -1, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$", -1, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_FALSE(res[0].has_value()); res.clear(); // Non-array - ASSERT_TRUE(json_->Set(key_, "$", R"({"o":{"x":1},"s":"str","i":1,"d":2.2})").ok()); - ASSERT_TRUE(json_->ArrPop(key_, "$.o", 1, &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"o":{"x":1},"s":"str","i":1,"d":2.2})").ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$.o", 1, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_FALSE(res[0].has_value()); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$.s", -1, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$.s", -1, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_FALSE(res[0].has_value()); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$.i", 0, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$.i", 0, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_FALSE(res[0].has_value()); res.clear(); - ASSERT_TRUE(json_->ArrPop(key_, "$.d", 2, &res).ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$.d", 2, &res).ok()); ASSERT_EQ(res.size(), 1); ASSERT_FALSE(res[0].has_value()); res.clear(); // Multiple arrays - ASSERT_TRUE(json_->Set(key_, "$", R"([[0,1],[3,{"x":2.0}],"str",[4,[5,"6"]]])").ok()); - ASSERT_TRUE(json_->ArrPop(key_, "$.*", -1, &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"([[0,1],[3,{"x":2.0}],"str",[4,[5,"6"]]])").ok()); + ASSERT_TRUE(json_->ArrPop(*ctx_, key_, "$.*", -1, &res).ok()); ASSERT_EQ(res.size(), 4); ASSERT_TRUE(res[0].has_value()); ASSERT_EQ(res[0]->Dump().GetValue(), R"([5,"6"])"); @@ -448,56 +449,56 @@ TEST_F(RedisJsonTest, ArrIndex) { Optionals res; int max_end = std::numeric_limits::max(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"arr":[0, 1, 2, 3, 2, 1, 0]})").ok()); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "0", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"arr":[0, 1, 2, 3, 2, 1, 0]})").ok()); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "0", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 0); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "3", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "3", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res.size(), 1); ASSERT_EQ(res[0], 3); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "4", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "4", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], -1); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "0", 1, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "0", 1, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 6); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "0", -1, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "0", -1, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 6); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "0", 6, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "0", 6, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 6); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "0", 5, -1, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "0", 5, -1, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], -1); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "0", 5, 0, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "0", 5, 0, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 6); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "2", -2, 6, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "2", -2, 6, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], -1); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "\"foo\"", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "\"foo\"", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], -1); - ASSERT_TRUE(json_->Set(key_, "$", R"({"arr":[0, 1, 2, 3, 4, 2, 1, 0]})").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"arr":[0, 1, 2, 3, 4, 2, 1, 0]})").ok()); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "3", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "3", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 3); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "2", 3, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "2", 3, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 5); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "1", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "1", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 1); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "2", 1, 4, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "2", 1, 4, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], 2); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "6", 0, max_end, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "6", 0, max_end, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], -1); - ASSERT_TRUE(json_->ArrIndex(key_, "$.arr", "3", 0, 2, &res).ok() && res.size() == 1); + ASSERT_TRUE(json_->ArrIndex(*ctx_, key_, "$.arr", "3", 0, 2, &res).ok() && res.size() == 1); ASSERT_EQ(res[0], -1); } @@ -506,177 +507,177 @@ TEST_F(RedisJsonTest, Del) { ASSERT_TRUE( json_ - ->Set(key_, "$", + ->Set(*ctx_, key_, "$", R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})") .ok()); - ASSERT_TRUE(json_->Del(key_, "$", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).IsNotFound()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).IsNotFound()); ASSERT_EQ(result, 1); ASSERT_TRUE( json_ - ->Set(key_, "$", + ->Set(*ctx_, key_, "$", R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})") .ok()); - ASSERT_TRUE(json_->Del(key_, "$.obj", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$.obj", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"arr":[1,2,3],"bool":true,"float":3.14,"int":42,"str":"foo"})"); ASSERT_EQ(result, 1); - ASSERT_TRUE(json_->Del(key_, "$.arr", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$.arr", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"bool":true,"float":3.14,"int":42,"str":"foo"})"); ASSERT_EQ(result, 1); ASSERT_TRUE( json_ - ->Set(key_, "$", + ->Set(*ctx_, key_, "$", R"({"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14})") .ok()); - ASSERT_TRUE(json_->Del(key_, "$.*", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$.*", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({})"); ASSERT_EQ(result, 6); - ASSERT_TRUE(json_->Del(key_, "$.some", &result).ok()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$.some", &result).ok()); ASSERT_EQ(result, 0); - ASSERT_TRUE(json_->Set(key_, "$", R"({"a": 1, "nested": {"a": 2, "b": 3}})").ok()); - ASSERT_TRUE(json_->Del(key_, "$..a", &result).ok()); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a": 1, "nested": {"a": 2, "b": 3}})").ok()); + ASSERT_TRUE(json_->Del(*ctx_, key_, "$..a", &result).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"nested":{"b":3}})"); ASSERT_EQ(result, 2); } TEST_F(RedisJsonTest, NumIncrBy) { - ASSERT_TRUE(json_->Set(key_, "$", R"({ "foo": 0, "bar": "baz" })").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({ "foo": 0, "bar": "baz" })").ok()); JsonValue res = JsonValue::FromString("[]").GetValue(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.foo", "1", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.foo", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.foo", "2", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.foo", "2", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[3]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.foo", "0.5", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.foo", "0.5", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[3.5]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.bar", "1", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.bar", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[null]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.fuzz", "1", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.fuzz", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[]"); res.value.clear(); - ASSERT_TRUE(json_->Set(key_, "$", "0").ok()); - ASSERT_TRUE(json_->NumIncrBy(key_, "$", "0", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "0").ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$", "0", &res).ok()); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$", "1", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$", "1.5", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$", "1.5", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[2.5]"); res.value.clear(); // overflow case - ASSERT_TRUE(json_->Set(key_, "$", "1.6350000000001313e+308").ok()); - ASSERT_TRUE(json_->NumIncrBy(key_, "$", "1", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "1.6350000000001313e+308").ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.6350000000001313e+308]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$", "2", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$", "2", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.6350000000001313e+308]"); res.value.clear(); // nested big_num object - ASSERT_TRUE(json_->Set(key_, "$", R"({"l1":{"l2_a":1.6350000000001313e+308,"l2_b":2}})").ok()); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.l1.l2_a", "1", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"l1":{"l2_a":1.6350000000001313e+308,"l2_b":2}})").ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.l1.l2_a", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.6350000000001313e+308]"); res.value.clear(); - ASSERT_TRUE(json_->NumIncrBy(key_, "$.l1.l2_a", "2", &res).ok()); + ASSERT_TRUE(json_->NumIncrBy(*ctx_, key_, "$.l1.l2_a", "2", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.6350000000001313e+308]"); res.value.clear(); // nested big_num array - ASSERT_TRUE(json_->Set(key_, "$", R"({"l1":{"l2":[0,1.6350000000001313e+308]}})").ok()); - ASSERT_FALSE(json_->NumIncrBy(key_, "$.l1.l2[1]", "1.6350000000001313e+308", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"l1":{"l2":[0,1.6350000000001313e+308]}})").ok()); + ASSERT_FALSE(json_->NumIncrBy(*ctx_, key_, "$.l1.l2[1]", "1.6350000000001313e+308", &res).ok()); res.value.clear(); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"l1":{"l2":[0,1.6350000000001313e+308]}})"); } TEST_F(RedisJsonTest, NumMultBy) { - ASSERT_TRUE(json_->Set(key_, "$", R"({ "foo": 1, "bar": "baz" })").ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({ "foo": 1, "bar": "baz" })").ok()); JsonValue res = JsonValue::FromString("[]").GetValue(); - ASSERT_TRUE(json_->NumMultBy(key_, "$.foo", "1", &res).ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$.foo", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1]"); res.value.clear(); - ASSERT_TRUE(json_->NumMultBy(key_, "$.foo", "2", &res).ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$.foo", "2", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[2]"); res.value.clear(); - ASSERT_TRUE(json_->NumMultBy(key_, "$.foo", "0.5", &res).ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$.foo", "0.5", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1]"); res.value.clear(); - ASSERT_TRUE(json_->NumMultBy(key_, "$.bar", "1", &res).ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$.bar", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[null]"); res.value.clear(); - ASSERT_TRUE(json_->NumMultBy(key_, "$.fuzz", "1", &res).ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$.fuzz", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[]"); res.value.clear(); // num object - ASSERT_TRUE(json_->Set(key_, "$", "1.0").ok()); - ASSERT_TRUE(json_->NumMultBy(key_, "$", "1", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "1.0").ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1]"); res.value.clear(); - ASSERT_TRUE(json_->NumMultBy(key_, "$", "1.5", &res).ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$", "1.5", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.5]"); res.value.clear(); // overflow case - ASSERT_TRUE(json_->Set(key_, "$", "1.6350000000001313e+308").ok()); - ASSERT_TRUE(json_->NumMultBy(key_, "$", "1", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", "1.6350000000001313e+308").ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.6350000000001313e+308]"); res.value.clear(); - ASSERT_FALSE(json_->NumMultBy(key_, "$", "2", &res).ok()); + ASSERT_FALSE(json_->NumMultBy(*ctx_, key_, "$", "2", &res).ok()); res.value.clear(); // nested big_num object - ASSERT_TRUE(json_->Set(key_, "$", R"({"l1":{"l2_a":1.6350000000001313e+308,"l2_b":2}})").ok()); - ASSERT_TRUE(json_->NumMultBy(key_, "$.l1.l2_a", "1", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"l1":{"l2_a":1.6350000000001313e+308,"l2_b":2}})").ok()); + ASSERT_TRUE(json_->NumMultBy(*ctx_, key_, "$.l1.l2_a", "1", &res).ok()); ASSERT_EQ(res.Print(0, true).GetValue(), "[1.6350000000001313e+308]"); res.value.clear(); - ASSERT_FALSE(json_->NumMultBy(key_, "$.l1.l2_a", "2", &res).ok()); + ASSERT_FALSE(json_->NumMultBy(*ctx_, key_, "$.l1.l2_a", "2", &res).ok()); res.value.clear(); // nested big_num array - ASSERT_TRUE(json_->Set(key_, "$", R"({"l1":{"l2":[0,1.6350000000001313e+308]}})").ok()); - ASSERT_FALSE(json_->NumMultBy(key_, "$.l1.l2[1]", "2", &res).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"l1":{"l2":[0,1.6350000000001313e+308]}})").ok()); + ASSERT_FALSE(json_->NumMultBy(*ctx_, key_, "$.l1.l2[1]", "2", &res).ok()); res.value.clear(); - ASSERT_TRUE(json_->Get(key_, {}, &json_val_).ok()); + ASSERT_TRUE(json_->Get(*ctx_, key_, {}, &json_val_).ok()); ASSERT_EQ(json_val_.Dump().GetValue(), R"({"l1":{"l2":[0,1.6350000000001313e+308]}})"); } TEST_F(RedisJsonTest, StrAppend) { Optionals results; - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); - ASSERT_TRUE(json_->StrAppend(key_, "$.a", "\"be\"", &results).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); + ASSERT_TRUE(json_->StrAppend(*ctx_, key_, "$.a", "\"be\"", &results).ok()); ASSERT_EQ(results.size(), 1); ASSERT_EQ(results[0], 5); results.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); - ASSERT_TRUE(json_->StrAppend(key_, "$..a", "\"be\"", &results).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); + ASSERT_TRUE(json_->StrAppend(*ctx_, key_, "$..a", "\"be\"", &results).ok()); ASSERT_EQ(results.size(), 3); Optionals result1 = {5, 7, std::nullopt}; for (int i = 0; i < 3; ++i) { @@ -686,14 +687,14 @@ TEST_F(RedisJsonTest, StrAppend) { TEST_F(RedisJsonTest, StrLen) { Optionals results; - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); - ASSERT_TRUE(json_->StrLen(key_, "$.a", &results).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); + ASSERT_TRUE(json_->StrLen(*ctx_, key_, "$.a", &results).ok()); ASSERT_EQ(results.size(), 1); ASSERT_EQ(results[0], 3); results.clear(); - ASSERT_TRUE(json_->Set(key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); - ASSERT_TRUE(json_->StrLen(key_, "$..a", &results).ok()); + ASSERT_TRUE(json_->Set(*ctx_, key_, "$", R"({"a":"foo", "nested": {"a": "hello"}, "nested2": {"a": 31}})").ok()); + ASSERT_TRUE(json_->StrLen(*ctx_, key_, "$..a", &results).ok()); ASSERT_EQ(results.size(), 3); Optionals result1 = {3, 5, std::nullopt}; for (int i = 0; i < 3; ++i) { diff --git a/tests/cppunit/types/list_test.cc b/tests/cppunit/types/list_test.cc index 643bdce9dd1..83a3b5ff825 100644 --- a/tests/cppunit/types/list_test.cc +++ b/tests/cppunit/types/list_test.cc @@ -58,20 +58,20 @@ class RedisListSpecificTest : public RedisListTest { class RedisListLMoveTest : public RedisListTest { protected: void SetUp() override { - auto s = list_->Del(key_); - s = list_->Del(dst_key_); + auto s = list_->Del(*ctx_, key_); + s = list_->Del(*ctx_, dst_key_); fields_ = {"src1", "src2", "src3", "src4"}; dst_fields_ = {"dst", "dst2", "dst3", "dst4"}; } void TearDown() override { - auto s = list_->Del(key_); - s = list_->Del(dst_key_); + auto s = list_->Del(*ctx_, key_); + s = list_->Del(*ctx_, dst_key_); } void listElementsAreEqualTo(const Slice &key, int start, int stop, const std::vector &expected_elems) { std::vector actual_elems; - auto s = list_->Range(key, start, stop, &actual_elems); + auto s = list_->Range(*ctx_, key, start, stop, &actual_elems); EXPECT_TRUE(s.ok()); EXPECT_EQ(actual_elems.size(), expected_elems.size()); @@ -87,123 +87,123 @@ class RedisListLMoveTest : public RedisListTest { TEST_F(RedisListTest, PushAndPop) { uint64_t ret = 0; - list_->Push(key_, fields_, true, &ret); + list_->Push(*ctx_, key_, fields_, true, &ret); EXPECT_EQ(fields_.size(), ret); for (auto &field : fields_) { std::string elem; - list_->Pop(key_, false, &elem); + list_->Pop(*ctx_, key_, false, &elem); EXPECT_EQ(elem, field.ToString()); } - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); for (auto &field : fields_) { std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, Pushx) { uint64_t ret = 0; Slice pushx_key("test-pushx-key"); - rocksdb::Status s = list_->PushX(pushx_key, fields_, true, &ret); + rocksdb::Status s = list_->PushX(*ctx_, pushx_key, fields_, true, &ret); EXPECT_TRUE(s.ok()); - list_->Push(pushx_key, fields_, true, &ret); + list_->Push(*ctx_, pushx_key, fields_, true, &ret); EXPECT_EQ(fields_.size(), ret); - s = list_->PushX(pushx_key, fields_, true, &ret); + s = list_->PushX(*ctx_, pushx_key, fields_, true, &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(ret, fields_.size() * 2); - s = list_->Del(pushx_key); + s = list_->Del(*ctx_, pushx_key); } TEST_F(RedisListTest, Index) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::string elem; for (size_t i = 0; i < fields_.size(); i++) { - list_->Index(key_, static_cast(i), &elem); + list_->Index(*ctx_, key_, static_cast(i), &elem); EXPECT_EQ(fields_[i].ToString(), elem); } for (auto &field : fields_) { - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } - rocksdb::Status s = list_->Index(key_, -1, &elem); + rocksdb::Status s = list_->Index(*ctx_, key_, -1, &elem); EXPECT_TRUE(s.IsNotFound()); - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, Set) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); Slice new_elem("new_elem"); - list_->Set(key_, -1, new_elem); + list_->Set(*ctx_, key_, -1, new_elem); std::string elem; - list_->Index(key_, -1, &elem); + list_->Index(*ctx_, key_, -1, &elem); EXPECT_EQ(new_elem.ToString(), elem); for (size_t i = 0; i < fields_.size(); i++) { - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, Range) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::vector elems; - list_->Range(key_, 0, int(elems.size() - 1), &elems); + list_->Range(*ctx_, key_, 0, int(elems.size() - 1), &elems); EXPECT_EQ(elems.size(), fields_.size()); for (size_t i = 0; i < elems.size(); i++) { EXPECT_EQ(fields_[i].ToString(), elems[i]); } for (auto &field : fields_) { std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, Pos) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); // Basic usage PosSpec spec; std::vector indexes; - list_->Pos(key_, fields_[0], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[0], spec, &indexes); EXPECT_EQ(1, indexes.size()); EXPECT_EQ(0, indexes[0]); - list_->Pos(key_, fields_[2], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[2], spec, &indexes); EXPECT_EQ(1, indexes.size()); EXPECT_EQ(2, indexes[0]); // RANK option spec = PosSpec{}; spec.rank = m_ + 1; - auto s = list_->Pos(key_, fields_[3], spec, &indexes); + auto s = list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_TRUE(s.ok()); EXPECT_TRUE(indexes.empty()); spec.rank = -(m_ + 1); - s = list_->Pos(key_, fields_[3], spec, &indexes); + s = list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_TRUE(s.ok()); EXPECT_TRUE(indexes.empty()); // positive for (int i = 1; i <= m_; ++i) { spec.rank = i; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(1, indexes.size()); EXPECT_EQ(n_ * (i - 1) + 3, indexes[0]); } // negative for (int i = 1; i <= m_; ++i) { spec.rank = -i; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(1, indexes.size()); EXPECT_EQ(fields_.size() - n_ * i + 3, indexes[0]); } @@ -211,15 +211,15 @@ TEST_F(RedisListTest, Pos) { // COUNT option spec = PosSpec{}; spec.count = 0; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(m_, indexes.size()); EXPECT_EQ(3, indexes[0]); spec.count = 2; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(2, indexes.size()); EXPECT_EQ(3, indexes[0]); spec.count = 100; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(m_, indexes.size()); EXPECT_EQ(3, indexes[0]); @@ -227,77 +227,77 @@ TEST_F(RedisListTest, Pos) { spec = PosSpec{}; spec.count = 0; spec.rank = 2; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(n_ - 2, indexes.size()); spec.count = 2; spec.rank = -2; - list_->Pos(key_, fields_[3], spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], spec, &indexes); EXPECT_EQ(2, indexes.size()); // MAXLEN option PosSpec maxlen_spec; maxlen_spec.max_len = 2; - list_->Pos(key_, fields_[2], maxlen_spec, &indexes); + list_->Pos(*ctx_, key_, fields_[2], maxlen_spec, &indexes); EXPECT_TRUE(indexes.empty()); - list_->Pos(key_, fields_[1], maxlen_spec, &indexes); + list_->Pos(*ctx_, key_, fields_[1], maxlen_spec, &indexes); EXPECT_EQ(1, indexes.size()); EXPECT_EQ(1, indexes[0]); maxlen_spec.count = 0; maxlen_spec.max_len = (n_ * 2); - list_->Pos(key_, fields_[3], maxlen_spec, &indexes); + list_->Pos(*ctx_, key_, fields_[3], maxlen_spec, &indexes); EXPECT_EQ(2, indexes.size()); EXPECT_EQ(3, indexes[0]); - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, Rem) { uint64_t ret = 0; uint64_t len = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); Slice del_elem("list-test-key-1"); // lrem key_ 1 list-test-key-1 - list_->Rem(key_, 1, del_elem, &ret); + list_->Rem(*ctx_, key_, 1, del_elem, &ret); EXPECT_EQ(1, ret); - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 1, len); for (size_t i = 1; i < fields_.size(); i++) { std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, fields_[i].ToString()); } // lrem key_ 0 list-test-key-1 - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Rem(key_, 0, del_elem, &ret); + list_->Rem(*ctx_, key_, 0, del_elem, &ret); EXPECT_EQ(4, ret); - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 4, len); for (auto &field : fields_) { std::string elem; if (field == del_elem) continue; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } // lrem key_ 1 nosuchelement Slice no_elem("no_such_element"); - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Rem(key_, 1, no_elem, &ret); + list_->Rem(*ctx_, key_, 1, no_elem, &ret); EXPECT_EQ(0, ret); - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size(), len); for (auto &field : fields_) { std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } // lrem key_ -1 list-test-key-1 - list_->Push(key_, fields_, false, &ret); - list_->Rem(key_, -1, del_elem, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); + list_->Rem(*ctx_, key_, -1, del_elem, &ret); EXPECT_EQ(1, ret); - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 1, len); int cnt = 0; for (auto &field : fields_) { @@ -305,35 +305,35 @@ TEST_F(RedisListTest, Rem) { if (field == del_elem) { if (++cnt > 3) continue; } - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } // lrem key_ -5 list-test-key-1 - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Rem(key_, -5, del_elem, &ret); + list_->Rem(*ctx_, key_, -5, del_elem, &ret); EXPECT_EQ(4, ret); - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 4, len); for (auto &field : fields_) { std::string elem; if (field == del_elem) continue; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListSpecificTest, Rem) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); Slice del_elem("9"); // lrem key_ 1 9 - list_->Rem(key_, 1, del_elem, &ret); + list_->Rem(*ctx_, key_, 1, del_elem, &ret); EXPECT_EQ(1, ret); uint64_t len = 0; - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 1, len); int cnt = 0; for (auto &field : fields_) { @@ -341,14 +341,14 @@ TEST_F(RedisListSpecificTest, Rem) { if (++cnt <= 1) continue; } std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } // lrem key_ -2 9 - list_->Push(key_, fields_, false, &ret); - list_->Rem(key_, -2, del_elem, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); + list_->Rem(*ctx_, key_, -2, del_elem, &ret); EXPECT_EQ(2, ret); - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 2, len); cnt = 0; for (size_t i = fields_.size(); i > 0; i--) { @@ -356,56 +356,56 @@ TEST_F(RedisListSpecificTest, Rem) { if (++cnt <= 2) continue; } std::string elem; - list_->Pop(key_, false, &elem); + list_->Pop(*ctx_, key_, false, &elem); EXPECT_EQ(elem, fields_[i - 1].ToString()); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, Trim) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Trim(key_, 1, 2000); + list_->Trim(*ctx_, key_, 1, 2000); uint64_t len = 0; - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 1, len); for (size_t i = 1; i < fields_.size(); i++) { std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, fields_[i].ToString()); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListSpecificTest, Trim) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); // ltrim key_ 3 -3 then linsert 2 3 and lrem key_ 5 3 Slice del_elem("3"); - list_->Trim(key_, 3, -3); + list_->Trim(*ctx_, key_, 3, -3); uint64_t len = 0; - list_->Size(key_, &len); + list_->Size(*ctx_, key_, &len); EXPECT_EQ(fields_.size() - 5, len); Slice insert_elem("3"); int insert_ret = 0; - list_->Insert(key_, Slice("2"), insert_elem, true, &insert_ret); + list_->Insert(*ctx_, key_, Slice("2"), insert_elem, true, &insert_ret); EXPECT_EQ(-1, insert_ret); - list_->Rem(key_, 5, del_elem, &ret); + list_->Rem(*ctx_, key_, 5, del_elem, &ret); EXPECT_EQ(4, ret); for (size_t i = 3; i < fields_.size() - 2; i++) { if (fields_[i] == del_elem) continue; std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, fields_[i].ToString()); } - auto s = list_->Del(key_); + auto s = list_->Del(*ctx_, key_); } TEST_F(RedisListLMoveTest, LMoveSrcNotExist) { std::string elem; - auto s = list_->LMove(key_, dst_key_, true, true, &elem); + auto s = list_->LMove(*ctx_, key_, dst_key_, true, true, &elem); EXPECT_EQ(elem, ""); EXPECT_FALSE(s.ok()); EXPECT_TRUE(s.IsNotFound()); @@ -414,10 +414,10 @@ TEST_F(RedisListLMoveTest, LMoveSrcNotExist) { TEST_F(RedisListLMoveTest, LMoveSrcAndDstAreTheSameSingleElem) { uint64_t ret = 0; Slice element = fields_[0]; - list_->Push(key_, {element}, false, &ret); + list_->Push(*ctx_, key_, {element}, false, &ret); EXPECT_EQ(1, ret); std::string expected_elem; - auto s = list_->LMove(key_, key_, true, true, &expected_elem); + auto s = list_->LMove(*ctx_, key_, key_, true, true, &expected_elem); EXPECT_EQ(expected_elem, element); EXPECT_TRUE(s.ok()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size()), {fields_[0]}); @@ -425,10 +425,10 @@ TEST_F(RedisListLMoveTest, LMoveSrcAndDstAreTheSameSingleElem) { TEST_F(RedisListLMoveTest, LMoveSrcAndDstAreTheSameManyElemsLeftRight) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, key_, true, false, &elem); + auto s = list_->LMove(*ctx_, key_, key_, true, false, &elem); EXPECT_TRUE(s.ok()); EXPECT_EQ(elem, fields_[0].ToString()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size() + 1), @@ -437,10 +437,10 @@ TEST_F(RedisListLMoveTest, LMoveSrcAndDstAreTheSameManyElemsLeftRight) { TEST_F(RedisListLMoveTest, LMoveSrcAndDstAreTheSameManyElemsRightLeft) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, key_, false, true, &elem); + auto s = list_->LMove(*ctx_, key_, key_, false, true, &elem); EXPECT_TRUE(s.ok()); EXPECT_EQ(elem, fields_[fields_.size() - 1].ToString()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size() + 1), @@ -449,10 +449,10 @@ TEST_F(RedisListLMoveTest, LMoveSrcAndDstAreTheSameManyElemsRightLeft) { TEST_F(RedisListLMoveTest, LMoveDstNotExist) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, dst_key_, true, false, &elem); + auto s = list_->LMove(*ctx_, key_, dst_key_, true, false, &elem); EXPECT_EQ(elem, fields_[0].ToString()); EXPECT_TRUE(s.ok()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size()), {fields_[1], fields_[2], fields_[3]}); @@ -461,12 +461,12 @@ TEST_F(RedisListLMoveTest, LMoveDstNotExist) { TEST_F(RedisListLMoveTest, LMoveSrcLeftDstLeft) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Push(dst_key_, dst_fields_, false, &ret); + list_->Push(*ctx_, dst_key_, dst_fields_, false, &ret); EXPECT_EQ(dst_fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, dst_key_, true, true, &elem); + auto s = list_->LMove(*ctx_, key_, dst_key_, true, true, &elem); EXPECT_EQ(elem, fields_[0].ToString()); EXPECT_TRUE(s.ok()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size()), {fields_[1], fields_[2], fields_[3]}); @@ -476,12 +476,12 @@ TEST_F(RedisListLMoveTest, LMoveSrcLeftDstLeft) { TEST_F(RedisListLMoveTest, LMoveSrcLeftDstRight) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Push(dst_key_, dst_fields_, false, &ret); + list_->Push(*ctx_, dst_key_, dst_fields_, false, &ret); EXPECT_EQ(dst_fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, dst_key_, true, false, &elem); + auto s = list_->LMove(*ctx_, key_, dst_key_, true, false, &elem); EXPECT_EQ(elem, fields_[0].ToString()); EXPECT_TRUE(s.ok()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size()), {fields_[1], fields_[2], fields_[3]}); @@ -491,12 +491,12 @@ TEST_F(RedisListLMoveTest, LMoveSrcLeftDstRight) { TEST_F(RedisListLMoveTest, LMoveSrcRightDstLeft) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Push(dst_key_, dst_fields_, false, &ret); + list_->Push(*ctx_, dst_key_, dst_fields_, false, &ret); EXPECT_EQ(dst_fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, dst_key_, false, true, &elem); + auto s = list_->LMove(*ctx_, key_, dst_key_, false, true, &elem); EXPECT_EQ(elem, fields_[3].ToString()); EXPECT_TRUE(s.ok()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size()), {fields_[0], fields_[1], fields_[2]}); @@ -506,12 +506,12 @@ TEST_F(RedisListLMoveTest, LMoveSrcRightDstLeft) { TEST_F(RedisListLMoveTest, LMoveSrcRightDstRight) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); - list_->Push(dst_key_, dst_fields_, false, &ret); + list_->Push(*ctx_, dst_key_, dst_fields_, false, &ret); EXPECT_EQ(dst_fields_.size(), ret); std::string elem; - auto s = list_->LMove(key_, dst_key_, false, false, &elem); + auto s = list_->LMove(*ctx_, key_, dst_key_, false, false, &elem); EXPECT_EQ(elem, fields_[3].ToString()); EXPECT_TRUE(s.ok()); listElementsAreEqualTo(key_, 0, static_cast(fields_.size()), {fields_[0], fields_[1], fields_[2]}); @@ -521,110 +521,110 @@ TEST_F(RedisListLMoveTest, LMoveSrcRightDstRight) { TEST_F(RedisListTest, LPopEmptyList) { std::string non_existing_key{"non-existing-key"}; - auto s = list_->Del(non_existing_key); + auto s = list_->Del(*ctx_, non_existing_key); std::string elem; - s = list_->Pop(non_existing_key, true, &elem); + s = list_->Pop(*ctx_, non_existing_key, true, &elem); EXPECT_TRUE(s.IsNotFound()); std::vector elems; - s = list_->PopMulti(non_existing_key, true, 10, &elems); + s = list_->PopMulti(*ctx_, non_existing_key, true, 10, &elems); EXPECT_TRUE(s.IsNotFound()); } TEST_F(RedisListTest, LPopOneElement) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); for (auto &field : fields_) { std::string elem; - list_->Pop(key_, true, &elem); + list_->Pop(*ctx_, key_, true, &elem); EXPECT_EQ(elem, field.ToString()); } std::string elem; - auto s = list_->Pop(key_, true, &elem); + auto s = list_->Pop(*ctx_, key_, true, &elem); EXPECT_TRUE(s.IsNotFound()); - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, LPopMulti) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::vector elems; size_t requested_size = fields_.size() / 3; - auto s = list_->PopMulti(key_, true, requested_size, &elems); + auto s = list_->PopMulti(*ctx_, key_, true, requested_size, &elems); EXPECT_TRUE(s.ok()); EXPECT_EQ(elems.size(), requested_size); for (size_t i = 0; i < elems.size(); ++i) { EXPECT_EQ(elems[i], fields_[i].ToString()); } - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, LPopMultiCountGreaterThanListSize) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::vector elems; - auto s = list_->PopMulti(key_, true, 2 * ret, &elems); + auto s = list_->PopMulti(*ctx_, key_, true, 2 * ret, &elems); EXPECT_TRUE(s.ok()); EXPECT_EQ(elems.size(), ret); for (size_t i = 0; i < elems.size(); ++i) { EXPECT_EQ(elems[i], fields_[i].ToString()); } - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, RPopEmptyList) { std::string non_existing_key{"non-existing-key"}; - auto s = list_->Del(non_existing_key); + auto s = list_->Del(*ctx_, non_existing_key); std::string elem; - s = list_->Pop(non_existing_key, false, &elem); + s = list_->Pop(*ctx_, non_existing_key, false, &elem); EXPECT_TRUE(s.IsNotFound()); std::vector elems; - s = list_->PopMulti(non_existing_key, false, 10, &elems); + s = list_->PopMulti(*ctx_, non_existing_key, false, 10, &elems); EXPECT_TRUE(s.IsNotFound()); } TEST_F(RedisListTest, RPopOneElement) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); for (size_t i = 0; i < fields_.size(); i++) { std::string elem; - list_->Pop(key_, false, &elem); + list_->Pop(*ctx_, key_, false, &elem); EXPECT_EQ(elem, fields_[fields_.size() - i - 1].ToString()); } std::string elem; - auto s = list_->Pop(key_, false, &elem); + auto s = list_->Pop(*ctx_, key_, false, &elem); EXPECT_TRUE(s.IsNotFound()); - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, RPopMulti) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::vector elems; size_t requested_size = fields_.size() / 3; - auto s = list_->PopMulti(key_, false, requested_size, &elems); + auto s = list_->PopMulti(*ctx_, key_, false, requested_size, &elems); EXPECT_TRUE(s.ok()); EXPECT_EQ(elems.size(), requested_size); for (size_t i = 0; i < elems.size(); ++i) { EXPECT_EQ(elems[i], fields_[fields_.size() - i - 1].ToString()); } - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } TEST_F(RedisListTest, RPopMultiCountGreaterThanListSize) { uint64_t ret = 0; - list_->Push(key_, fields_, false, &ret); + list_->Push(*ctx_, key_, fields_, false, &ret); EXPECT_EQ(fields_.size(), ret); std::vector elems; - auto s = list_->PopMulti(key_, false, 2 * ret, &elems); + auto s = list_->PopMulti(*ctx_, key_, false, 2 * ret, &elems); EXPECT_TRUE(s.ok()); EXPECT_EQ(elems.size(), ret); for (size_t i = 0; i < elems.size(); ++i) { EXPECT_EQ(elems[i], fields_[fields_.size() - i - 1].ToString()); } - s = list_->Del(key_); + s = list_->Del(*ctx_, key_); } diff --git a/tests/cppunit/types/set_test.cc b/tests/cppunit/types/set_test.cc index de94a611b68..44f230d23ae 100644 --- a/tests/cppunit/types/set_test.cc +++ b/tests/cppunit/types/set_test.cc @@ -35,82 +35,82 @@ class RedisSetTest : public TestBase { fields_ = {"set-key-1", "set-key-2", "set-key-3", "set-key-4"}; } - void TearDown() override { [[maybe_unused]] auto s = set_->Del(key_); } + void TearDown() override { [[maybe_unused]] auto s = set_->Del(*ctx_, key_); } std::unique_ptr set_; }; TEST_F(RedisSetTest, AddAndRemove) { uint64_t ret = 0; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = set_->Card(key_, &ret); + s = set_->Card(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = set_->Remove(key_, fields_, &ret); + s = set_->Remove(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = set_->Card(key_, &ret); + s = set_->Card(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && ret == 0); } TEST_F(RedisSetTest, AddAndRemoveRepeated) { std::vector allmembers{"m1", "m1", "m2", "m3"}; uint64_t ret = 0; - rocksdb::Status s = set_->Add(key_, allmembers, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, allmembers, &ret); EXPECT_TRUE(s.ok() && (allmembers.size() - 1) == ret); uint64_t card = 0; - set_->Card(key_, &card); + set_->Card(*ctx_, key_, &card); EXPECT_EQ(card, allmembers.size() - 1); std::vector remembers{"m1", "m2", "m2"}; - s = set_->Remove(key_, remembers, &ret); + s = set_->Remove(*ctx_, key_, remembers, &ret); EXPECT_TRUE(s.ok() && (remembers.size() - 1) == ret); - set_->Card(key_, &card); + set_->Card(*ctx_, key_, &card); EXPECT_EQ(card, allmembers.size() - 1 - ret); } TEST_F(RedisSetTest, Members) { uint64_t ret = 0; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); std::vector members; - s = set_->Members(key_, &members); + s = set_->Members(*ctx_, key_, &members); EXPECT_TRUE(s.ok() && fields_.size() == members.size()); // Note: the members was fetched by iterator, so the order should be asec for (size_t i = 0; i < fields_.size(); i++) { EXPECT_EQ(fields_[i], members[i]); } - s = set_->Remove(key_, fields_, &ret); + s = set_->Remove(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); } TEST_F(RedisSetTest, IsMember) { uint64_t ret = 0; bool flag = false; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); for (auto &field : fields_) { - s = set_->IsMember(key_, field, &flag); + s = set_->IsMember(*ctx_, key_, field, &flag); EXPECT_TRUE(s.ok() && flag); } - set_->IsMember(key_, "foo", &flag); + set_->IsMember(*ctx_, key_, "foo", &flag); EXPECT_TRUE(s.ok() && !flag); - s = set_->Remove(key_, fields_, &ret); + s = set_->Remove(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); } TEST_F(RedisSetTest, MIsMember) { uint64_t ret = 0; std::vector exists; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = set_->MIsMember(key_, fields_, &exists); + s = set_->MIsMember(*ctx_, key_, fields_, &exists); EXPECT_TRUE(s.ok()); for (size_t i = 0; i < fields_.size(); i++) { EXPECT_TRUE(exists[i] == 1); } - s = set_->Remove(key_, {fields_[0]}, &ret); + s = set_->Remove(*ctx_, key_, {fields_[0]}, &ret); EXPECT_TRUE(s.ok() && ret == 1); - s = set_->MIsMember(key_, fields_, &exists); + s = set_->MIsMember(*ctx_, key_, fields_, &exists); EXPECT_TRUE(s.ok() && exists[0] == 0); for (size_t i = 1; i < fields_.size(); i++) { EXPECT_TRUE(exists[i] == 1); @@ -120,36 +120,36 @@ TEST_F(RedisSetTest, MIsMember) { TEST_F(RedisSetTest, Move) { uint64_t ret = 0; bool flag = false; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); Slice dst("set-test-move-key"); for (auto &field : fields_) { - s = set_->Move(key_, dst, field, &flag); + s = set_->Move(*ctx_, key_, dst, field, &flag); EXPECT_TRUE(s.ok() && flag); } - s = set_->Move(key_, dst, "set-no-exists-key", &flag); + s = set_->Move(*ctx_, key_, dst, "set-no-exists-key", &flag); EXPECT_TRUE(s.ok() && !flag); - s = set_->Card(key_, &ret); + s = set_->Card(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && ret == 0); - s = set_->Card(dst, &ret); + s = set_->Card(*ctx_, dst, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = set_->Remove(dst, fields_, &ret); + s = set_->Remove(*ctx_, dst, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - s = set_->Del(dst); + s = set_->Del(*ctx_, dst); } TEST_F(RedisSetTest, TakeWithPop) { uint64_t ret = 0; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); std::vector members; - s = set_->Take(key_, &members, 3, true); + s = set_->Take(*ctx_, key_, &members, 3, true); EXPECT_TRUE(s.ok()); EXPECT_EQ(members.size(), 3); - s = set_->Take(key_, &members, 2, true); + s = set_->Take(*ctx_, key_, &members, 2, true); EXPECT_TRUE(s.ok()); EXPECT_EQ(members.size(), 1); - s = set_->Take(key_, &members, 1, true); + s = set_->Take(*ctx_, key_, &members, 1, true); EXPECT_TRUE(s.ok()); EXPECT_TRUE(s.ok() && members.size() == 0); } @@ -157,120 +157,120 @@ TEST_F(RedisSetTest, TakeWithPop) { TEST_F(RedisSetTest, Diff) { uint64_t ret = 0; std::string k1 = "key1", k2 = "key2", k3 = "key3"; - rocksdb::Status s = set_->Add(k1, {"a", "b", "c", "d"}, &ret); + rocksdb::Status s = set_->Add(*ctx_, k1, {"a", "b", "c", "d"}, &ret); EXPECT_EQ(ret, 4); - set_->Add(k2, {"c"}, &ret); + set_->Add(*ctx_, k2, {"c"}, &ret); EXPECT_EQ(ret, 1); - set_->Add(k3, {"a", "c", "e"}, &ret); + set_->Add(*ctx_, k3, {"a", "c", "e"}, &ret); EXPECT_EQ(ret, 3); std::vector members; - set_->Diff({k1, k2, k3}, &members); + set_->Diff(*ctx_, {k1, k2, k3}, &members); EXPECT_EQ(2, members.size()); - s = set_->Del(k1); - s = set_->Del(k2); - s = set_->Del(k3); + s = set_->Del(*ctx_, k1); + s = set_->Del(*ctx_, k2); + s = set_->Del(*ctx_, k3); } TEST_F(RedisSetTest, Union) { uint64_t ret = 0; std::string k1 = "key1", k2 = "key2", k3 = "key3"; - rocksdb::Status s = set_->Add(k1, {"a", "b", "c", "d"}, &ret); + rocksdb::Status s = set_->Add(*ctx_, k1, {"a", "b", "c", "d"}, &ret); EXPECT_EQ(ret, 4); - set_->Add(k2, {"c"}, &ret); + set_->Add(*ctx_, k2, {"c"}, &ret); EXPECT_EQ(ret, 1); - set_->Add(k3, {"a", "c", "e"}, &ret); + set_->Add(*ctx_, k3, {"a", "c", "e"}, &ret); EXPECT_EQ(ret, 3); std::vector members; - set_->Union({k1, k2, k3}, &members); + set_->Union(*ctx_, {k1, k2, k3}, &members); EXPECT_EQ(5, members.size()); - s = set_->Del(k1); - s = set_->Del(k2); - s = set_->Del(k3); + s = set_->Del(*ctx_, k1); + s = set_->Del(*ctx_, k2); + s = set_->Del(*ctx_, k3); } TEST_F(RedisSetTest, Inter) { uint64_t ret = 0; std::string k1 = "key1", k2 = "key2", k3 = "key3", k4 = "key4", k5 = "key5"; - rocksdb::Status s = set_->Add(k1, {"a", "b", "c", "d"}, &ret); + rocksdb::Status s = set_->Add(*ctx_, k1, {"a", "b", "c", "d"}, &ret); EXPECT_EQ(ret, 4); - set_->Add(k2, {"c"}, &ret); + set_->Add(*ctx_, k2, {"c"}, &ret); EXPECT_EQ(ret, 1); - set_->Add(k3, {"a", "c", "e"}, &ret); + set_->Add(*ctx_, k3, {"a", "c", "e"}, &ret); EXPECT_EQ(ret, 3); - set_->Add(k5, {"a"}, &ret); + set_->Add(*ctx_, k5, {"a"}, &ret); EXPECT_EQ(ret, 1); std::vector members; - set_->Inter({k1, k2, k3}, &members); + set_->Inter(*ctx_, {k1, k2, k3}, &members); EXPECT_EQ(1, members.size()); members.clear(); - set_->Inter({k1, k2, k4}, &members); + set_->Inter(*ctx_, {k1, k2, k4}, &members); EXPECT_EQ(0, members.size()); - set_->Inter({k1, k4, k5}, &members); + set_->Inter(*ctx_, {k1, k4, k5}, &members); EXPECT_EQ(0, members.size()); - s = set_->Del(k1); - s = set_->Del(k2); - s = set_->Del(k3); - s = set_->Del(k4); - s = set_->Del(k5); + s = set_->Del(*ctx_, k1); + s = set_->Del(*ctx_, k2); + s = set_->Del(*ctx_, k3); + s = set_->Del(*ctx_, k4); + s = set_->Del(*ctx_, k5); } TEST_F(RedisSetTest, InterCard) { uint64_t ret = 0; std::string k1 = "key1", k2 = "key2", k3 = "key3", k4 = "key4"; - rocksdb::Status s = set_->Add(k1, {"a", "b", "c", "d"}, &ret); + rocksdb::Status s = set_->Add(*ctx_, k1, {"a", "b", "c", "d"}, &ret); EXPECT_EQ(ret, 4); - set_->Add(k2, {"c", "d", "e"}, &ret); + set_->Add(*ctx_, k2, {"c", "d", "e"}, &ret); EXPECT_EQ(ret, 3); - set_->Add(k3, {"e", "f"}, &ret); + set_->Add(*ctx_, k3, {"e", "f"}, &ret); EXPECT_EQ(ret, 2); - set_->InterCard({k1, k2}, 0, &ret); + set_->InterCard(*ctx_, {k1, k2}, 0, &ret); EXPECT_EQ(ret, 2); - set_->InterCard({k1, k2}, 1, &ret); + set_->InterCard(*ctx_, {k1, k2}, 1, &ret); EXPECT_EQ(ret, 1); - set_->InterCard({k1, k2}, 3, &ret); + set_->InterCard(*ctx_, {k1, k2}, 3, &ret); EXPECT_EQ(ret, 2); - set_->InterCard({k2, k3}, 1, &ret); + set_->InterCard(*ctx_, {k2, k3}, 1, &ret); EXPECT_EQ(ret, 1); - set_->InterCard({k1, k3}, 5, &ret); + set_->InterCard(*ctx_, {k1, k3}, 5, &ret); EXPECT_EQ(ret, 0); - set_->InterCard({k1, k4}, 5, &ret); + set_->InterCard(*ctx_, {k1, k4}, 5, &ret); EXPECT_EQ(ret, 0); - set_->InterCard({k1}, 0, &ret); + set_->InterCard(*ctx_, {k1}, 0, &ret); EXPECT_EQ(ret, 4); for (uint32_t i = 1; i < 20; i++) { - set_->InterCard({k1}, i, &ret); + set_->InterCard(*ctx_, {k1}, i, &ret); uint64_t val = (i >= 4) ? 4 : i; EXPECT_EQ(ret, val); } - s = set_->Del(k1); - s = set_->Del(k2); - s = set_->Del(k3); - s = set_->Del(k4); + s = set_->Del(*ctx_, k1); + s = set_->Del(*ctx_, k2); + s = set_->Del(*ctx_, k3); + s = set_->Del(*ctx_, k4); } TEST_F(RedisSetTest, Overwrite) { uint64_t ret = 0; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); - set_->Overwrite(key_, {"a"}); - set_->Card(key_, &ret); + set_->Overwrite(*ctx_, key_, {"a"}); + set_->Card(*ctx_, key_, &ret); EXPECT_EQ(ret, 1); } TEST_F(RedisSetTest, TakeWithoutPop) { uint64_t ret = 0; - rocksdb::Status s = set_->Add(key_, fields_, &ret); + rocksdb::Status s = set_->Add(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); std::vector members; - s = set_->Take(key_, &members, int(fields_.size() + 1), false); + s = set_->Take(*ctx_, key_, &members, int(fields_.size() + 1), false); EXPECT_TRUE(s.ok()); EXPECT_EQ(members.size(), fields_.size()); - s = set_->Take(key_, &members, int(fields_.size() - 1), false); + s = set_->Take(*ctx_, key_, &members, int(fields_.size() - 1), false); EXPECT_TRUE(s.ok()); EXPECT_EQ(members.size(), fields_.size() - 1); - s = set_->Take(key_, &members, -int(fields_.size() - 1), false); + s = set_->Take(*ctx_, key_, &members, -int(fields_.size() - 1), false); EXPECT_TRUE(s.ok()); EXPECT_EQ(members.size(), fields_.size() - 1); - s = set_->Remove(key_, fields_, &ret); + s = set_->Remove(*ctx_, key_, fields_, &ret); EXPECT_TRUE(s.ok() && fields_.size() == ret); } diff --git a/tests/cppunit/types/sortedint_test.cc b/tests/cppunit/types/sortedint_test.cc index 79f0da78e95..3fc25dc49fe 100644 --- a/tests/cppunit/types/sortedint_test.cc +++ b/tests/cppunit/types/sortedint_test.cc @@ -41,28 +41,28 @@ class RedisSortedintTest : public TestBase { TEST_F(RedisSortedintTest, AddAndRemove) { uint64_t ret = 0; - rocksdb::Status s = sortedint_->Add(key_, ids_, &ret); + rocksdb::Status s = sortedint_->Add(*ctx_, key_, ids_, &ret); EXPECT_TRUE(s.ok() && ids_.size() == ret); - s = sortedint_->Card(key_, &ret); + s = sortedint_->Card(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && ids_.size() == ret); - s = sortedint_->Remove(key_, ids_, &ret); + s = sortedint_->Remove(*ctx_, key_, ids_, &ret); EXPECT_TRUE(s.ok() && ids_.size() == ret); - s = sortedint_->Card(key_, &ret); + s = sortedint_->Card(*ctx_, key_, &ret); EXPECT_TRUE(s.ok() && ret == 0); - s = sortedint_->Del(key_); + s = sortedint_->Del(*ctx_, key_); } TEST_F(RedisSortedintTest, Range) { uint64_t ret = 0; - rocksdb::Status s = sortedint_->Add(key_, ids_, &ret); + rocksdb::Status s = sortedint_->Add(*ctx_, key_, ids_, &ret); EXPECT_TRUE(s.ok() && ids_.size() == ret); std::vector ids; - s = sortedint_->Range(key_, 0, 0, 20, false, &ids); + s = sortedint_->Range(*ctx_, key_, 0, 0, 20, false, &ids); EXPECT_TRUE(s.ok() && ids_.size() == ids.size()); for (size_t i = 0; i < ids_.size(); i++) { EXPECT_EQ(ids_[i], ids[i]); } - s = sortedint_->Remove(key_, ids_, &ret); + s = sortedint_->Remove(*ctx_, key_, ids_, &ret); EXPECT_TRUE(s.ok() && ids_.size() == ret); - s = sortedint_->Del(key_); + s = sortedint_->Del(*ctx_, key_); } diff --git a/tests/cppunit/types/stream_test.cc b/tests/cppunit/types/stream_test.cc index f522b8273c5..c09574dc0d9 100644 --- a/tests/cppunit/types/stream_test.cc +++ b/tests/cppunit/types/stream_test.cc @@ -44,9 +44,8 @@ class RedisStreamTest : public TestBase { // NOLINT ~RedisStreamTest() override { delete stream_; } - void SetUp() override { auto s = stream_->Del(name_); } - - void TearDown() override { auto s = stream_->Del(name_); } + void SetUp() override { auto s = stream_->Del(*ctx_, name_); } + void TearDown() override { auto s = stream_->Del(*ctx_, name_); } std::string name_; redis::Stream *stream_; @@ -260,7 +259,7 @@ TEST_F(RedisStreamTest, AddEntryToNonExistingStreamWithNomkstreamOption) { options.nomkstream = true; std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.IsNotFound()); } @@ -269,7 +268,7 @@ TEST_F(RedisStreamTest, AddEntryPredefinedIDAsZeroZero) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy("0-0"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(!s.ok()); } @@ -278,7 +277,7 @@ TEST_F(RedisStreamTest, AddEntryWithPredefinedIDAsZeroMsAndAnySeq) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy("0-*"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); EXPECT_EQ(id.ToString(), "0-1"); } @@ -288,7 +287,7 @@ TEST_F(RedisStreamTest, AddFirstEntryWithoutPredefinedID) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); EXPECT_EQ(id.seq, 0); EXPECT_TRUE(id.ms <= util::GetTimeStampMS()); @@ -300,7 +299,7 @@ TEST_F(RedisStreamTest, AddEntryFirstEntryWithPredefinedID) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", expected_id.ms, expected_id.seq)); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); EXPECT_EQ(id.ms, expected_id.ms); EXPECT_EQ(id.seq, expected_id.seq); @@ -312,7 +311,7 @@ TEST_F(RedisStreamTest, AddFirstEntryWithPredefinedNonZeroMsAndAnySeqNo) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-*", ms)); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); EXPECT_EQ(id.ms, ms); EXPECT_EQ(id.seq, 0); @@ -323,12 +322,12 @@ TEST_F(RedisStreamTest, AddEntryToNonEmptyStreamWithPredefinedMsAndAnySeqNo) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12345, 678)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, options, values1, &id1); EXPECT_TRUE(s.ok()); options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12346-*"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, options, values2, &id2); + s = stream_->Add(*ctx_, name_, options, values2, &id2); EXPECT_TRUE(s.ok()); EXPECT_EQ(id2.ToString(), "12346-0"); } @@ -340,10 +339,10 @@ TEST_F(RedisStreamTest, AddEntryWithPredefinedButExistingMsAndAnySeqNo) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", ms, seq)); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-*", ms)); - s = stream_->Add(name_, options, values, &id); + s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); EXPECT_EQ(id.ms, ms); EXPECT_EQ(id.seq, seq + 1); @@ -356,10 +355,10 @@ TEST_F(RedisStreamTest, AddEntryWithExistingMsAnySeqNoAndExistingSeqNoIsAlreadyM options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", ms, seq)); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-*", ms)); - s = stream_->Add(name_, options, values, &id); + s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(!s.ok()); } @@ -370,10 +369,10 @@ TEST_F(RedisStreamTest, AddEntryAndExistingMsAndSeqNoAreAlreadyMax) { options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", ms, seq)); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, options, values, &id); + auto s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(s.ok()); options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); - s = stream_->Add(name_, options, values, &id); + s = stream_->Add(*ctx_, name_, options, values, &id); EXPECT_TRUE(!s.ok()); } @@ -382,12 +381,12 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMaxLenStrategy) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions trim_options; @@ -396,14 +395,14 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMaxLenStrategy) { add_options.trim_options = trim_options; redis::StreamEntryID id3; std::vector values3 = {"key3", "val3"}; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -417,12 +416,12 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMaxLenStrategyThatDeletesAddedEntry) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions trim_options; @@ -431,14 +430,14 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMaxLenStrategyThatDeletesAddedEntry) { add_options.trim_options = trim_options; redis::StreamEntryID id3; std::vector values3 = {"key3", "val3"}; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -448,12 +447,12 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMinIdStrategy) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12345, 0)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12346, 0)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions trim_options; @@ -463,14 +462,14 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMinIdStrategy) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12347-0"); redis::StreamEntryID id3; std::vector values3 = {"key3", "val3"}; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -484,12 +483,12 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMinIdStrategyThatDeletesAddedEntry) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12345, 0)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12346, 0)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions trim_options; @@ -499,14 +498,14 @@ TEST_F(RedisStreamTest, AddEntryWithTrimMinIdStrategyThatDeletesAddedEntry) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12347, 0)); redis::StreamEntryID id3; std::vector values3 = {"key3", "val3"}; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -516,7 +515,7 @@ TEST_F(RedisStreamTest, RangeOnNonExistingStream) { options.start = redis::StreamEntryID{0, 0}; options.end = redis::StreamEntryID{1234567, 0}; std::vector entries; - auto s = stream_->Range(name_, options, &entries); + auto s = stream_->Range(*ctx_, name_, options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -526,17 +525,17 @@ TEST_F(RedisStreamTest, RangeOnEmptyStream) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("*"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); uint64_t removed = 0; - s = stream_->DeleteEntries(name_, {id}, &removed); + s = stream_->DeleteEntries(*ctx_, name_, {id}, &removed); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -546,24 +545,24 @@ TEST_F(RedisStreamTest, RangeWithStartAndEndSameMs) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12345678, 0)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12345678, 1)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 12345679, 0)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID{12345678, 0}; range_options.end = redis::StreamEntryID{12345678, UINT64_MAX}; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id1.ToString()); @@ -577,29 +576,29 @@ TEST_F(RedisStreamTest, RangeInterval) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID{123456, 0}; range_options.end = redis::StreamEntryID{123459, 0}; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 3); EXPECT_EQ(entries[0].key, id1.ToString()); @@ -615,29 +614,29 @@ TEST_F(RedisStreamTest, RangeFromMinimumToMaximum) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 4); EXPECT_EQ(entries[0].key, id1.ToString()); @@ -655,19 +654,19 @@ TEST_F(RedisStreamTest, RangeFromMinimumToMinimum) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Minimum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -677,19 +676,19 @@ TEST_F(RedisStreamTest, RangeWithStartGreaterThanEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = redis::StreamEntryID::Maximum(); range_options.end = redis::StreamEntryID::Minimum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -699,19 +698,19 @@ TEST_F(RedisStreamTest, RangeWithStartAndEndAreEqual) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; range_options.start = id2; range_options.end = id2; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 1); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -723,12 +722,12 @@ TEST_F(RedisStreamTest, RangeWithStartAndEndAreEqualAndExcludedStart) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -736,7 +735,7 @@ TEST_F(RedisStreamTest, RangeWithStartAndEndAreEqualAndExcludedStart) { range_options.exclude_start = true; range_options.end = id2; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -746,12 +745,12 @@ TEST_F(RedisStreamTest, RangeWithStartAndEndAreEqualAndExcludedEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -759,7 +758,7 @@ TEST_F(RedisStreamTest, RangeWithStartAndEndAreEqualAndExcludedEnd) { range_options.end = id2; range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -769,22 +768,22 @@ TEST_F(RedisStreamTest, RangeWithExcludedStart) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -792,7 +791,7 @@ TEST_F(RedisStreamTest, RangeWithExcludedStart) { range_options.exclude_start = true; range_options.end = redis::StreamEntryID{123458, 3}; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -806,22 +805,22 @@ TEST_F(RedisStreamTest, RangeWithExcludedEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -829,7 +828,7 @@ TEST_F(RedisStreamTest, RangeWithExcludedEnd) { range_options.end = redis::StreamEntryID{123459, 4}; range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -843,22 +842,22 @@ TEST_F(RedisStreamTest, RangeWithExcludedStartAndExcludedEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -867,7 +866,7 @@ TEST_F(RedisStreamTest, RangeWithExcludedStartAndExcludedEnd) { range_options.end = redis::StreamEntryID{123459, 4}; range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -881,7 +880,7 @@ TEST_F(RedisStreamTest, RangeWithStartAsMaximumAndExclusion) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -889,7 +888,7 @@ TEST_F(RedisStreamTest, RangeWithStartAsMaximumAndExclusion) { range_options.exclude_start = true; range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(!s.ok()); } @@ -898,7 +897,7 @@ TEST_F(RedisStreamTest, RangeWithEndAsMinimumAndExclusion) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -906,7 +905,7 @@ TEST_F(RedisStreamTest, RangeWithEndAsMinimumAndExclusion) { range_options.end = redis::StreamEntryID::Minimum(); range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(!s.ok()); } @@ -915,22 +914,22 @@ TEST_F(RedisStreamTest, RangeWithCountEqualToZero) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -939,7 +938,7 @@ TEST_F(RedisStreamTest, RangeWithCountEqualToZero) { range_options.with_count = true; range_options.count = 0; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -949,22 +948,22 @@ TEST_F(RedisStreamTest, RangeWithCountGreaterThanRequiredElements) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -973,7 +972,7 @@ TEST_F(RedisStreamTest, RangeWithCountGreaterThanRequiredElements) { range_options.with_count = true; range_options.count = 3; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 3); EXPECT_EQ(entries[0].key, id1.ToString()); @@ -989,22 +988,22 @@ TEST_F(RedisStreamTest, RangeWithCountLessThanRequiredElements) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123456, 1)); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123457, 2)); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123458, 3)); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy(fmt::format("{}-{}", 123459, 4)); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1013,7 +1012,7 @@ TEST_F(RedisStreamTest, RangeWithCountLessThanRequiredElements) { range_options.with_count = true; range_options.count = 2; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id1.ToString()); @@ -1027,17 +1026,17 @@ TEST_F(RedisStreamTest, RevRangeWithStartAndEndSameMs) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345678-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345678-1"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345679-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1045,7 +1044,7 @@ TEST_F(RedisStreamTest, RevRangeWithStartAndEndSameMs) { range_options.start = redis::StreamEntryID{12345678, UINT64_MAX}; range_options.end = redis::StreamEntryID{12345678, 0}; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -1059,22 +1058,22 @@ TEST_F(RedisStreamTest, RevRangeInterval) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-3"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-4"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1082,7 +1081,7 @@ TEST_F(RedisStreamTest, RevRangeInterval) { range_options.start = redis::StreamEntryID{123459, 0}; range_options.end = redis::StreamEntryID{123456, 0}; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 3); EXPECT_EQ(entries[0].key, id3.ToString()); @@ -1098,22 +1097,22 @@ TEST_F(RedisStreamTest, RevRangeFromMaximumToMinimum) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-3"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-4"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1121,7 +1120,7 @@ TEST_F(RedisStreamTest, RevRangeFromMaximumToMinimum) { range_options.start = redis::StreamEntryID::Maximum(); range_options.end = redis::StreamEntryID::Minimum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 4); EXPECT_EQ(entries[0].key, id4.ToString()); @@ -1139,12 +1138,12 @@ TEST_F(RedisStreamTest, RevRangeFromMinimumToMinimum) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1152,7 +1151,7 @@ TEST_F(RedisStreamTest, RevRangeFromMinimumToMinimum) { range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Minimum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -1162,12 +1161,12 @@ TEST_F(RedisStreamTest, RevRangeWithStartLessThanEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1175,7 +1174,7 @@ TEST_F(RedisStreamTest, RevRangeWithStartLessThanEnd) { range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -1185,12 +1184,12 @@ TEST_F(RedisStreamTest, RevRangeStartAndEndAreEqual) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1198,7 +1197,7 @@ TEST_F(RedisStreamTest, RevRangeStartAndEndAreEqual) { range_options.start = id2; range_options.end = id2; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 1); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -1210,12 +1209,12 @@ TEST_F(RedisStreamTest, RevRangeStartAndEndAreEqualAndExcludedStart) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1224,7 +1223,7 @@ TEST_F(RedisStreamTest, RevRangeStartAndEndAreEqualAndExcludedStart) { range_options.exclude_start = true; range_options.end = id2; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -1234,12 +1233,12 @@ TEST_F(RedisStreamTest, RevRangeStartAndEndAreEqualAndExcludedEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1248,7 +1247,7 @@ TEST_F(RedisStreamTest, RevRangeStartAndEndAreEqualAndExcludedEnd) { range_options.end = id2; range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 0); } @@ -1258,22 +1257,22 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedStart) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-3"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-4"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1282,7 +1281,7 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedStart) { range_options.exclude_start = true; range_options.end = redis::StreamEntryID{123456, 1}; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -1296,22 +1295,22 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-3"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-4"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1320,7 +1319,7 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedEnd) { range_options.end = redis::StreamEntryID{123456, 1}; range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id3.ToString()); @@ -1334,22 +1333,22 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedStartAndExcludedEnd) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-1"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-2"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-3"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-4"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamRangeOptions range_options; @@ -1359,7 +1358,7 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedStartAndExcludedEnd) { range_options.end = redis::StreamEntryID{123456, 1}; range_options.exclude_end = true; std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id3.ToString()); @@ -1371,7 +1370,7 @@ TEST_F(RedisStreamTest, RevRangeWithExcludedStartAndExcludedEnd) { TEST_F(RedisStreamTest, DeleteFromNonExistingStream) { std::vector ids = {redis::StreamEntryID{12345, 6789}}; uint64_t deleted = 0; - auto s = stream_->DeleteEntries(name_, ids, &deleted); + auto s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); EXPECT_EQ(deleted, 0); } @@ -1381,12 +1380,12 @@ TEST_F(RedisStreamTest, DeleteExistingEntry) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); std::vector ids = {id}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); EXPECT_EQ(deleted, 1); } @@ -1396,12 +1395,12 @@ TEST_F(RedisStreamTest, DeleteNonExistingEntry) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); std::vector ids = {redis::StreamEntryID{123, 456}}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); EXPECT_EQ(deleted, 0); } @@ -1411,28 +1410,28 @@ TEST_F(RedisStreamTest, DeleteMultipleEntries) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); std::vector ids = {redis::StreamEntryID{123456, 0}, redis::StreamEntryID{1234567, 89}, redis::StreamEntryID{123458, 0}}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); EXPECT_EQ(deleted, 2); @@ -1440,7 +1439,7 @@ TEST_F(RedisStreamTest, DeleteMultipleEntries) { range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id2.ToString()); @@ -1451,7 +1450,7 @@ TEST_F(RedisStreamTest, DeleteMultipleEntries) { TEST_F(RedisStreamTest, LenOnNonExistingStream) { uint64_t length = 0; - auto s = stream_->Len(name_, redis::StreamLenOptions{}, &length); + auto s = stream_->Len(*ctx_, name_, redis::StreamLenOptions{}, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); } @@ -1461,16 +1460,16 @@ TEST_F(RedisStreamTest, LenOnEmptyStream) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); std::vector ids = {id}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); uint64_t length = 0; - s = stream_->Len(name_, redis::StreamLenOptions{}, &length); + s = stream_->Len(*ctx_, name_, redis::StreamLenOptions{}, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); } @@ -1480,16 +1479,16 @@ TEST_F(RedisStreamTest, Len) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); uint64_t length = 0; - s = stream_->Len(name_, redis::StreamLenOptions{}, &length); + s = stream_->Len(*ctx_, name_, redis::StreamLenOptions{}, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 2); } @@ -1498,23 +1497,23 @@ TEST_F(RedisStreamTest, LenWithStartOptionGreaterThanLastEntryID) { redis::StreamAddOptions add_options; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, {"key1", "val1"}, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, {"key1", "val1"}, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, {"key2", "val2"}, &id2); + s = stream_->Add(*ctx_, name_, add_options, {"key2", "val2"}, &id2); EXPECT_TRUE(s.ok()); uint64_t length = 0; redis::StreamLenOptions len_options; len_options.with_entry_id = true; len_options.entry_id = redis::StreamEntryID{id2.ms + 10, 0}; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); len_options.to_first = true; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 2); } @@ -1523,23 +1522,23 @@ TEST_F(RedisStreamTest, LenWithStartOptionEqualToLastEntryID) { redis::StreamAddOptions add_options; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, {"key1", "val1"}, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, {"key1", "val1"}, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, {"key2", "val2"}, &id2); + s = stream_->Add(*ctx_, name_, add_options, {"key2", "val2"}, &id2); EXPECT_TRUE(s.ok()); uint64_t length = 0; redis::StreamLenOptions len_options; len_options.with_entry_id = true; len_options.entry_id = redis::StreamEntryID{id2.ms, id2.seq}; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); len_options.to_first = true; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 1); } @@ -1548,23 +1547,23 @@ TEST_F(RedisStreamTest, LenWithStartOptionLessThanFirstEntryID) { redis::StreamAddOptions add_options; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, {"key1", "val1"}, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, {"key1", "val1"}, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, {"key2", "val2"}, &id2); + s = stream_->Add(*ctx_, name_, add_options, {"key2", "val2"}, &id2); EXPECT_TRUE(s.ok()); uint64_t length = 0; redis::StreamLenOptions len_options; len_options.with_entry_id = true; len_options.entry_id = redis::StreamEntryID{123, 0}; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 2); len_options.to_first = true; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); } @@ -1573,23 +1572,23 @@ TEST_F(RedisStreamTest, LenWithStartOptionEqualToFirstEntryID) { redis::StreamAddOptions add_options; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, {"key1", "val1"}, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, {"key1", "val1"}, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, {"key2", "val2"}, &id2); + s = stream_->Add(*ctx_, name_, add_options, {"key2", "val2"}, &id2); EXPECT_TRUE(s.ok()); uint64_t length = 0; redis::StreamLenOptions len_options; len_options.with_entry_id = true; len_options.entry_id = id1; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 1); len_options.to_first = true; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); } @@ -1598,31 +1597,31 @@ TEST_F(RedisStreamTest, LenWithStartOptionEqualToExistingEntryID) { redis::StreamAddOptions add_options; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, {"key1", "val1"}, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, {"key1", "val1"}, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, {"key2", "val2"}, &id2); + s = stream_->Add(*ctx_, name_, add_options, {"key2", "val2"}, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, {"key3", "val3"}, &id3); + s = stream_->Add(*ctx_, name_, add_options, {"key3", "val3"}, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, {"key4", "val4"}, &id4); + s = stream_->Add(*ctx_, name_, add_options, {"key4", "val4"}, &id4); EXPECT_TRUE(s.ok()); uint64_t length = 0; redis::StreamLenOptions len_options; len_options.with_entry_id = true; len_options.entry_id = id2; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 2); len_options.to_first = true; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 1); } @@ -1631,31 +1630,31 @@ TEST_F(RedisStreamTest, LenWithStartOptionNotEqualToExistingEntryID) { redis::StreamAddOptions add_options; add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, {"key1", "val1"}, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, {"key1", "val1"}, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, {"key2", "val2"}, &id2); + s = stream_->Add(*ctx_, name_, add_options, {"key2", "val2"}, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, {"key3", "val3"}, &id3); + s = stream_->Add(*ctx_, name_, add_options, {"key3", "val3"}, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, {"key4", "val4"}, &id4); + s = stream_->Add(*ctx_, name_, add_options, {"key4", "val4"}, &id4); EXPECT_TRUE(s.ok()); uint64_t length = 0; redis::StreamLenOptions len_options; len_options.with_entry_id = true; len_options.entry_id = redis::StreamEntryID{id1.ms, id1.seq + 10}; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 3); len_options.to_first = true; - s = stream_->Len(name_, len_options, &length); + s = stream_->Len(*ctx_, name_, len_options, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 1); } @@ -1665,7 +1664,7 @@ TEST_F(RedisStreamTest, TrimNonExistingStream) { options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 10; uint64_t trimmed = 0; - auto s = stream_->Trim(name_, options, &trimmed); + auto s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1675,18 +1674,18 @@ TEST_F(RedisStreamTest, TrimEmptyStream) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); std::vector ids = {id}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 10; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1696,13 +1695,13 @@ TEST_F(RedisStreamTest, TrimWithNoStrategySpecified) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.min_id = redis::StreamEntryID{123456, 0}; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1712,29 +1711,29 @@ TEST_F(RedisStreamTest, TrimWithMaxLenGreaterThanStreamSize) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 10; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1744,29 +1743,29 @@ TEST_F(RedisStreamTest, TrimWithMaxLenEqualToStreamSize) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 4; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1776,29 +1775,29 @@ TEST_F(RedisStreamTest, TrimWithMaxLenLessThanStreamSize) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 2; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 2); @@ -1806,7 +1805,7 @@ TEST_F(RedisStreamTest, TrimWithMaxLenLessThanStreamSize) { range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id3.ToString()); @@ -1820,29 +1819,29 @@ TEST_F(RedisStreamTest, TrimWithMaxLenEqualTo1) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 1; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 3); @@ -1850,7 +1849,7 @@ TEST_F(RedisStreamTest, TrimWithMaxLenEqualTo1) { range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 1); EXPECT_EQ(entries[0].key, id4.ToString()); @@ -1862,33 +1861,33 @@ TEST_F(RedisStreamTest, TrimWithMaxLenZero) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 0; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 4); uint64_t length = 0; - s = stream_->Len(name_, redis::StreamLenOptions{}, &length); + s = stream_->Len(*ctx_, name_, redis::StreamLenOptions{}, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); } @@ -1898,19 +1897,19 @@ TEST_F(RedisStreamTest, TrimWithMinIdLessThanFirstEntryID) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MinID; options.min_id = redis::StreamEntryID{12345, 0}; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1920,19 +1919,19 @@ TEST_F(RedisStreamTest, TrimWithMinIdEqualToFirstEntryID) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MinID; options.min_id = redis::StreamEntryID{123456, 0}; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 0); } @@ -1942,29 +1941,29 @@ TEST_F(RedisStreamTest, TrimWithMinId) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MinID; options.min_id = redis::StreamEntryID{123457, 10}; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 2); @@ -1972,7 +1971,7 @@ TEST_F(RedisStreamTest, TrimWithMinId) { range_options.start = redis::StreamEntryID::Minimum(); range_options.end = redis::StreamEntryID::Maximum(); std::vector entries; - s = stream_->Range(name_, range_options, &entries); + s = stream_->Range(*ctx_, name_, range_options, &entries); EXPECT_TRUE(s.ok()); EXPECT_EQ(entries.size(), 2); EXPECT_EQ(entries[0].key, id3.ToString()); @@ -1986,41 +1985,41 @@ TEST_F(RedisStreamTest, TrimWithMinIdGreaterThanLastEntryID) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MinID; options.min_id = redis::StreamEntryID{12345678, 0}; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); EXPECT_EQ(trimmed, 4); uint64_t length = 0; - s = stream_->Len(name_, redis::StreamLenOptions{}, &length); + s = stream_->Len(*ctx_, name_, redis::StreamLenOptions{}, &length); EXPECT_TRUE(s.ok()); EXPECT_EQ(length, 0); } TEST_F(RedisStreamTest, StreamInfoOnNonExistingStream) { redis::StreamInfo info; - auto s = stream_->GetStreamInfo(name_, false, 0, &info); + auto s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.IsNotFound()); } @@ -2029,16 +2028,16 @@ TEST_F(RedisStreamTest, StreamInfoOnEmptyStream) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); std::vector ids = {id}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 0); EXPECT_EQ(info.last_generated_id.ToString(), id.ToString()); @@ -2054,11 +2053,11 @@ TEST_F(RedisStreamTest, StreamInfoOneEntry) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("12345-6789"); std::vector values = {"key1", "val1"}; redis::StreamEntryID id; - auto s = stream_->Add(name_, add_options, values, &id); + auto s = stream_->Add(*ctx_, name_, add_options, values, &id); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 1); EXPECT_EQ(info.last_generated_id.ToString(), id.ToString()); @@ -2078,21 +2077,21 @@ TEST_F(RedisStreamTest, StreamInfoOnStreamWithElements) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 3); EXPECT_EQ(info.last_generated_id.ToString(), id3.ToString()); @@ -2113,21 +2112,21 @@ TEST_F(RedisStreamTest, StreamInfoOnStreamWithElementsFullOption) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, true, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, true, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 3); EXPECT_EQ(info.last_generated_id.ToString(), id3.ToString()); @@ -2150,26 +2149,26 @@ TEST_F(RedisStreamTest, StreamInfoCheckAfterLastEntryDeletion) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); std::vector ids = {id3}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 2); EXPECT_EQ(info.last_generated_id.ToString(), id3.ToString()); @@ -2190,26 +2189,26 @@ TEST_F(RedisStreamTest, StreamInfoCheckAfterFirstEntryDeletion) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); std::vector ids = {id1}; uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, ids, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, ids, &deleted); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 2); EXPECT_EQ(info.last_generated_id.ToString(), id3.ToString()); @@ -2230,33 +2229,33 @@ TEST_F(RedisStreamTest, StreamInfoCheckAfterTrimMinId) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MinID; options.min_id = redis::StreamEntryID{123458, 0}; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 2); EXPECT_EQ(info.last_generated_id.ToString(), id4.ToString()); @@ -2277,33 +2276,33 @@ TEST_F(RedisStreamTest, StreamInfoCheckAfterTrimMaxLen) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 2; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 2); EXPECT_EQ(info.last_generated_id.ToString(), id4.ToString()); @@ -2324,33 +2323,33 @@ TEST_F(RedisStreamTest, StreamInfoCheckAfterTrimAllEntries) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123457-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - s = stream_->Add(name_, add_options, values2, &id2); + s = stream_->Add(*ctx_, name_, add_options, values2, &id2); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123458-0"); std::vector values3 = {"key3", "val3"}; redis::StreamEntryID id3; - s = stream_->Add(name_, add_options, values3, &id3); + s = stream_->Add(*ctx_, name_, add_options, values3, &id3); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123459-0"); std::vector values4 = {"key4", "val4"}; redis::StreamEntryID id4; - s = stream_->Add(name_, add_options, values4, &id4); + s = stream_->Add(*ctx_, name_, add_options, values4, &id4); EXPECT_TRUE(s.ok()); redis::StreamTrimOptions options; options.strategy = redis::StreamTrimStrategy::MaxLen; options.max_len = 0; uint64_t trimmed = 0; - s = stream_->Trim(name_, options, &trimmed); + s = stream_->Trim(*ctx_, name_, options, &trimmed); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.size, 0); EXPECT_EQ(info.last_generated_id.ToString(), id4.ToString()); @@ -2366,20 +2365,20 @@ TEST_F(RedisStreamTest, StreamSetIdNonExistingStreamCreatesEmptyStream) { redis::StreamEntryID last_id(5, 0); std::optional max_del_id = redis::StreamEntryID{2, 0}; uint64_t entries_added = 3; - auto s = stream_->SetId("some-non-existing-stream1", last_id, entries_added, max_del_id); + auto s = stream_->SetId(*ctx_, "some-non-existing-stream1", last_id, entries_added, max_del_id); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo("some-non-existing-stream1", false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, "some-non-existing-stream1", false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.last_generated_id.ToString(), last_id.ToString()); EXPECT_EQ(info.entries_added, entries_added); EXPECT_EQ(info.max_deleted_entry_id.ToString(), max_del_id->ToString()); - s = stream_->SetId("some-non-existing-stream2", last_id, std::nullopt, max_del_id); + s = stream_->SetId(*ctx_, "some-non-existing-stream2", last_id, std::nullopt, max_del_id); EXPECT_FALSE(s.ok()); - s = stream_->SetId("some-non-existing-stream3", last_id, entries_added, std::nullopt); + s = stream_->SetId(*ctx_, "some-non-existing-stream3", last_id, entries_added, std::nullopt); EXPECT_FALSE(s.ok()); } @@ -2388,10 +2387,10 @@ TEST_F(RedisStreamTest, StreamSetIdLastIdLessThanExisting) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); - s = stream_->SetId(name_, {1, 0}, std::nullopt, std::nullopt); + s = stream_->SetId(*ctx_, name_, {1, 0}, std::nullopt, std::nullopt); EXPECT_FALSE(s.ok()); } @@ -2400,15 +2399,15 @@ TEST_F(RedisStreamTest, StreamSetIdEntriesAddedLessThanStreamSize) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values2 = {"key2", "val2"}; redis::StreamEntryID id2; - stream_->Add(name_, add_options, values1, &id1); + stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); - s = stream_->SetId(name_, {id2.ms + 1, 0}, 1, std::nullopt); + s = stream_->SetId(*ctx_, name_, {id2.ms + 1, 0}, 1, std::nullopt); EXPECT_FALSE(s.ok()); } @@ -2417,10 +2416,10 @@ TEST_F(RedisStreamTest, StreamSetIdLastIdEqualToExisting) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); - s = stream_->SetId(name_, {id1.ms, id1.seq}, std::nullopt, std::nullopt); + s = stream_->SetId(*ctx_, name_, {id1.ms, id1.seq}, std::nullopt, std::nullopt); EXPECT_TRUE(s.ok()); } @@ -2429,18 +2428,18 @@ TEST_F(RedisStreamTest, StreamSetIdMaxDeletedIdLessThanCurrent) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, {id1}, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, {id1}, &deleted); EXPECT_TRUE(s.ok()); std::optional max_del_id = redis::StreamEntryID{1, 0}; - s = stream_->SetId(name_, {id1.ms, id1.seq}, std::nullopt, max_del_id); + s = stream_->SetId(*ctx_, name_, {id1.ms, id1.seq}, std::nullopt, max_del_id); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.max_deleted_entry_id.ToString(), max_del_id->ToString()); } @@ -2450,18 +2449,18 @@ TEST_F(RedisStreamTest, StreamSetIdMaxDeletedIdIsZero) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, {id1}, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, {id1}, &deleted); EXPECT_TRUE(s.ok()); std::optional max_del_id = redis::StreamEntryID{0, 0}; - s = stream_->SetId(name_, {id1.ms, id1.seq}, std::nullopt, max_del_id); + s = stream_->SetId(*ctx_, name_, {id1.ms, id1.seq}, std::nullopt, max_del_id); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.max_deleted_entry_id.ToString(), id1.ToString()); } @@ -2471,14 +2470,14 @@ TEST_F(RedisStreamTest, StreamSetIdMaxDeletedIdGreaterThanLastGeneratedId) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); uint64_t deleted = 0; - s = stream_->DeleteEntries(name_, {id1}, &deleted); + s = stream_->DeleteEntries(*ctx_, name_, {id1}, &deleted); EXPECT_TRUE(s.ok()); std::optional max_del_id = redis::StreamEntryID{id1.ms + 1, 0}; - s = stream_->SetId(name_, {id1.ms, id1.seq}, std::nullopt, max_del_id); + s = stream_->SetId(*ctx_, name_, {id1.ms, id1.seq}, std::nullopt, max_del_id); EXPECT_FALSE(s.ok()); } @@ -2487,27 +2486,27 @@ TEST_F(RedisStreamTest, StreamSetIdLastIdGreaterThanExisting) { add_options.next_id_strategy = *ParseNextStreamEntryIDStrategy("123456-0"); std::vector values1 = {"key1", "val1"}; redis::StreamEntryID id1; - auto s = stream_->Add(name_, add_options, values1, &id1); + auto s = stream_->Add(*ctx_, name_, add_options, values1, &id1); EXPECT_TRUE(s.ok()); - s = stream_->SetId(name_, {id1.ms + 1, id1.seq}, std::nullopt, std::nullopt); + s = stream_->SetId(*ctx_, name_, {id1.ms + 1, id1.seq}, std::nullopt, std::nullopt); EXPECT_TRUE(s.ok()); uint64_t added = 10; - s = stream_->SetId(name_, {id1.ms + 1, id1.seq}, added, std::nullopt); + s = stream_->SetId(*ctx_, name_, {id1.ms + 1, id1.seq}, added, std::nullopt); EXPECT_TRUE(s.ok()); redis::StreamInfo info; - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.entries_added, added); added = 5; std::optional max_del_id = redis::StreamEntryID{5, 0}; - s = stream_->SetId(name_, {id1.ms + 1, id1.seq}, added, max_del_id); + s = stream_->SetId(*ctx_, name_, {id1.ms + 1, id1.seq}, added, max_del_id); EXPECT_TRUE(s.ok()); - s = stream_->GetStreamInfo(name_, false, 0, &info); + s = stream_->GetStreamInfo(*ctx_, name_, false, 0, &info); EXPECT_TRUE(s.ok()); EXPECT_EQ(info.entries_added, added); EXPECT_EQ(info.max_deleted_entry_id.ToString(), max_del_id->ToString()); @@ -2517,12 +2516,12 @@ TEST_F(RedisStreamTest, StreamConsumerGroupCreateAndDestroy) { redis::StreamXGroupCreateOptions create_options = {true, 0, "$"}; std::string stream_name = "TestStream"; std::string group_name = "TestGroup"; - auto s = stream_->CreateGroup(stream_name, create_options, group_name); + auto s = stream_->CreateGroup(*ctx_, stream_name, create_options, group_name); EXPECT_TRUE(s.ok()); uint64_t delete_cnt = 0; - s = stream_->DestroyGroup(stream_name, group_name, &delete_cnt); + s = stream_->DestroyGroup(*ctx_, stream_name, group_name, &delete_cnt); EXPECT_TRUE(delete_cnt != 0); delete_cnt = 0; - s = stream_->DestroyGroup(stream_name, group_name, &delete_cnt); + s = stream_->DestroyGroup(*ctx_, stream_name, group_name, &delete_cnt); EXPECT_TRUE(delete_cnt == 0); } diff --git a/tests/cppunit/types/string_test.cc b/tests/cppunit/types/string_test.cc index 3fed5ce8944..386aebb31d9 100644 --- a/tests/cppunit/types/string_test.cc +++ b/tests/cppunit/types/string_test.cc @@ -47,93 +47,93 @@ class RedisStringTest : public TestBase { TEST_F(RedisStringTest, Append) { uint64_t ret = 0; for (size_t i = 0; i < 32; i++) { - rocksdb::Status s = string_->Append(key_, "a", &ret); + rocksdb::Status s = string_->Append(*ctx_, key_, "a", &ret); EXPECT_TRUE(s.ok()); EXPECT_EQ(static_cast(i + 1), ret); } - auto s = string_->Del(key_); + auto s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, GetAndSet) { for (auto &pair : pairs_) { - string_->Set(pair.key.ToString(), pair.value.ToString()); + string_->Set(*ctx_, pair.key.ToString(), pair.value.ToString()); } for (auto &pair : pairs_) { std::string got_value; - string_->Get(pair.key.ToString(), &got_value); + string_->Get(*ctx_, pair.key.ToString(), &got_value); EXPECT_EQ(pair.value, got_value); } for (auto &pair : pairs_) { - auto s = string_->Del(pair.key); + auto s = string_->Del(*ctx_, pair.key); } } TEST_F(RedisStringTest, MGetAndMSet) { - string_->MSet(pairs_, 0); + string_->MSet(*ctx_, pairs_, 0); std::vector keys; std::vector values; keys.reserve(pairs_.size()); for (const auto &pair : pairs_) { keys.emplace_back(pair.key); } - string_->MGet(keys, &values); + string_->MGet(*ctx_, keys, &values); for (size_t i = 0; i < pairs_.size(); i++) { EXPECT_EQ(pairs_[i].value, values[i]); } for (auto &pair : pairs_) { - auto s = string_->Del(pair.key); + auto s = string_->Del(*ctx_, pair.key); } } TEST_F(RedisStringTest, IncrByFloat) { double f = 0.0; double max_float = std::numeric_limits::max(); - string_->IncrByFloat(key_, 1.0, &f); + string_->IncrByFloat(*ctx_, key_, 1.0, &f); EXPECT_EQ(1.0, f); - string_->IncrByFloat(key_, max_float - 1, &f); + string_->IncrByFloat(*ctx_, key_, max_float - 1, &f); EXPECT_EQ(max_float, f); - string_->IncrByFloat(key_, 1.2, &f); + string_->IncrByFloat(*ctx_, key_, 1.2, &f); EXPECT_EQ(max_float, f); - string_->IncrByFloat(key_, -1 * max_float, &f); + string_->IncrByFloat(*ctx_, key_, -1 * max_float, &f); EXPECT_EQ(0, f); - string_->IncrByFloat(key_, -1 * max_float, &f); + string_->IncrByFloat(*ctx_, key_, -1 * max_float, &f); EXPECT_EQ(-1 * max_float, f); - string_->IncrByFloat(key_, -1.2, &f); + string_->IncrByFloat(*ctx_, key_, -1.2, &f); EXPECT_EQ(-1 * max_float, f); // key hold value is not the number - string_->Set(key_, "abc"); - rocksdb::Status s = string_->IncrByFloat(key_, 1.2, &f); + string_->Set(*ctx_, key_, "abc"); + rocksdb::Status s = string_->IncrByFloat(*ctx_, key_, 1.2, &f); EXPECT_TRUE(s.IsInvalidArgument()); - s = string_->Del(key_); + s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, IncrBy) { int64_t ret = 0; - string_->IncrBy(key_, 1, &ret); + string_->IncrBy(*ctx_, key_, 1, &ret); EXPECT_EQ(1, ret); - string_->IncrBy(key_, INT64_MAX - 1, &ret); + string_->IncrBy(*ctx_, key_, INT64_MAX - 1, &ret); EXPECT_EQ(INT64_MAX, ret); - rocksdb::Status s = string_->IncrBy(key_, 1, &ret); + rocksdb::Status s = string_->IncrBy(*ctx_, key_, 1, &ret); EXPECT_TRUE(s.IsInvalidArgument()); - string_->IncrBy(key_, INT64_MIN + 1, &ret); + string_->IncrBy(*ctx_, key_, INT64_MIN + 1, &ret); EXPECT_EQ(0, ret); - string_->IncrBy(key_, INT64_MIN, &ret); + string_->IncrBy(*ctx_, key_, INT64_MIN, &ret); EXPECT_EQ(INT64_MIN, ret); - s = string_->IncrBy(key_, -1, &ret); + s = string_->IncrBy(*ctx_, key_, -1, &ret); EXPECT_TRUE(s.IsInvalidArgument()); // key hold value is not the number - string_->Set(key_, "abc"); - s = string_->IncrBy(key_, 1, &ret); + string_->Set(*ctx_, key_, "abc"); + s = string_->IncrBy(*ctx_, key_, 1, &ret); EXPECT_TRUE(s.IsInvalidArgument()); - s = string_->Del(key_); + s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, GetEmptyValue) { const std::string key = "empty_value_key"; - auto s = string_->Set(key, ""); + auto s = string_->Set(*ctx_, key, ""); EXPECT_TRUE(s.ok()); std::string value; - s = string_->Get(key, &value); + s = string_->Get(*ctx_, key, &value); EXPECT_TRUE(s.ok() && value.empty()); } @@ -144,49 +144,49 @@ TEST_F(RedisStringTest, GetSet) { std::vector values = {"a", "b", "c", "d"}; for (size_t i = 0; i < values.size(); i++) { std::optional old_value; - auto s = string_->Expire(key_, now * 1000 + 100000); - string_->GetSet(key_, values[i], old_value); + auto s = string_->Expire(*ctx_, key_, now * 1000 + 100000); + string_->GetSet(*ctx_, key_, values[i], old_value); if (i != 0) { EXPECT_EQ(values[i - 1], old_value); - auto s = string_->TTL(key_, &ttl); + auto s = string_->TTL(*ctx_, key_, &ttl); EXPECT_TRUE(ttl == -1); } else { EXPECT_TRUE(!old_value.has_value()); } } - auto s = string_->Del(key_); + auto s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, GetDel) { for (auto &pair : pairs_) { - string_->Set(pair.key.ToString(), pair.value.ToString()); + string_->Set(*ctx_, pair.key.ToString(), pair.value.ToString()); } for (auto &pair : pairs_) { std::string got_value; - string_->GetDel(pair.key.ToString(), &got_value); + string_->GetDel(*ctx_, pair.key.ToString(), &got_value); EXPECT_EQ(pair.value, got_value); std::string second_got_value; - auto s = string_->GetDel(pair.key.ToString(), &second_got_value); + auto s = string_->GetDel(*ctx_, pair.key.ToString(), &second_got_value); EXPECT_TRUE(!s.ok() && s.IsNotFound()); } } TEST_F(RedisStringTest, MSetXX) { bool flag = false; - string_->SetXX(key_, "test-value", util::GetTimeStampMS() + 3000, &flag); + string_->SetXX(*ctx_, key_, "test-value", util::GetTimeStampMS() + 3000, &flag); EXPECT_FALSE(flag); - string_->Set(key_, "test-value"); - string_->SetXX(key_, "test-value", util::GetTimeStampMS() + 3000, &flag); + string_->Set(*ctx_, key_, "test-value"); + string_->SetXX(*ctx_, key_, "test-value", util::GetTimeStampMS() + 3000, &flag); EXPECT_TRUE(flag); int64_t ttl = 0; - auto s = string_->TTL(key_, &ttl); + auto s = string_->TTL(*ctx_, key_, &ttl); EXPECT_TRUE(ttl >= 2000 && ttl <= 4000); - s = string_->Del(key_); + s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, MSetNX) { bool flag = false; - string_->MSetNX(pairs_, 0, &flag); + string_->MSetNX(*ctx_, pairs_, 0, &flag); EXPECT_TRUE(flag); std::vector keys; std::vector values; @@ -194,7 +194,7 @@ TEST_F(RedisStringTest, MSetNX) { for (const auto &pair : pairs_) { keys.emplace_back(pair.key); } - string_->MGet(keys, &values); + string_->MGet(*ctx_, keys, &values); for (size_t i = 0; i < pairs_.size(); i++) { EXPECT_EQ(pairs_[i].value, values[i]); } @@ -202,111 +202,111 @@ TEST_F(RedisStringTest, MSetNX) { std::vector new_pairs{ {"a", "1"}, {"b", "2"}, {"c", "3"}, {pairs_[0].key, pairs_[0].value}, {"d", "4"}, }; - string_->MSetNX(pairs_, 0, &flag); + string_->MSetNX(*ctx_, pairs_, 0, &flag); EXPECT_FALSE(flag); for (auto &pair : pairs_) { - auto s = string_->Del(pair.key); + auto s = string_->Del(*ctx_, pair.key); } } TEST_F(RedisStringTest, MSetNXWithTTL) { bool flag = false; - string_->SetNX(key_, "test-value", util::GetTimeStampMS() + 3000, &flag); + string_->SetNX(*ctx_, key_, "test-value", util::GetTimeStampMS() + 3000, &flag); int64_t ttl = 0; - auto s = string_->TTL(key_, &ttl); + auto s = string_->TTL(*ctx_, key_, &ttl); EXPECT_TRUE(ttl >= 2000 && ttl <= 4000); - s = string_->Del(key_); + s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, SetEX) { - string_->SetEX(key_, "test-value", util::GetTimeStampMS() + 3000); + string_->SetEX(*ctx_, key_, "test-value", util::GetTimeStampMS() + 3000); int64_t ttl = 0; - auto s = string_->TTL(key_, &ttl); + auto s = string_->TTL(*ctx_, key_, &ttl); EXPECT_TRUE(ttl >= 2000 && ttl <= 4000); - s = string_->Del(key_); + s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, SetRange) { uint64_t ret = 0; - string_->Set(key_, "hello,world"); - string_->SetRange(key_, 6, "redis", &ret); + string_->Set(*ctx_, key_, "hello,world"); + string_->SetRange(*ctx_, key_, 6, "redis", &ret); EXPECT_EQ(11, ret); std::string value; - string_->Get(key_, &value); + string_->Get(*ctx_, key_, &value); EXPECT_EQ("hello,redis", value); - string_->SetRange(key_, 6, "test", &ret); + string_->SetRange(*ctx_, key_, 6, "test", &ret); EXPECT_EQ(11, ret); - string_->Get(key_, &value); + string_->Get(*ctx_, key_, &value); EXPECT_EQ("hello,tests", value); - string_->SetRange(key_, 6, "redis-1234", &ret); - string_->Get(key_, &value); + string_->SetRange(*ctx_, key_, 6, "redis-1234", &ret); + string_->Get(*ctx_, key_, &value); EXPECT_EQ("hello,redis-1234", value); - string_->SetRange(key_, 15, "1", &ret); + string_->SetRange(*ctx_, key_, 15, "1", &ret); EXPECT_EQ(16, ret); - string_->Get(key_, &value); + string_->Get(*ctx_, key_, &value); EXPECT_EQ(16, value.size()); - auto s = string_->Del(key_); + auto s = string_->Del(*ctx_, key_); } TEST_F(RedisStringTest, CAS) { int flag = 0; std::string key = "cas_key", value = "cas_value", new_value = "new_value"; - auto status = string_->Set(key, value); + auto status = string_->Set(*ctx_, key, value); ASSERT_TRUE(status.ok()); - status = string_->CAS("non_exist_key", value, new_value, util::GetTimeStampMS() + 10000, &flag); + status = string_->CAS(*ctx_, "non_exist_key", value, new_value, util::GetTimeStampMS() + 10000, &flag); ASSERT_TRUE(status.ok()); EXPECT_EQ(-1, flag); - status = string_->CAS(key, "cas_value_err", new_value, util::GetTimeStampMS() + 10000, &flag); + status = string_->CAS(*ctx_, key, "cas_value_err", new_value, util::GetTimeStampMS() + 10000, &flag); ASSERT_TRUE(status.ok()); EXPECT_EQ(0, flag); - status = string_->CAS(key, value, new_value, util::GetTimeStampMS() + 10000, &flag); + status = string_->CAS(*ctx_, key, value, new_value, util::GetTimeStampMS() + 10000, &flag); ASSERT_TRUE(status.ok()); EXPECT_EQ(1, flag); std::string current_value; - status = string_->Get(key, ¤t_value); + status = string_->Get(*ctx_, key, ¤t_value); ASSERT_TRUE(status.ok()); EXPECT_EQ(new_value, current_value); int64_t ttl = 0; - status = string_->TTL(key, &ttl); + status = string_->TTL(*ctx_, key, &ttl); EXPECT_TRUE(ttl >= 9000 && ttl <= 11000); - status = string_->Del(key); + status = string_->Del(*ctx_, key); } TEST_F(RedisStringTest, CAD) { int ret = 0; std::string key = "cas_key", value = "cas_value"; - auto status = string_->Set(key, value); + auto status = string_->Set(*ctx_, key, value); ASSERT_TRUE(status.ok()); - status = string_->CAD("non_exist_key", value, &ret); + status = string_->CAD(*ctx_, "non_exist_key", value, &ret); ASSERT_TRUE(status.ok()); EXPECT_EQ(-1, ret); - status = string_->CAD(key, "cas_value_err", &ret); + status = string_->CAD(*ctx_, key, "cas_value_err", &ret); ASSERT_TRUE(status.ok()); EXPECT_EQ(0, ret); - status = string_->CAD(key, value, &ret); + status = string_->CAD(*ctx_, key, value, &ret); ASSERT_TRUE(status.ok()); EXPECT_EQ(1, ret); std::string current_value; - status = string_->Get(key, ¤t_value); + status = string_->Get(*ctx_, key, ¤t_value); ASSERT_TRUE(status.IsNotFound()); - status = string_->Del(key); + status = string_->Del(*ctx_, key); } TEST_F(RedisStringTest, LCS) { @@ -328,20 +328,20 @@ TEST_F(RedisStringTest, LCS) { std::string value1 = "abcdef"; std::string value2 = "acdf"; - auto status = string_->Set(key1, value1); + auto status = string_->Set(*ctx_, key1, value1); ASSERT_TRUE(status.ok()); - status = string_->Set(key2, value2); + status = string_->Set(*ctx_, key2, value2); ASSERT_TRUE(status.ok()); - status = string_->LCS(key1, key2, {}, &rst); + status = string_->LCS(*ctx_, key1, key2, {}, &rst); ASSERT_TRUE(status.ok()); EXPECT_EQ("acdf", std::get(rst)); - status = string_->LCS(key1, key2, {StringLCSType::LEN}, &rst); + status = string_->LCS(*ctx_, key1, key2, {StringLCSType::LEN}, &rst); ASSERT_TRUE(status.ok()); EXPECT_EQ(4, std::get(rst)); - status = string_->LCS(key1, key2, {StringLCSType::IDX}, &rst); + status = string_->LCS(*ctx_, key1, key2, {StringLCSType::IDX}, &rst); ASSERT_TRUE(status.ok()); expect_result_eq({{ {{5, 5}, {3, 3}, 1}, @@ -351,7 +351,7 @@ TEST_F(RedisStringTest, LCS) { 4}, std::get(rst)); - status = string_->LCS(key1, key2, {StringLCSType::IDX, 2}, &rst); + status = string_->LCS(*ctx_, key1, key2, {StringLCSType::IDX, 2}, &rst); ASSERT_TRUE(status.ok()); expect_result_eq({{ {{2, 3}, {1, 2}, 2}, diff --git a/tests/cppunit/types/zset_test.cc b/tests/cppunit/types/zset_test.cc index 79c8794269d..c698403d553 100644 --- a/tests/cppunit/types/zset_test.cc +++ b/tests/cppunit/types/zset_test.cc @@ -47,16 +47,16 @@ TEST_F(RedisZSetTest, Add) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); for (size_t i = 0; i < fields_.size(); i++) { double got = 0.0; - rocksdb::Status s = zset_->Score(key_, fields_[i], &got); + rocksdb::Status s = zset_->Score(*ctx_, key_, fields_[i], &got); EXPECT_EQ(scores_[i], got); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(ret, 0); - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, IncrBy) { @@ -65,15 +65,15 @@ TEST_F(RedisZSetTest, IncrBy) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); for (size_t i = 0; i < fields_.size(); i++) { double increment = 12.3; double score = 0.0; - zset_->IncrBy(key_, fields_[i], increment, &score); + zset_->IncrBy(*ctx_, key_, fields_[i], increment, &score); EXPECT_EQ(scores_[i] + increment, score); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, Remove) { @@ -82,16 +82,16 @@ TEST_F(RedisZSetTest, Remove) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - zset_->Remove(key_, fields_, &ret); + zset_->Remove(*ctx_, key_, fields_, &ret); EXPECT_EQ(fields_.size(), ret); for (auto &field : fields_) { double score = 0.0; - rocksdb::Status s = zset_->Score(key_, field, &score); + rocksdb::Status s = zset_->Score(*ctx_, key_, field, &score); EXPECT_TRUE(s.IsNotFound()); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, AddAndRemoveRepeated) { @@ -103,24 +103,24 @@ TEST_F(RedisZSetTest, AddAndRemoveRepeated) { for (size_t i = 0; i < members.size(); i++) { mscores.emplace_back(MemberScore{members[i], scores[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(mscores.size() - 1, ret); double score = 0.0; - zset_->Score(key_, members[0], &score); + zset_->Score(*ctx_, key_, members[0], &score); EXPECT_EQ(scores[1], score); uint64_t card = 0; - zset_->Card(key_, &card); + zset_->Card(*ctx_, key_, &card); EXPECT_EQ(mscores.size() - 1, card); std::vector members_to_remove{"m1", "m2", "m2"}; - zset_->Remove(key_, members_to_remove, &ret); + zset_->Remove(*ctx_, key_, members_to_remove, &ret); EXPECT_EQ(members_to_remove.size() - 1, ret); - zset_->Card(key_, &card); + zset_->Card(*ctx_, key_, &card); EXPECT_EQ(mscores.size() - 1 - ret, card); - zset_->Score(key_, members[3], &score); + zset_->Score(*ctx_, key_, members[3], &score); EXPECT_EQ(scores[3], score); - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, Range) { @@ -130,18 +130,18 @@ TEST_F(RedisZSetTest, Range) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } uint64_t count = mscores.size() - 1; - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); RangeRankSpec rank_spec; rank_spec.start = 0; rank_spec.stop = -2; - zset_->RangeByRank(key_, rank_spec, &mscores, nullptr); + zset_->RangeByRank(*ctx_, key_, rank_spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), count); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); EXPECT_EQ(mscores[i].score, scores_[i]); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, RevRange) { @@ -151,19 +151,19 @@ TEST_F(RedisZSetTest, RevRange) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } uint64_t count = mscores.size() - 1; - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); RangeRankSpec rank_spec; rank_spec.start = 0; rank_spec.stop = -2; rank_spec.reversed = true; - zset_->RangeByRank(key_, rank_spec, &mscores, nullptr); + zset_->RangeByRank(*ctx_, key_, rank_spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), count); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[count - i].ToString()); EXPECT_EQ(mscores[i].score, scores_[count - i]); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, PopMin) { @@ -172,14 +172,14 @@ TEST_F(RedisZSetTest, PopMin) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - zset_->Pop(key_, static_cast(mscores.size() - 1), true, &mscores); + zset_->Pop(*ctx_, key_, static_cast(mscores.size() - 1), true, &mscores); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); EXPECT_EQ(mscores[i].score, scores_[i]); } - zset_->Pop(key_, 1, true, &mscores); + zset_->Pop(*ctx_, key_, 1, true, &mscores); EXPECT_EQ(mscores[0].member, fields_[fields_.size() - 1].ToString()); EXPECT_EQ(mscores[0].score, scores_[fields_.size() - 1]); } @@ -191,14 +191,14 @@ TEST_F(RedisZSetTest, PopMax) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); - zset_->Pop(key_, static_cast(mscores.size() - 1), false, &mscores); + zset_->Pop(*ctx_, key_, static_cast(mscores.size() - 1), false, &mscores); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[count - i - 1].ToString()); EXPECT_EQ(mscores[i].score, scores_[count - i - 1]); } - zset_->Pop(key_, 1, true, &mscores); + zset_->Pop(*ctx_, key_, 1, true, &mscores); EXPECT_EQ(mscores[0].member, fields_[0].ToString()); } @@ -209,13 +209,13 @@ TEST_F(RedisZSetTest, RangeByLex) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(count, ret); RangeLexSpec spec; spec.min = fields_[0].ToString(); spec.max = fields_[fields_.size() - 1].ToString(); - zset_->RangeByLex(key_, spec, &mscores, nullptr); + zset_->RangeByLex(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), fields_.size()); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); @@ -223,7 +223,7 @@ TEST_F(RedisZSetTest, RangeByLex) { } spec.minex = true; - zset_->RangeByLex(key_, spec, &mscores, nullptr); + zset_->RangeByLex(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), fields_.size() - 1); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i + 1].ToString()); @@ -232,7 +232,7 @@ TEST_F(RedisZSetTest, RangeByLex) { spec.minex = false; spec.maxex = true; - zset_->RangeByLex(key_, spec, &mscores, nullptr); + zset_->RangeByLex(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), fields_.size() - 1); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); @@ -241,7 +241,7 @@ TEST_F(RedisZSetTest, RangeByLex) { spec.minex = true; spec.maxex = true; - zset_->RangeByLex(key_, spec, &mscores, nullptr); + zset_->RangeByLex(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), fields_.size() - 2); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i + 1].ToString()); @@ -253,14 +253,14 @@ TEST_F(RedisZSetTest, RangeByLex) { spec.max = "+"; spec.max_infinite = true; spec.reversed = true; - zset_->RangeByLex(key_, spec, &mscores, nullptr); + zset_->RangeByLex(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), fields_.size()); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[count - i - 1].ToString()); EXPECT_EQ(mscores[i].score, scores_[count - i - 1]); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, RangeByScore) { @@ -269,14 +269,14 @@ TEST_F(RedisZSetTest, RangeByScore) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); // test case: inclusive the min and max score RangeScoreSpec spec; spec.min = scores_[0]; spec.max = scores_[scores_.size() - 2]; - zset_->RangeByScore(key_, spec, &mscores, nullptr); + zset_->RangeByScore(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), scores_.size() - 1); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); @@ -284,7 +284,7 @@ TEST_F(RedisZSetTest, RangeByScore) { } // test case: exclusive the min score spec.minex = true; - zset_->RangeByScore(key_, spec, &mscores, nullptr); + zset_->RangeByScore(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), scores_.size() - 3); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i + 2].ToString()); @@ -293,7 +293,7 @@ TEST_F(RedisZSetTest, RangeByScore) { // test case: exclusive the max score spec.minex = false; spec.maxex = true; - zset_->RangeByScore(key_, spec, &mscores, nullptr); + zset_->RangeByScore(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), scores_.size() - 3); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i].ToString()); @@ -302,13 +302,13 @@ TEST_F(RedisZSetTest, RangeByScore) { // test case: exclusive the min and max score spec.minex = true; spec.maxex = true; - zset_->RangeByScore(key_, spec, &mscores, nullptr); + zset_->RangeByScore(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), scores_.size() - 5); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i + 2].ToString()); EXPECT_EQ(mscores[i].score, scores_[i + 2]); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, RangeByScoreWithLimit) { @@ -317,19 +317,19 @@ TEST_F(RedisZSetTest, RangeByScoreWithLimit) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); RangeScoreSpec spec; spec.offset = 1; spec.count = 2; - zset_->RangeByScore(key_, spec, &mscores, nullptr); + zset_->RangeByScore(*ctx_, key_, spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), 2); for (size_t i = 0; i < mscores.size(); i++) { EXPECT_EQ(mscores[i].member, fields_[i + 1].ToString()); EXPECT_EQ(mscores[i].score, scores_[i + 1]); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, RemRangeByScore) { @@ -338,19 +338,19 @@ TEST_F(RedisZSetTest, RemRangeByScore) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); RangeScoreSpec spec; spec.with_deletion = true; spec.min = scores_[0]; spec.max = scores_[scores_.size() - 2]; - zset_->RangeByScore(key_, spec, nullptr, &ret); + zset_->RangeByScore(*ctx_, key_, spec, nullptr, &ret); EXPECT_EQ(scores_.size() - 1, ret); spec.min = scores_[scores_.size() - 1]; spec.max = spec.min; - zset_->RangeByScore(key_, spec, nullptr, &ret); + zset_->RangeByScore(*ctx_, key_, spec, nullptr, &ret); EXPECT_EQ(1, ret); } @@ -360,7 +360,7 @@ TEST_F(RedisZSetTest, RemoveRangeByRank) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); RangeRankSpec spec; @@ -368,12 +368,12 @@ TEST_F(RedisZSetTest, RemoveRangeByRank) { spec.start = 0; spec.stop = static_cast(fields_.size() - 2); - zset_->RangeByRank(key_, spec, nullptr, &ret); + zset_->RangeByRank(*ctx_, key_, spec, nullptr, &ret); EXPECT_EQ(fields_.size() - 1, ret); spec.start = 0; spec.stop = 2; - zset_->RangeByRank(key_, spec, nullptr, &ret); + zset_->RangeByRank(*ctx_, key_, spec, nullptr, &ret); EXPECT_EQ(1, ret); } @@ -383,7 +383,7 @@ TEST_F(RedisZSetTest, RemoveRevRangeByRank) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(fields_.size(), ret); RangeRankSpec spec; @@ -391,12 +391,12 @@ TEST_F(RedisZSetTest, RemoveRevRangeByRank) { spec.start = 0; spec.stop = static_cast(fields_.size() - 2); - zset_->RangeByRank(key_, spec, nullptr, &ret); + zset_->RangeByRank(*ctx_, key_, spec, nullptr, &ret); EXPECT_EQ(fields_.size() - 1, ret); spec.start = 0; spec.stop = 2; - zset_->RangeByRank(key_, spec, nullptr, &ret); + zset_->RangeByRank(*ctx_, key_, spec, nullptr, &ret); EXPECT_EQ(1, ret); } @@ -406,20 +406,20 @@ TEST_F(RedisZSetTest, Rank) { for (size_t i = 0; i < fields_.size(); i++) { mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &mscores, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); for (size_t i = 0; i < fields_.size(); i++) { int rank = 0; double score = 0.0; - zset_->Rank(key_, fields_[i], false, &rank, &score); + zset_->Rank(*ctx_, key_, fields_[i], false, &rank, &score); EXPECT_EQ(i, rank); EXPECT_EQ(scores_[i], score); } for (size_t i = 0; i < fields_.size(); i++) { int rank = 0; double score = 0.0; - zset_->Rank(key_, fields_[i], true, &rank, &score); + zset_->Rank(*ctx_, key_, fields_[i], true, &rank, &score); EXPECT_EQ(i, static_cast(fields_.size() - rank - 1)); EXPECT_EQ(scores_[i], score); } @@ -427,11 +427,11 @@ TEST_F(RedisZSetTest, Rank) { for (const auto &member : no_exist_members) { int rank = 0; double score = 0.0; - zset_->Rank(key_, member, true, &rank, &score); + zset_->Rank(*ctx_, key_, member, true, &rank, &score); EXPECT_EQ(-1, rank); EXPECT_EQ(0.0, score); } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); } TEST_F(RedisZSetTest, RandMember) { @@ -442,7 +442,7 @@ TEST_F(RedisZSetTest, RandMember) { for (size_t i = 0; i < fields_.size(); i++) { in_mscores.emplace_back(MemberScore{fields_[i].ToString(), scores_[i]}); } - zset_->Add(key_, ZAddFlags::Default(), &in_mscores, &ret); + zset_->Add(*ctx_, key_, ZAddFlags::Default(), &in_mscores, &ret); EXPECT_EQ(static_cast(fields_.size()), ret); } @@ -454,7 +454,7 @@ TEST_F(RedisZSetTest, RandMember) { // count = 0 { std::vector mscores; - rocksdb::Status s = zset_->RandMember(key_, 0, &mscores); + rocksdb::Status s = zset_->RandMember(*ctx_, key_, 0, &mscores); EXPECT_EQ(0, mscores.size()); EXPECT_TRUE(s.ok()); } @@ -462,7 +462,7 @@ TEST_F(RedisZSetTest, RandMember) { // count = 1/-1 for (int64_t count : {1, -1}) { std::vector mscores; - rocksdb::Status s = zset_->RandMember(key_, count, &mscores); + rocksdb::Status s = zset_->RandMember(*ctx_, key_, count, &mscores); EXPECT_EQ(1, mscores.size()); EXPECT_TRUE(s.ok()); EXPECT_NE(member_map.find(mscores[0].member), member_map.end()); @@ -495,7 +495,7 @@ TEST_F(RedisZSetTest, RandMember) { static_cast(fields_.size() / 2), }) { std::vector mscores; - rocksdb::Status s = zset_->RandMember(key_, count, &mscores); + rocksdb::Status s = zset_->RandMember(*ctx_, key_, count, &mscores); EXPECT_EQ(static_cast(count), mscores.size()); EXPECT_TRUE(s.ok()); ASSERT_TRUE(no_non_exist_members(mscores)); @@ -508,7 +508,7 @@ TEST_F(RedisZSetTest, RandMember) { -static_cast(fields_.size() / 2), }) { std::vector mscores; - rocksdb::Status s = zset_->RandMember(key_, count, &mscores); + rocksdb::Status s = zset_->RandMember(*ctx_, key_, count, &mscores); EXPECT_EQ(static_cast(-count), mscores.size()); EXPECT_TRUE(s.ok()); ASSERT_TRUE(no_non_exist_members(mscores)); @@ -521,7 +521,7 @@ TEST_F(RedisZSetTest, RandMember) { -static_cast(fields_.size() + 10), }) { std::vector mscores; - rocksdb::Status s = zset_->RandMember(key_, count, &mscores); + rocksdb::Status s = zset_->RandMember(*ctx_, key_, count, &mscores); EXPECT_TRUE(s.ok()); ASSERT_TRUE(no_non_exist_members(mscores)); if (count > 0) { @@ -532,7 +532,7 @@ TEST_F(RedisZSetTest, RandMember) { } } - auto s = zset_->Del(key_); + auto s = zset_->Del(*ctx_, key_); EXPECT_TRUE(s.ok()); } @@ -548,15 +548,15 @@ TEST_F(RedisZSetTest, Diff) { std::string k3 = "key3"; std::vector k3_mscores = {{"a", -1000.1}, {"c", -100.1}, {"e", 8000.9}}; - auto s = zset_->Add(k1, ZAddFlags::Default(), &k1_mscores, &ret); + auto s = zset_->Add(*ctx_, k1, ZAddFlags::Default(), &k1_mscores, &ret); EXPECT_EQ(ret, 4); - zset_->Add(k2, ZAddFlags::Default(), &k2_mscores, &ret); + zset_->Add(*ctx_, k2, ZAddFlags::Default(), &k2_mscores, &ret); EXPECT_EQ(ret, 1); - zset_->Add(k3, ZAddFlags::Default(), &k3_mscores, &ret); + zset_->Add(*ctx_, k3, ZAddFlags::Default(), &k3_mscores, &ret); EXPECT_EQ(ret, 3); std::vector mscores; - zset_->Diff({k1, k2, k3}, &mscores); + zset_->Diff(*ctx_, {k1, k2, k3}, &mscores); EXPECT_EQ(2, mscores.size()); std::vector expected_mscores = {{"b", -100.1}, {"d", 1.234}}; @@ -567,11 +567,11 @@ TEST_F(RedisZSetTest, Diff) { index++; } - s = zset_->Del(k1); + s = zset_->Del(*ctx_, k1); EXPECT_TRUE(s.ok()); - s = zset_->Del(k2); + s = zset_->Del(*ctx_, k2); EXPECT_TRUE(s.ok()); - s = zset_->Del(k3); + s = zset_->Del(*ctx_, k3); EXPECT_TRUE(s.ok()); } @@ -584,18 +584,18 @@ TEST_F(RedisZSetTest, DiffStore) { std::string k2 = "key2"; std::vector k2_mscores = {{"c", -150.1}}; - auto s = zset_->Add(k1, ZAddFlags::Default(), &k1_mscores, &ret); + auto s = zset_->Add(*ctx_, k1, ZAddFlags::Default(), &k1_mscores, &ret); EXPECT_EQ(ret, 4); - zset_->Add(k2, ZAddFlags::Default(), &k2_mscores, &ret); + zset_->Add(*ctx_, k2, ZAddFlags::Default(), &k2_mscores, &ret); EXPECT_EQ(ret, 1); uint64_t stored_count = 0; - zset_->DiffStore("zsetdiff", {k1, k2}, &stored_count); + zset_->DiffStore(*ctx_, "zsetdiff", {k1, k2}, &stored_count); EXPECT_EQ(stored_count, 3); RangeScoreSpec spec; std::vector mscores; - zset_->RangeByScore("zsetdiff", spec, &mscores, nullptr); + zset_->RangeByScore(*ctx_, "zsetdiff", spec, &mscores, nullptr); EXPECT_EQ(mscores.size(), 3); std::vector expected_mscores = {{"a", -100.1}, {"b", -100.1}, {"d", 1.234}}; @@ -606,10 +606,10 @@ TEST_F(RedisZSetTest, DiffStore) { index++; } - s = zset_->Del(k1); + s = zset_->Del(*ctx_, k1); EXPECT_TRUE(s.ok()); - s = zset_->Del(k2); + s = zset_->Del(*ctx_, k2); EXPECT_TRUE(s.ok()); - s = zset_->Del("zsetdiff"); + s = zset_->Del(*ctx_, "zsetdiff"); EXPECT_TRUE(s.ok()); } diff --git a/tests/cppunit/writebatch_indexer_test.cc b/tests/cppunit/writebatch_indexer_test.cc new file mode 100644 index 00000000000..51a5d4203ea --- /dev/null +++ b/tests/cppunit/writebatch_indexer_test.cc @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include +#include +#include + +#include "storage/batch_indexer.h" +#include "test_base.h" + +class WriteBatchIndexerTest : public TestBase { + protected: + explicit WriteBatchIndexerTest() = default; + ~WriteBatchIndexerTest() override = default; +}; + +TEST_F(WriteBatchIndexerTest, PutDelete) { + rocksdb::WriteBatch batch; + auto s = batch.Put("key0", "value0"); + EXPECT_TRUE(s.ok()) << s.ToString(); + for (int i = 1; i < 4; ++i) { + std::string key = "key" + std::to_string(i); + std::string value = "value" + std::to_string(i); + s = batch.Put(storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), key, value); + EXPECT_TRUE(s.ok()) << s.ToString(); + } + + ctx_->batch = std::make_unique(); + WriteBatchIndexer handle1(*ctx_); + s = batch.Iterate(&handle1); + EXPECT_TRUE(s.ok()) << s.ToString(); + + rocksdb::Options options; + std::string value; + for (int i = 0; i < 4; i++) { + std::string key = "key" + std::to_string(i); + std::string expect_value = "value" + std::to_string(i); + s = ctx_->batch->GetFromBatch(options, key, &value); + EXPECT_TRUE(s.ok()) << s.ToString(); + EXPECT_EQ(expect_value, value); + } + + s = storage_->GetDB()->Write(rocksdb::WriteOptions(), ctx_->batch->GetWriteBatch()); + EXPECT_TRUE(s.ok()) << s.ToString(); + + batch.Clear(); + s = batch.Delete("key0"); + EXPECT_TRUE(s.ok()) << s.ToString(); + + s = batch.DeleteRange(storage_->GetCFHandle(ColumnFamilyID::PrimarySubkey), "key1", "key3"); + EXPECT_TRUE(s.ok()) << s.ToString(); + + WriteBatchIndexer handle2(*ctx_); + s = batch.Iterate(&handle2); + s = batch.Iterate(&handle2); + EXPECT_TRUE(s.ok()) << s.ToString(); + + for (int i = 0; i < 3; i++) { + std::string key = "key" + std::to_string(i); + s = ctx_->batch->GetFromBatchAndDB(storage_->GetDB(), rocksdb::ReadOptions(), key, &value); + EXPECT_TRUE(s.IsNotFound()); + } + + s = ctx_->batch->GetFromBatchAndDB(storage_->GetDB(), rocksdb::ReadOptions(), "key3", &value); + EXPECT_TRUE(s.ok()) << s.ToString(); + EXPECT_EQ("value3", value); +} + +TEST_F(WriteBatchIndexerTest, SingleDelete) { + auto s = storage_->GetDB()->Put(rocksdb::WriteOptions(), "key", "value"); + EXPECT_TRUE(s.ok()) << s.ToString(); + + std::string value; + s = storage_->GetDB()->Get(rocksdb::ReadOptions(), "key", &value); + EXPECT_TRUE(s.ok()) << s.ToString(); + EXPECT_EQ("value", value); + + rocksdb::WriteBatch batch; + s = batch.SingleDelete("key"); + EXPECT_TRUE(s.ok()) << s.ToString(); + + ctx_->batch = std::make_unique(); + WriteBatchIndexer handle(*ctx_); + s = batch.Iterate(&handle); + EXPECT_TRUE(s.ok()) << s.ToString(); + + s = ctx_->batch->GetFromBatchAndDB(storage_->GetDB(), rocksdb::ReadOptions(), "key", &value); + EXPECT_TRUE(s.IsNotFound()); +} diff --git a/tests/gocase/integration/replication/replication_test.go b/tests/gocase/integration/replication/replication_test.go index 71e08c77f61..7adc9862b9a 100644 --- a/tests/gocase/integration/replication/replication_test.go +++ b/tests/gocase/integration/replication/replication_test.go @@ -181,7 +181,6 @@ func TestReplicationBasics(t *testing.T) { util.SlaveOf(t, slaveClient, master) require.Equal(t, "slave", util.FindInfoEntry(slaveClient, "role")) }) - util.WaitForSync(t, slaveClient) t.Run("Sync should have transferred keys from master", func(t *testing.T) { require.Equal(t, masterClient.Get(ctx, "mykey"), slaveClient.Get(ctx, "mykey")) diff --git a/tests/gocase/unit/protocol/regression_test.go b/tests/gocase/unit/protocol/regression_test.go index 3111aee41e0..7dd4ea22b41 100644 --- a/tests/gocase/unit/protocol/regression_test.go +++ b/tests/gocase/unit/protocol/regression_test.go @@ -23,6 +23,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/apache/kvrocks/tests/gocase/util" "github.com/stretchr/testify/require" @@ -41,7 +42,8 @@ func TestRegression(t *testing.T) { proto := "*3\r\n$5\r\nBLPOP\r\n$6\r\nhandle\r\n$1\r\n0\r\n" require.NoError(t, c.Write(fmt.Sprintf("%s%s", proto, proto))) - + // TODO: Remove time.Sleep after fix issue #2473 + time.Sleep(100 * time.Millisecond) resList := []string{"*2", "$6", "handle", "$1", "a"} v := rdb.RPush(ctx, "handle", "a") diff --git a/tests/gocase/unit/type/list/list_test.go b/tests/gocase/unit/type/list/list_test.go index c440ebab458..a2234626417 100644 --- a/tests/gocase/unit/type/list/list_test.go +++ b/tests/gocase/unit/type/list/list_test.go @@ -324,13 +324,22 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() createList("blist", []string{"a", "b", large, "c", "d"}) + // TODO: Remove time.Sleep after fix issue #2473 + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blpop", "blist", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist", "a"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("brpop", "blist", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist", "d"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blpop", "blist", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist", "b"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("brpop", "blist", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist", "c"}) }) @@ -339,15 +348,23 @@ func TestList(t *testing.T) { defer func() { require.NoError(t, rd.Close()) }() createList("blist1", []string{"a", large, "c"}) createList("blist2", []string{"d", large, "f"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blpop", "blist1", "blist2", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist1", "a"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("brpop", "blist1", "blist2", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist1", "c"}) require.EqualValues(t, 1, rdb.LLen(ctx, "blist1").Val()) require.EqualValues(t, 3, rdb.LLen(ctx, "blist2").Val()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blpop", "blist2", "blist2", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist2", "d"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("brpop", "blist2", "blist2", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist2", "f"}) require.EqualValues(t, 1, rdb.LLen(ctx, "blist1").Val()) require.EqualValues(t, 1, rdb.LLen(ctx, "blist2").Val()) @@ -358,9 +375,13 @@ func TestList(t *testing.T) { defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "blist1").Err()) createList("blist2", []string{"d", large, "f"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blpop", "blist1", "blist2", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist2", "d"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("brpop", "blist1", "blist2", "1")) + time.Sleep(100 * time.Millisecond) rd.MustReadStrings(t, []string{"blist2", "f"}) require.EqualValues(t, 0, rdb.LLen(ctx, "blist1").Val()) require.EqualValues(t, 1, rdb.LLen(ctx, "blist2").Val()) @@ -371,17 +392,25 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "list1", "list2").Err()) + time.Sleep(time.Millisecond * 100) require.NoError(t, rd.WriteArgs("blpop", "list1", "list2", "list2", "list1", "0")) + time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.LPush(ctx, "list1", "a").Err()) rd.MustReadStrings(t, []string{"list1", "a"}) + time.Sleep(time.Millisecond * 100) require.NoError(t, rd.WriteArgs("blpop", "list1", "list2", "list2", "list1", "0")) + time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.LPush(ctx, "list2", "b").Err()) rd.MustReadStrings(t, []string{"list2", "b"}) require.NoError(t, rdb.LPush(ctx, "list1", "a").Err()) require.NoError(t, rdb.LPush(ctx, "list2", "b").Err()) + time.Sleep(time.Millisecond * 100) require.NoError(t, rd.WriteArgs("blpop", "list1", "list2", "list2", "list1", "0")) + time.Sleep(time.Millisecond * 100) rd.MustReadStrings(t, []string{"list1", "a"}) + time.Sleep(time.Millisecond * 100) require.NoError(t, rd.WriteArgs("blpop", "list1", "list2", "list2", "list1", "0")) + time.Sleep(time.Millisecond * 100) rd.MustReadStrings(t, []string{"list2", "b"}) }) @@ -393,7 +422,6 @@ func TestList(t *testing.T) { require.NoError(t, rd.WriteArgs("blpop", "blist", "0")) time.Sleep(time.Millisecond * 100) require.EqualValues(t, 2, rdb.LPush(ctx, "blist", "foo", "bar").Val()) - time.Sleep(time.Millisecond * 100) rd.MustReadStrings(t, []string{"blist", "bar"}) require.Equal(t, "foo", rdb.LRange(ctx, "blist", 0, -1).Val()[0]) }) @@ -403,7 +431,9 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "blist1").Err()) - require.NoError(t, rd.WriteArgs(popType, "blist1", "1")) + time.Sleep(100 * time.Millisecond) + require.NoError(t, rd.WriteArgs(popType, "blist1", "0")) + time.Sleep(100 * time.Millisecond) require.NoError(t, rdb.RPush(ctx, "blist1", "foo").Err()) rd.MustReadStrings(t, []string{"blist1", "foo"}) require.EqualValues(t, 0, rdb.Exists(ctx, "blist1").Val()) @@ -413,6 +443,7 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rd.WriteArgs(popType, "blist1", "-1")) + time.Sleep(100 * time.Millisecond) rd.MustMatch(t, ".*negative.*") }) @@ -432,6 +463,7 @@ func TestList(t *testing.T) { defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "blist1", "blist2").Err()) require.NoError(t, rdb.Set(ctx, "blist2", "nolist", 0).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs(popType, "blist1", "blist2", "1")) rd.MustMatch(t, ".*WRONGTYPE.*") }) @@ -440,6 +472,7 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "blist1", "blist2").Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs(popType, "blist1", "blist2", "1")) rd.MustMatch(t, "") }) @@ -448,12 +481,16 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "blist1", "blist2").Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs(popType, "blist1", "blist2", "4")) + time.Sleep(100 * time.Millisecond) require.NoError(t, rdb.RPush(ctx, "blist1", "foo").Err()) rd.MustReadStrings(t, []string{"blist1", "foo"}) require.EqualValues(t, 0, rdb.Exists(ctx, "blist1").Val()) require.EqualValues(t, 0, rdb.Exists(ctx, "blist2").Val()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs(popType, "blist1", "blist2", "1")) + time.Sleep(100 * time.Millisecond) require.NoError(t, rdb.RPush(ctx, "blist2", "foo").Err()) rd.MustReadStrings(t, []string{"blist2", "foo"}) require.EqualValues(t, 0, rdb.Exists(ctx, "blist1").Val()) @@ -861,7 +898,9 @@ func TestList(t *testing.T) { require.NoError(t, rdb.Del(ctx, "target_key{t}").Err()) require.NoError(t, rdb.RPush(ctx, "target_key{t}", 1).Err()) createList("list{t}", []string{"a", "b", "c", "d"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("lmove", "list{t}", "target_key{t}", from, to)) + time.Sleep(100 * time.Millisecond) r, err1 := rd.ReadLine() require.Equal(t, "$1", r) require.NoError(t, err1) @@ -907,7 +946,9 @@ func TestList(t *testing.T) { require.NoError(t, rdb.Del(ctx, "target_key{t}").Err()) require.NoError(t, rdb.RPush(ctx, "target_key{t}", 1).Err()) createList("list{t}", []string{"a", "b", "c", "d"}) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmove", "list{t}", "target_key{t}", from, to, "1")) + time.Sleep(100 * time.Millisecond) r, err1 := rd.ReadLine() require.Equal(t, "$1", r) require.NoError(t, err1) @@ -933,7 +974,9 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, "blist", "target").Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmove", "blist", "target", "left", "right", "0")) + time.Sleep(100 * time.Millisecond) require.EqualValues(t, 2, rdb.LPush(ctx, "blist", "foo", "bar").Val()) rd.MustRead(t, "$3") require.Equal(t, "bar", rdb.LRange(ctx, "target", 0, -1).Val()[0]) @@ -1341,10 +1384,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "1", key1, direction, "count", "1")) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key1, "ONE", "TWO").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key1, []string{"ONE"}) } else { @@ -1357,10 +1400,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "1", key1, direction, "count", "2")) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key1, "ONE", "TWO").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key1, []string{"ONE", "TWO"}) } else { @@ -1373,10 +1416,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "1", key1, direction, "count", "10")) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key1, "ONE", "TWO").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key1, []string{"ONE", "TWO"}) } else { @@ -1389,10 +1432,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "2", key1, key2, direction, "count", "2")) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key1, "ONE", "TWO").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key1, []string{"ONE", "TWO"}) } else { @@ -1405,10 +1448,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "2", key1, key2, direction, "count", "2")) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key2, "one", "two").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key2, []string{"one", "two"}) } else { @@ -1421,12 +1464,11 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "2", key1, key2, direction, "count", "2")) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key2, "one", "two").Err()) - time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key1, "ONE", "TWO").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key2, []string{"one", "two"}) } else { @@ -1440,10 +1482,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "2", key1, key2, direction)) time.Sleep(time.Millisecond * 100) require.NoError(t, rdb.RPush(ctx, key2, "one", "two").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key2, []string{"one"}) } else { @@ -1457,6 +1499,7 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "1", "2", key1, key2, direction)) time.Sleep(time.Millisecond * 1200) rd.MustMatch(t, "") @@ -1467,10 +1510,10 @@ func TestList(t *testing.T) { rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() require.NoError(t, rdb.Del(ctx, key1, key2).Err()) + time.Sleep(100 * time.Millisecond) require.NoError(t, rd.WriteArgs("blmpop", "0", "2", key1, key2, direction, "count", "2")) time.Sleep(time.Millisecond * 1200) require.NoError(t, rdb.RPush(ctx, key2, "one", "two").Err()) - time.Sleep(time.Millisecond * 100) if direction == "LEFT" { rd.MustReadStringsWithKey(t, key2, []string{"one", "two"}) } else { diff --git a/tests/gocase/unit/type/zset/zset_test.go b/tests/gocase/unit/type/zset/zset_test.go index e3d609120a8..20441b5b17e 100644 --- a/tests/gocase/unit/type/zset/zset_test.go +++ b/tests/gocase/unit/type/zset/zset_test.go @@ -332,6 +332,8 @@ func basicTests(t *testing.T, rdb *redis.Client, ctx context.Context, enabledRES rdb.ZAdd(ctx, "zsetb", redis.Z{Score: 1, Member: "d"}, redis.Z{Score: 2, Member: "e"}) require.EqualValues(t, 3, rdb.ZCard(ctx, "zseta").Val()) require.EqualValues(t, 2, rdb.ZCard(ctx, "zsetb").Val()) + // TODO: Remove time.Sleep after fix issue #2473 + time.Sleep(time.Millisecond * 100) resultz := rdb.BZPopMin(ctx, 0, "zseta", "zsetb").Val().Z require.Equal(t, redis.Z{Score: 1, Member: "a"}, resultz) resultz = rdb.BZPopMin(ctx, 0, "zseta", "zsetb").Val().Z @@ -347,7 +349,9 @@ func basicTests(t *testing.T, rdb *redis.Client, ctx context.Context, enabledRES rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() + time.Sleep(time.Millisecond * 100) require.NoError(t, rd.WriteArgs("bzpopmin", "zseta", "0")) + time.Sleep(time.Millisecond * 100) rdb.ZAdd(ctx, "zseta", redis.Z{Score: 1, Member: "a"}) rd.MustReadStrings(t, []string{"zseta", "a", "1"}) }) @@ -359,6 +363,7 @@ func basicTests(t *testing.T, rdb *redis.Client, ctx context.Context, enabledRES rdb.ZAdd(ctx, "zsetb", redis.Z{Score: 1, Member: "d"}, redis.Z{Score: 2, Member: "e"}) require.EqualValues(t, 3, rdb.ZCard(ctx, "zseta").Val()) require.EqualValues(t, 2, rdb.ZCard(ctx, "zsetb").Val()) + time.Sleep(time.Millisecond * 100) resultz := rdb.BZPopMax(ctx, 0, "zseta", "zsetb").Val().Z require.Equal(t, redis.Z{Score: 3, Member: "c"}, resultz) resultz = rdb.BZPopMax(ctx, 0, "zseta", "zsetb").Val().Z @@ -374,7 +379,9 @@ func basicTests(t *testing.T, rdb *redis.Client, ctx context.Context, enabledRES rd := srv.NewTCPClient() defer func() { require.NoError(t, rd.Close()) }() + time.Sleep(time.Millisecond * 100) require.NoError(t, rd.WriteArgs("bzpopmax", "zseta", "0")) + time.Sleep(time.Millisecond * 100) rdb.ZAdd(ctx, "zseta", redis.Z{Score: 1, Member: "a"}) rd.MustReadStrings(t, []string{"zseta", "a", "1"}) }) diff --git a/utils/kvrocks2redis/parser.cc b/utils/kvrocks2redis/parser.cc index c131f14654f..22a5cd61405 100644 --- a/utils/kvrocks2redis/parser.cc +++ b/utils/kvrocks2redis/parser.cc @@ -94,7 +94,8 @@ Status Parser::parseComplexKV(const Slice &ns_key, const Metadata &metadata) { read_options.iterate_upper_bound = &upper_bound; std::string output; - auto iter = util::UniqueIterator(storage_, read_options); + auto no_txn_ctx = engine::Context::NoTransactionContext(storage_); + auto iter = util::UniqueIterator(no_txn_ctx, read_options); for (iter->Seek(prefix_key); iter->Valid(); iter->Next()) { if (!iter->key().starts_with(prefix_key)) { break;