diff --git a/src/base_cmd.h b/src/base_cmd.h index 17ff6b432..f36f9079b 100644 --- a/src/base_cmd.h +++ b/src/base_cmd.h @@ -25,6 +25,10 @@ namespace pikiwidb { const std::string kCmdNameSet = "set"; const std::string kCmdNameGet = "get"; const std::string kCmdNameIncrby = "incrby"; +const std::string kCmdNameStrlen = "strlen"; +const std::string kCmdNameSetex = "setex"; +const std::string kCmdNamePsetex = "psetex"; +const std::string kCmdNameSetnx = "setnx"; // multi const std::string kCmdNameMulti = "multi"; diff --git a/src/cmd_kv.cc b/src/cmd_kv.cc index b9f7aa970..da9249780 100644 --- a/src/cmd_kv.cc +++ b/src/cmd_kv.cc @@ -7,6 +7,7 @@ #include "cmd_kv.h" #include "pstd_string.h" +#include "pstd_util.h" #include "store.h" namespace pikiwidb { @@ -215,6 +216,78 @@ void BitCountCmd::DoCmd(PClient* client) { client->AppendInteger(static_cast(count)); } +StrlenCmd::StrlenCmd(const std::string& name, int16_t arity) + : BaseCmd(name, arity, CmdFlagsReadonly, AclCategoryRead | AclCategoryString) {} + +bool StrlenCmd::DoInitial(PClient* client) { + client->SetKey(client->argv_[1]); + return true; +} + +void StrlenCmd::DoCmd(PClient* client) { + PObject* value = nullptr; + PError err = PSTORE.GetValueByType(client->Key(), value, PType_string); + + switch (err) { + case PError_ok: { + auto str = GetDecodedString(value); + size_t len = str->size(); + client->AppendInteger(static_cast(len)); + break; + } + case PError_notExist: { + client->AppendInteger(0); + break; + } + default: { + client->SetRes(CmdRes::kErrOther, "error other"); + break; + } + } +} + +SetexCmd::SetexCmd(const std::string& name, int16_t arity) + : BaseCmd(name, arity, CmdFlagsWrite, AclCategoryWrite | AclCategoryString) {} + +bool SetexCmd::DoInitial(PClient* client) { + client->SetKey(client->argv_[1]); + int64_t sec = 0; + if (pstd::String2int(client->argv_[2], &sec) == 0) { + client->SetRes(CmdRes::kInvalidInt); + return false; + } + return true; +} + +void SetexCmd::DoCmd(PClient* client) { + PSTORE.SetValue(client->argv_[1], PObject::CreateString(client->argv_[3])); + int64_t sec = 0; + pstd::String2int(client->argv_[2], &sec); + PSTORE.SetExpire(client->argv_[1], pstd::UnixMilliTimestamp() + sec * 1000); + client->SetRes(CmdRes::kOk); +} + +PsetexCmd::PsetexCmd(const std::string& name, int16_t arity) + : BaseCmd(name, arity, CmdFlagsWrite, AclCategoryWrite | AclCategoryString) {} + +bool PsetexCmd::DoInitial(PClient* client) { + client->SetKey(client->argv_[1]); + int64_t msec = 0; + if (pstd::String2int(client->argv_[2], &msec) == 0) { + client->SetRes(CmdRes::kInvalidInt); + return false; + } + return true; +} + +void PsetexCmd::DoCmd(PClient* client) { + PSTORE.SetValue(client->argv_[1], PObject::CreateString(client->argv_[3])); + int64_t msec = 0; + pstd::String2int(client->argv_[2], &msec); + PSTORE.SetExpire(client->argv_[1], pstd::UnixMilliTimestamp() + msec); + client->SetRes(CmdRes::kOk); +} + IncrbyCmd::IncrbyCmd(const std::string& name, int16_t arity) : BaseCmd(name, arity, CmdFlagsWrite, AclCategoryWrite | AclCategoryString) {} @@ -250,4 +323,26 @@ void IncrbyCmd::DoCmd(PClient* client) { break; } } + +SetnxCmd::SetnxCmd(const std::string& name, int16_t arity) + : BaseCmd(name, arity, CmdFlagsWrite, AclCategoryWrite | AclCategoryString) {} + +bool SetnxCmd::DoInitial(PClient* client) { + client->SetKey(client->argv_[1]); + return true; +} + +void SetnxCmd::DoCmd(PClient* client) { + int iSuccess = 1; + PObject* value = nullptr; + PError err = PSTORE.GetValue(client->argv_[1], value); + if (err == PError_notExist) { + PSTORE.ClearExpire(client->argv_[1]); // clear key's old ttl + PSTORE.SetValue(client->argv_[1], PObject::CreateString(client->argv_[2])); + client->AppendInteger(iSuccess); + } else { + client->AppendInteger(!iSuccess); + } +} + } // namespace pikiwidb diff --git a/src/cmd_kv.h b/src/cmd_kv.h index e3ef2bab7..94114af42 100644 --- a/src/cmd_kv.h +++ b/src/cmd_kv.h @@ -33,6 +33,50 @@ class SetCmd : public BaseCmd { void DoCmd(PClient *client) override; }; +class StrlenCmd : public BaseCmd { + public: + StrlenCmd(const std::string &name, int16_t arity); + + protected: + bool DoInitial(PClient *client) override; + + private: + void DoCmd(PClient *client) override; +}; + +class SetexCmd : public BaseCmd { + public: + SetexCmd(const std::string &name, int16_t arity); + + protected: + bool DoInitial(PClient *client) override; + + private: + void DoCmd(PClient *client) override; +}; + +class PsetexCmd : public BaseCmd { + public: + PsetexCmd(const std::string &name, int16_t arity); + + protected: + bool DoInitial(PClient *client) override; + + private: + void DoCmd(PClient *client) override; +}; + +class SetnxCmd : public BaseCmd { + public: + SetnxCmd(const std::string &name, int16_t arity); + + protected: + bool DoInitial(PClient *client) override; + + private: + void DoCmd(PClient *client) override; +}; + class AppendCmd : public BaseCmd { public: AppendCmd(const std::string &name, int16_t arity); diff --git a/src/cmd_table_manager.cc b/src/cmd_table_manager.cc index 92215f1be..1b37ca780 100644 --- a/src/cmd_table_manager.cc +++ b/src/cmd_table_manager.cc @@ -42,9 +42,16 @@ void CmdTableManager::InitCmdTable() { cmds_->insert(std::make_pair(kCmdNameMset, std::move(msetPtr))); std::unique_ptr bitcountPtr = std::make_unique(kCmdNameBitCount, -2); cmds_->insert(std::make_pair(kCmdNameBitCount, std::move(bitcountPtr))); - std::unique_ptr incrbyPtr = std::make_unique(kCmdNameIncrby, 3); cmds_->insert(std::make_pair(kCmdNameIncrby, std::move(incrbyPtr))); + std::unique_ptr strlenPtr = std::make_unique(kCmdNameStrlen, 2); + cmds_->insert(std::make_pair(kCmdNameStrlen, std::move(strlenPtr))); + std::unique_ptr setexPtr = std::make_unique(kCmdNameSetex, 4); + cmds_->insert(std::make_pair(kCmdNameSetex, std::move(setexPtr))); + std::unique_ptr psetexPtr = std::make_unique(kCmdNamePsetex, 4); + cmds_->insert(std::make_pair(kCmdNamePsetex, std::move(psetexPtr))); + std::unique_ptr setnxPtr = std::make_unique(kCmdNameSetnx, 3); + cmds_->insert(std::make_pair(kCmdNameSetnx, std::move(setnxPtr))); } std::pair CmdTableManager::GetCommand(const std::string& cmdName, PClient* client) {