Skip to content

Commit

Permalink
feat: definition and implementation of the incrbyfloat command (#67)
Browse files Browse the repository at this point in the history
* feat: add and implement the incrby command

* fix: deleted print log

* feat: resolve the issues found in pr

* fix: initialize pointer

* fix: params nums

* fix: fix commond params num

* feat: fix review bug

* feat: definition and implementation of the incrbyfloat command

* style: format code style

* fix: resolve converstaion

* fix: value initialization

* fix: value initialization

* Update cmd_kv.cc

---------

Co-authored-by: Xin.Zh <[email protected]>
  • Loading branch information
jettcc and AlexStocks authored Dec 10, 2023
1 parent 232e3a9 commit ad6d274
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 6 deletions.
Empty file.
1 change: 1 addition & 0 deletions src/base_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const std::string kCmdNameStrlen = "strlen";
const std::string kCmdNameSetex = "setex";
const std::string kCmdNamePsetex = "psetex";
const std::string kCmdNameSetnx = "setnx";
const std::string kCmdNameIncrbyfloat = "incrbyfloat";
const std::string kCmdNameGetBit = "getbit";

// multi
Expand Down
45 changes: 40 additions & 5 deletions src/cmd_kv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

#include "cmd_kv.h"
#include "pstd/pstd_string.h"
#include "common.h"
#include "pstd_string.h"
#include "pstd_util.h"
#include "store.h"

Expand Down Expand Up @@ -413,10 +414,10 @@ bool IncrbyCmd::DoInitial(PClient* client) {
}

void IncrbyCmd::DoCmd(PClient* client) {
int64_t new_value_ = 0;
int64_t new_value = 0;
int64_t by_ = 0;
pstd::String2int(client->argv_[2].data(), client->argv_[2].size(), &by_);
PError err = PSTORE.Incrby(client->Key(), by_, &new_value_);
PError err = PSTORE.Incrby(client->Key(), by_, &new_value);
switch (err) {
case PError_type:
client->SetRes(CmdRes::kInvalidInt);
Expand All @@ -427,14 +428,48 @@ void IncrbyCmd::DoCmd(PClient* client) {
client->AppendInteger(by_);
break;
case PError_ok:
client->AppendInteger(new_value_);
client->AppendInteger(new_value);
break;
default:
client->SetRes(CmdRes::kErrOther, "incrby cmd error");
break;
}
}

IncrbyfloatCmd::IncrbyfloatCmd(const std::string& name, int16_t arity)
: BaseCmd(name, arity, CmdFlagsWrite, AclCategoryWrite | AclCategoryString) {}

bool IncrbyfloatCmd::DoInitial(PClient* client) {
long double by_ = 0.00f;
if (StrToLongDouble(client->argv_[2].data(), client->argv_[2].size(), &by_)) {
client->SetRes(CmdRes::kInvalidFloat);
return false;
}
client->SetKey(client->argv_[1]);
return true;
}

void IncrbyfloatCmd::DoCmd(PClient* client) {
std::string new_value;
PError err = PSTORE.Incrbyfloat(client->argv_[1], client->argv_[2], &new_value);
switch (err) {
case PError_type:
client->SetRes(CmdRes::kInvalidFloat);
break;
case PError_notExist: // key not exist, set a new value
PSTORE.ClearExpire(client->Key()); // clear key's old ttl
PSTORE.SetValue(client->Key(), PObject::CreateString(client->argv_[2]));
client->AppendString(client->argv_[2]);
break;
case PError_ok:
client->AppendString(new_value);
break;
default:
client->SetRes(CmdRes::kErrOther, "incrbyfloat cmd error");
break;
}
}

SetnxCmd::SetnxCmd(const std::string& name, int16_t arity)
: BaseCmd(name, arity, CmdFlagsWrite, AclCategoryWrite | AclCategoryString) {}

Expand Down Expand Up @@ -499,4 +534,4 @@ void GetBitCmd::DoCmd(PClient* client) {
return;
}

} // namespace pikiwidb
} // namespace pikiwidb
11 changes: 11 additions & 0 deletions src/cmd_kv.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,15 @@ class GetBitCmd : public BaseCmd {
void DoCmd(PClient *client) override;
};

class IncrbyfloatCmd : public BaseCmd {
public:
IncrbyfloatCmd(const std::string &name, int16_t arity);

protected:
bool DoInitial(PClient *client) override;

private:
void DoCmd(PClient *client) override;
};

} // namespace pikiwidb
2 changes: 2 additions & 0 deletions src/cmd_table_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ void CmdTableManager::InitCmdTable() {
cmds_->insert(std::make_pair(kCmdNameBitCount, std::move(bitcountPtr)));
std::unique_ptr<BaseCmd> incrbyPtr = std::make_unique<IncrbyCmd>(kCmdNameIncrby, 3);
cmds_->insert(std::make_pair(kCmdNameIncrby, std::move(incrbyPtr)));
std::unique_ptr<BaseCmd> incrbyfloatPtr = std::make_unique<IncrbyfloatCmd>(kCmdNameIncrbyfloat, 3);
cmds_->insert(std::make_pair(kCmdNameIncrbyfloat, std::move(incrbyfloatPtr)));
std::unique_ptr<BaseCmd> strlenPtr = std::make_unique<StrlenCmd>(kCmdNameStrlen, 2);
cmds_->insert(std::make_pair(kCmdNameStrlen, std::move(strlenPtr)));
std::unique_ptr<BaseCmd> setexPtr = std::make_unique<SetexCmd>(kCmdNameSetex, 4);
Expand Down
47 changes: 47 additions & 0 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
*/

#include "common.h"
#include <math.h>
#include <algorithm>
#include <cerrno>
#include <chrono>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <limits>
#include <sstream>
#include "unbounded_buffer.h"

namespace pikiwidb {
Expand Down Expand Up @@ -44,6 +47,50 @@ struct PErrorInfo g_errorInfo[] = {

int Double2Str(char* ptr, std::size_t nBytes, double val) { return snprintf(ptr, nBytes - 1, "%.6g", val); }

int StrToLongDouble(const char* s, size_t slen, long double* ldval) {
char* pEnd;
std::string t(s, slen);
if (t.find(' ') != std::string::npos) {
return -1;
}
long double d = strtold(s, &pEnd);
if (pEnd != s + slen) {
return -1;
}

if (ldval) {
*ldval = d;
}
return 0;
}

int LongDoubleToStr(long double ldval, std::string* value) {
if (isnan(ldval)) {
return -1;
} else if (isinf(ldval)) {
if (ldval > 0) {
*value = "inf";
} else {
*value = "-inf";
}
return -1;
} else {
std::ostringstream oss;
oss << std::setprecision(15) << ldval;
*value = oss.str();

// Remove trailing zeroes after the '.'
size_t dotPos = value->find('.');
if (dotPos != std::string::npos) {
value->erase(value->find_last_not_of('0') + 1, std::string::npos);
if (value->back() == '.') {
value->pop_back();
}
}
return 0;
}
}

bool TryStr2Long(const char* ptr, size_t nBytes, long& val) {
bool negtive = false;
size_t i = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ enum PError {
PError_moduleinit = 16,
PError_moduleuninit = 17,
PError_modulerepeat = 18,
PError_overflow = 19,
PError_max,
};

Expand Down Expand Up @@ -145,6 +146,8 @@ inline std::size_t Number2Str(char* ptr, std::size_t nBytes, T val) {
}

int Double2Str(char* ptr, std::size_t nBytes, double val);
int StrToLongDouble(const char* s, size_t slen, long double* ldval);
int LongDoubleToStr(long double ldval, std::string* value);
bool TryStr2Long(const char* ptr, std::size_t nBytes, long& val); // only for decimal
bool Strtol(const char* ptr, std::size_t nBytes, long* outVal);
bool Strtoll(const char* ptr, std::size_t nBytes, long long* outVal);
Expand Down
46 changes: 45 additions & 1 deletion src/store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
#include <cassert>
#include <limits>
#include "client.h"
#include "common.h"
#include "config.h"
#include "event_loop.h"
#include "leveldb.h"
#include "log.h"
#include "multi.h"

namespace pikiwidb {

uint32_t PObject::lruclock = static_cast<uint32_t>(::time(nullptr));
Expand Down Expand Up @@ -589,6 +589,50 @@ PError PStore::Incrby(const PString& key, int64_t value, int64_t* ret) {
return PError_ok;
}

PError PStore::Incrbyfloat(const PString& key, std::string value, std::string* ret) {
PObject* old_value = nullptr;
long double old_number = 0.00f;
long double long_double_by = 0.00f;
auto db = &dbs_[dbno_];

if (StrToLongDouble(value.data(), value.size(), &long_double_by)) {
return PError_type;
}

// shared when reading
std::unique_lock<std::shared_mutex> lock(mutex_);
PError err = getValueByType(key, old_value, PType_string);
if (err != PError_ok) {
return err;
}

auto old_number_str = pikiwidb::GetDecodedString(old_value);
// old number to long double
if (StrToLongDouble(old_number_str->c_str(), old_number_str->size(), &old_number)) {
return PError_type;
}

std::string total_string;
long double total = old_number + long_double_by;
if (LongDoubleToStr(total, &total_string)) {
return PError_overflow;
}

*ret = total_string;
PObject new_value;
new_value = PObject::CreateString(total_string);
new_value.lru = PObject::lruclock;
auto [realObj, status] = db->insert_or_assign(key, std::move(new_value));
const PObject& obj = realObj->second;

// put this key to sync list
if (!waitSyncKeys_.empty()) {
waitSyncKeys_[dbno_].insert_or_assign(key, &obj);
}

return PError_ok;
}

void PStore::SetExpire(const PString& key, uint64_t when) const { expiredDBs_[dbno_].SetExpire(key, when); }

int64_t PStore::TTL(const PString& key, uint64_t now) { return expiredDBs_[dbno_].TTL(key, now); }
Expand Down
1 change: 1 addition & 0 deletions src/store.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class PStore {
PObject* SetValue(const PString& key, PObject&& value);
// incr
PError Incrby(const PString& key, int64_t value, int64_t* ret);
PError Incrbyfloat(const PString& key, std::string value, std::string* ret);

// for expire key
enum ExpireResult : std::int8_t {
Expand Down

0 comments on commit ad6d274

Please sign in to comment.