text: // Copyright (c) 2015-present, Qihoo, Inc.  All rights reserved.
  // This source code is licensed under the BSD-style license found in the
  // LICENSE file in the root directory of this source tree. An additional grant
  // of patent rights can be found in the PATENTS file in the same directory.
  
  #include "slash_string.h"
  #include "nemo.h"
  #include "pika_kv.h"
  #include "pika_server.h"
  #include "pika_slot.h"
  
  extern PikaServer *g_pika_server;
  
  void SetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameSet);
      return;
    }
    key_ = argv[1];
    value_ = argv[2];
    condition_ = SetCmd::kANY;
    sec_ = 0;
    size_t index = 3;
    while (index != argv.size()) {
      std::string opt = slash::StringToLower(argv[index]);
      if (opt == "xx") {
        condition_ = SetCmd::kXX;
      } else if (opt == "nx") {
        condition_ = SetCmd::kNX;
      } else if (opt == "ex") {
        index++;
        if (index == argv.size()) {
          res_.SetRes(CmdRes::kSyntaxErr);
          return;
        }
        if (!slash::string2l(argv[index].data(), argv[index].size(), &sec_)) {
          res_.SetRes(CmdRes::kInvalidInt);
          return;
        }
      } else {
        res_.SetRes(CmdRes::kSyntaxErr);
        return;
      }
      index++;
    }
    return;
  }
  
  void SetCmd::Do() {
    nemo::Status s;
    int64_t res = 1;
    switch (condition_) {
      case SetCmd::kXX:
        s = g_pika_server->db()->Setxx(key_, value_, &res, sec_);
        break;
      case SetCmd::kNX:
        s = g_pika_server->db()->Setnx(key_, value_, &res, sec_);
        break;
      default:
        s = g_pika_server->db()->Set(key_, value_, sec_);
        break;
    }
  
    if (s.ok() || s.IsNotFound()) {
      if (res == 1) {
        res_.SetRes(CmdRes::kOk);
      } else {
        res_.AppendArrayLen(-1);;
      }
      SlotKeyAdd("k", key_);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void GetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameGet);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void GetCmd::Do() {
    std::string value;
    nemo::Status s = g_pika_server->db()->Get(key_, &value);
    if (s.ok()) {
      res_.AppendStringLen(value.size());
      res_.AppendContent(value);
    } else if (s.IsNotFound()) {
      res_.AppendStringLen(-1);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void DelCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameDel);
      return;
    }
    std::vector<std::string>::iterator iter = argv.begin();
    keys_.assign(++iter, argv.end());
    return;
  }
  
  void DelCmd::Do() {
    int64_t count = 0;
    std::vector<std::string>::const_iterator it;
    for (it = keys_.begin(); it != keys_.end(); it++) {
      SlotKeyRem(*it);
    }
    nemo::Status s = g_pika_server->db()->MDel(keys_, &count);
    if (s.ok()) {
      res_.AppendInteger(count);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void IncrCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameIncr);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void IncrCmd::Do() {
    std::string new_value;
    nemo::Status s = g_pika_server->db()->Incrby(key_, 1, new_value);
    if (s.ok()) {
     res_.AppendContent(":" + new_value);
     SlotKeyAdd("k", key_);
    } else if (s.IsCorruption() && s.ToString() == "Corruption: value is not a integer") {
      res_.SetRes(CmdRes::kInvalidInt);
    } else if (s.IsInvalidArgument()) {
      res_.SetRes(CmdRes::kOverFlow);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void IncrbyCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameIncrby);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &by_)) {
      res_.SetRes(CmdRes::kInvalidInt, kCmdNameIncrby);
      return;
    }
    return;
  }
  
  void IncrbyCmd::Do() {
    std::string new_value;
    nemo::Status s = g_pika_server->db()->Incrby(key_, by_, new_value);
    if (s.ok()) {
      res_.AppendContent(":" + new_value);
      SlotKeyAdd("k", key_);
    } else if (s.IsCorruption() && s.ToString() == "Corruption: value is not a integer") {
      res_.SetRes(CmdRes::kInvalidInt);
    } else if (s.IsInvalidArgument()) {
      res_.SetRes(CmdRes::kOverFlow);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void IncrbyfloatCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameIncrbyfloat);
      return;
    }
    key_ = argv[1];
    if (!slash::string2d(argv[2].data(), argv[2].size(), &by_)) {
      res_.SetRes(CmdRes::kInvalidFloat);
      return;
    }
    return;
  }
  
  void IncrbyfloatCmd::Do() {
    std::string new_value;
    nemo::Status s = g_pika_server->db()->Incrbyfloat(key_, by_, new_value);
    if (s.ok()) {
      res_.AppendStringLen(new_value.size());
      res_.AppendContent(new_value);
      SlotKeyAdd("k", key_);
    } else if (s.IsCorruption() && s.ToString() == "Corruption: value is not a float"){
      res_.SetRes(CmdRes::kInvalidFloat);
    } else if (s.IsInvalidArgument()) {
      res_.SetRes(CmdRes::kOverFlow);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void DecrCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameDecr);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void DecrCmd::Do() {
    std::string new_value;
    nemo::Status s = g_pika_server->db()->Decrby(key_, 1, new_value);
    if (s.ok()) {
     res_.AppendContent(":" + new_value);
    } else if (s.IsCorruption() && s.ToString() == "Corruption: value is not a integer") {
      res_.SetRes(CmdRes::kInvalidInt);
    } else if (s.IsInvalidArgument()) {
      res_.SetRes(CmdRes::kOverFlow);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void DecrbyCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameDecrby);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &by_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    return;
  }
  
  void DecrbyCmd::Do() {
    std::string new_value;
    nemo::Status s = g_pika_server->db()->Decrby(key_, by_, new_value);
    if (s.ok()) {
      res_.AppendContent(":" + new_value);
    } else if (s.IsCorruption() && s.ToString() == "Corruption: value is not a integer") {
      res_.SetRes(CmdRes::kInvalidInt);
    } else if (s.IsInvalidArgument()) {
      res_.SetRes(CmdRes::kOverFlow);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void GetsetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameGetset);
      return;
    }
    key_ = argv[1];
    new_value_ = argv[2];
    return;
  }
  
  void GetsetCmd::Do() {
    std::string old_value;
    nemo::Status s = g_pika_server->db()->GetSet(key_, new_value_, &old_value);
    if (s.ok()) {
      if (old_value.empty()) {
        res_.AppendContent("$-1");
      } else {
        res_.AppendStringLen(old_value.size());
        res_.AppendContent(old_value);
      }
      SlotKeyAdd("k", key_);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void AppendCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameAppend);
      return;
    }
    key_ = argv[1];
    value_ = argv[2];
    return;
  }
  
  void AppendCmd::Do() {
    int64_t new_len = 0;
    nemo::Status s = g_pika_server->db()->Append(key_, value_, &new_len);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(new_len);
      SlotKeyAdd("k", key_);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void MgetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameMget);
      return;
    }
    keys_ = argv;
    keys_.erase(keys_.begin());
    return;
  }
  
  void MgetCmd::Do() {
    std::vector<nemo::KVS> kvs_v;
    nemo::Status s = g_pika_server->db()->MGet(keys_, kvs_v);
    res_.AppendArrayLen(kvs_v.size());
    std::vector<nemo::KVS>::const_iterator iter;
    for (iter = kvs_v.begin(); iter != kvs_v.end(); iter++) {
      if ((iter->status).ok()) {
        res_.AppendStringLen((iter->val).size());
        res_.AppendContent(iter->val);
      } else {
        res_.AppendContent("$-1");
      }
    }
    return;
  }
  
  void KeysCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameKeys);
      return;
    }
    pattern_ = argv[1];
    return;
  }
  
  void KeysCmd::Do() {
    std::vector<std::string> keys;
    nemo::Status s = g_pika_server->db()->Keys(pattern_, keys);
    res_.AppendArrayLen(keys.size());
    for (std::vector<std::string>::iterator iter = keys.begin(); iter != keys.end(); iter++) {
      res_.AppendStringLen(iter->size());
      res_.AppendContent(*iter);
    }
    return;
  }
  
  void SetnxCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameSetnx);
      return;
    }
    key_ = argv[1];
    value_ = argv[2];
    return;
  }
  
  void SetnxCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->Setnx(key_, value_, &res);
    if (s.ok()) {
      res_.AppendInteger(res);
      SlotKeyAdd("k", key_);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void SetexCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameSetex);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &sec_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    value_ = argv[3];
    return;
  }
  
  void SetexCmd::Do() {
    nemo::Status s = g_pika_server->db()->Set(key_, value_, sec_);
    if (s.ok()) {
      res_.SetRes(CmdRes::kOk);
      SlotKeyAdd("k", key_);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void MsetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameMset);
      return;
    }
    size_t argc = argv.size();
    if (argc % 2 == 0) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameMset);
      return;
    }
    kvs_.clear();
    for (size_t index = 1; index != argc; index += 2) {
      kvs_.push_back({argv[index], argv[index+1]});
    }
    return;
  }
  
  void MsetCmd::Do() {
    nemo::Status s = g_pika_server->db()->MSet(kvs_);
    if (s.ok()) {
      res_.SetRes(CmdRes::kOk);
      std::vector<nemo::KV>::const_iterator it;
      for (it = kvs_.begin(); it != kvs_.end(); it++) {
        SlotKeyAdd("k", it->key);
      }
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void MsetnxCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameMsetnx);
      return;
    }
    size_t argc = argv.size();
    if (argc % 2 == 0) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameMsetnx);
      return;
    }
    kvs_.clear();
    for (size_t index = 1; index != argc; index += 2) {
      kvs_.push_back({argv[index], argv[index+1]});
    }
    return;
  }
  
  void MsetnxCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->MSetnx(kvs_, &res);
    if (s.ok()) {
      res_.AppendInteger(res);
      std::vector<nemo::KV>::const_iterator it;
      for (it = kvs_.begin(); it != kvs_.end(); it++) {
        SlotKeyAdd("k", it->key);
      }
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void GetrangeCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameGetrange);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &start_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    if (!slash::string2l(argv[3].data(), argv[3].size(), &end_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    return;
  }
  
  void GetrangeCmd::Do() {
    std::string substr;
    nemo::Status s = g_pika_server->db()->Getrange(key_, start_, end_, substr);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendStringLen(substr.size());
      res_.AppendContent(substr);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void SetrangeCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameSetrange);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &offset_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    value_ = argv[3];
    return;
  }
  
  void SetrangeCmd::Do() {
    int64_t new_len;
    nemo::Status s = g_pika_server->db()->Setrange(key_, offset_, value_, &new_len);
    if (s.ok()) {
      res_.AppendInteger(new_len);
      SlotKeyAdd("k", key_);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void StrlenCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameStrlen);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void StrlenCmd::Do() {
    int64_t len = 0;
    nemo::Status s = g_pika_server->db()->Strlen(key_, &len);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(len);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void ExistsCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameExists);
      return;
    }
    keys_ = argv;
    keys_.erase(keys_.begin());
    return;
  }
  
  void ExistsCmd::Do() {
    int64_t res;
  
    nemo::Status s = g_pika_server->db()->Exists(keys_, &res);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void ExpireCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameExpire);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &sec_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    return;
  }
  
  void ExpireCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->Expire(key_, sec_, &res);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void PexpireCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNamePexpire);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &msec_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    return;
  }
  
  void PexpireCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->Expire(key_, msec_/1000, &res);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void ExpireatCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameExpireat);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &time_stamp_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    return;
  }
  
  void ExpireatCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->Expireat(key_, time_stamp_, &res);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void PexpireatCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNamePexpireat);
      return;
    }
    key_ = argv[1];
    if (!slash::string2l(argv[2].data(), argv[2].size(), &time_stamp_ms_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    return;
  }
  
  void PexpireatCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->Expireat(key_, time_stamp_ms_/1000, &res);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
  }
  
  void TtlCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameTtl);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void TtlCmd::Do() {
    int64_t ttl = 0;
    nemo::Status s = g_pika_server->db()->TTL(key_, &ttl);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(ttl);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void PttlCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNamePttl);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void PttlCmd::Do() {
    int64_t ttl = 0;
    nemo::Status s = g_pika_server->db()->TTL(key_, &ttl);
    if (ttl > 0) {
      ttl *= 1000;
    }
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(ttl);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void PersistCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNamePersist);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void PersistCmd::Do() {
    int64_t res = 0;
    nemo::Status s = g_pika_server->db()->Persist(key_, &res);
    if (s.ok() || s.IsNotFound()) {
      res_.AppendInteger(res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void TypeCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameType);
      return;
    }
    key_ = argv[1];
    return;
  }
  
  void TypeCmd::Do() {
    std::string res;
    nemo::Status s = g_pika_server->db()->Type(key_, &res);
    if (s.ok()) {
      res_.AppendContent("+" + res);
    } else {
      res_.SetRes(CmdRes::kErrOther, s.ToString());
    }
    return;
  }
  
  void ScanCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
    if (!ptr_info->CheckArg(argv.size())) {
      res_.SetRes(CmdRes::kWrongNum, kCmdNameScan);
      return;
    }
    if (!slash::string2l(argv[1].data(), argv[1].size(), &cursor_)) {
      res_.SetRes(CmdRes::kInvalidInt);
      return;
    }
    size_t index = 2, argc = argv.size();
  
    while (index < argc) {
      std::string opt = slash::StringToLower(argv[index]); 
      if (opt == "match" || opt == "count") {
        index++;
        if (index >= argc) {
          res_.SetRes(CmdRes::kSyntaxErr);
          return;
        }
        if (opt == "match") {
          pattern_ = argv[index];
        } else if (!slash::string2l(argv[index].data(), argv[index].size(), &count_)) {
          res_.SetRes(CmdRes::kInvalidInt);
          return;
        }
      } else {
        res_.SetRes(CmdRes::kSyntaxErr);
        return;
      }
      index++;
    }
    return;
  }
  
  void ScanCmd::Do() {
    std::vector<std::string> keys;
    int64_t cursor_ret = 0;
    nemo::Status s = g_pika_server->db()->Scan(cursor_, pattern_, count_, keys, &cursor_ret);
    
    res_.AppendArrayLen(2);
  
    char buf[32];
    int len = slash::ll2string(buf, sizeof(buf), cursor_ret);
    res_.AppendStringLen(len);
    res_.AppendContent(buf);
  
    res_.AppendArrayLen(keys.size());
    std::vector<std::string>::const_iterator iter;
    for (iter = keys.begin(); iter != keys.end(); iter++) {
      res_.AppendStringLen(iter->size());
      res_.AppendContent(*iter);
    }
    return;
  }
  
  
  
  
  
  
  
  
  
  