blob: 0b4ba7b3c7e382303b5f06c24c3a1dfdd8c1fec8 [file]
/*
* 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 <map>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <variant>
#include <vector>
#include "status.h"
#include "types/redis_hash.h"
#include "types/redis_zset.h"
// Redis object type
constexpr const int RDBTypeString = 0;
constexpr const int RDBTypeList = 1;
constexpr const int RDBTypeSet = 2;
constexpr const int RDBTypeZSet = 3;
constexpr const int RDBTypeHash = 4;
constexpr const int RDBTypeZSet2 = 5;
// NOTE: when adding new Redis object type, update LoadObjectType.
// Redis object encoding
constexpr const int RDBTypeHashZipMap = 9;
constexpr const int RDBTypeListZipList = 10;
constexpr const int RDBTypeSetIntSet = 11;
constexpr const int RDBTypeZSetZipList = 12;
constexpr const int RDBTypeHashZipList = 13;
constexpr const int RDBTypeListQuickList = 14;
constexpr const int RDBTypeStreamListPack = 15;
constexpr const int RDBTypeHashListPack = 16;
constexpr const int RDBTypeZSetListPack = 17;
constexpr const int RDBTypeListQuickList2 = 18;
constexpr const int RDBTypeStreamListPack2 = 19;
constexpr const int RDBTypeSetListPack = 20;
constexpr const int RDBTypeStreamListPack3 = 21;
// NOTE: when adding new Redis object encoding type, update isObjectType.
// Quick list node encoding
constexpr const int QuickListNodeContainerPlain = 1;
constexpr const int QuickListNodeContainerPacked = 2;
constexpr const int MaxRDBVersion = 12; // The current max rdb version supported by redis.
// Min Redis RDB version supported by Kvrocks, we choose 6 because it's the first version
// that supports the DUMP command.
constexpr int MinRDBVersion = 6;
class RdbStream;
using RedisObjValue =
std::variant<std::string, std::vector<std::string>, std::vector<MemberScore>, std::map<std::string, std::string>>;
class RDB {
public:
explicit RDB(engine::Storage *storage, std::string ns, std::unique_ptr<RdbStream> stream)
: storage_(storage), ns_(std::move(ns)), stream_(std::move(stream)) {}
~RDB() = default;
Status VerifyPayloadChecksum(const std::string_view &payload);
StatusOr<int> LoadObjectType();
Status Restore(engine::Context &ctx, const std::string &key, std::string_view payload, uint64_t ttl_ms);
// String
StatusOr<std::string> LoadStringObject();
// Hash
StatusOr<std::map<std::string, std::string>> LoadHashObject();
StatusOr<std::map<std::string, std::string>> LoadHashWithZipMap();
StatusOr<std::map<std::string, std::string>> LoadHashWithListPack();
StatusOr<std::map<std::string, std::string>> LoadHashWithZipList();
// Sorted Set
StatusOr<std::vector<MemberScore>> LoadZSetObject(int type);
StatusOr<std::vector<MemberScore>> LoadZSetWithListPack();
StatusOr<std::vector<MemberScore>> LoadZSetWithZipList();
// Set
StatusOr<std::vector<std::string>> LoadSetObject();
StatusOr<std::vector<std::string>> LoadSetWithIntSet();
StatusOr<std::vector<std::string>> LoadSetWithListPack();
// List
StatusOr<std::vector<std::string>> LoadListObject();
StatusOr<std::vector<std::string>> LoadListWithZipList();
StatusOr<std::vector<std::string>> LoadListWithQuickList(int type);
// Load rdb
Status LoadRdb(engine::Context &ctx, uint32_t db_index, bool overwrite_exist_key = true);
std::unique_ptr<RdbStream> &GetStream() { return stream_; }
Status Dump(const std::string &key, RedisType type);
Status SaveObjectType(RedisType type);
Status SaveObject(const std::string &key, RedisType type);
Status RdbSaveLen(uint64_t len);
// String
Status SaveStringObject(const std::string &value);
// List
Status SaveListObject(const std::vector<std::string> &elems);
// Set
Status SaveSetObject(const std::vector<std::string> &members);
// Sorted Set
Status SaveZSetObject(const std::vector<MemberScore> &member_scores);
// Hash
Status SaveHashObject(const std::vector<FieldValue> &field_value);
// SortedInt
Status SaveSortedintObject(const std::vector<uint64_t> &ids);
private:
engine::Storage *storage_;
std::string ns_;
std::unique_ptr<RdbStream> stream_;
StatusOr<std::string> loadLzfString();
StatusOr<std::string> loadEncodedString();
StatusOr<uint64_t> loadObjectLen(bool *is_encoded);
StatusOr<double> loadBinaryDouble();
StatusOr<double> loadDouble();
StatusOr<int> loadRdbType();
StatusOr<RedisObjValue> loadRdbObject(int rdbtype, const std::string &key);
Status saveRdbObject(engine::Context &ctx, int type, const std::string &key, const RedisObjValue &obj,
uint64_t ttl_ms);
StatusOr<uint32_t> loadExpiredTimeSeconds();
StatusOr<uint64_t> loadExpiredTimeMilliseconds(int rdb_version);
/*0-5 is the basic type of Redis objects and 9-21 is the encoding type of Redis objects.
Redis allow basic is 0-7 and 6/7 is for the module type which we don't support here.*/
static bool isObjectType(int type) { return (type >= 0 && type <= 5) || (type >= 9 && type <= 21); };
static bool isEmptyRedisObject(const RedisObjValue &value);
static int rdbEncodeInteger(long long value, unsigned char *enc);
Status rdbSaveBinaryDoubleValue(double val);
Status rdbSaveZipListObject(const std::string &elem);
};