Skip to content

Commit

Permalink
new feature:bitmap
Browse files Browse the repository at this point in the history
  • Loading branch information
wenduo committed Jun 3, 2016
1 parent 1f0aa65 commit 7f7ce0c
Show file tree
Hide file tree
Showing 5 changed files with 378 additions and 0 deletions.
98 changes: 98 additions & 0 deletions include/pika_bit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#ifndef PIKA_BIT_H_
#define PIKA_BIT_H_
#include "pika_command.h"
#include "nemo.h"


/*
* bitoperation
*/
class BitGetCmd : public Cmd {
public:
BitGetCmd() {};
virtual void Do();
private:
std::string key_;
int64_t bit_offset_;
virtual void Clear() {
key_ = "";
bit_offset_ = -1;
}

virtual void DoInitial(PikaCmdArgsType &argvs, const CmdInfo* const ptr_info);
};

class BitSetCmd : public Cmd {
public:
BitSetCmd() {};
virtual void Do();
private:
std::string key_;
int64_t bit_offset_;
int64_t on_;
virtual void Clear() {
key_ = "";
bit_offset_ = -1;
on_ = -1;
}
virtual void DoInitial(PikaCmdArgsType &argvs, const CmdInfo* const ptr_info);
};

class BitCountCmd : public Cmd {
public:
BitCountCmd() {}
virtual void Do();
private:
std::string key_;
bool count_all_;
int64_t start_offset_;
int64_t end_offset_;
virtual void Clear() {
key_ = "";
count_all_ = false;
start_offset_ = -1;
end_offset_ = -1;
}
virtual void DoInitial(PikaCmdArgsType &argvs, const CmdInfo* const ptr_info);
};

class BitPosCmd : public Cmd {
public:
BitPosCmd() {};
virtual void Do();
private:
std::string key_;
bool pos_all_;
bool endoffset_set_;
int64_t bit_val_;
int64_t start_offset_;
int64_t end_offset_;
virtual void Clear() {
key_ = "";
pos_all_ = false;
endoffset_set_ = false;
bit_val_ = -1;
start_offset_ = -1;
end_offset_ = -1;
}

virtual void DoInitial(PikaCmdArgsType &argvs, const CmdInfo* const ptr_info);
};

class BitOpCmd : public Cmd {
public:
BitOpCmd() {};
virtual void Do();
private:
std::string dest_key_;
std::vector<std::string> src_keys_;
nemo::BitOpType op_;
virtual void Clear() {
dest_key_ = "";
src_keys_.clear();
op_ = nemo::kBitOpDefault;
}

virtual void DoInitial(PikaCmdArgsType &argvs, const CmdInfo* const ptr_info);
};
#endif
21 changes: 21 additions & 0 deletions include/pika_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ const std::string kCmdNameRPopLPush = "rpoplpush";
const std::string kCmdNameRPush = "rpush";
const std::string kCmdNameRPushx = "rpushx";

//BitMap
const std::string kCmdNameBitSet = "setbit";
const std::string kCmdNameBitGet = "getbit";
const std::string kCmdNameBitPos = "bitpos";
const std::string kCmdNameBitOp = "bitop";
const std::string kCmdNameBitCount = "bitcount";

//Zset
const std::string kCmdNameZAdd = "zadd";
const std::string kCmdNameZCard = "zcard";
Expand Down Expand Up @@ -151,6 +158,7 @@ enum CmdFlags {
kCmdFlagsList = 6,
kCmdFlagsSet = 8,
kCmdFlagsZset = 10,
kCmdFlagsBit = 12,
kCmdFlagsNoLocal = 0, //default nolocal
kCmdFlagsLocal = 16,
kCmdFlagsNoSuspend = 0, //default nosuspend
Expand Down Expand Up @@ -217,6 +225,10 @@ class CmdRes {
kPong,
kSyntaxErr,
kInvalidInt,
kInvalidBitInt,
kInvalidBitOffsetInt,
kInvalidBitPosArgument,
kWrongBitOpNotNum,
kInvalidFloat,
kOverFlow,
kNotFound,
Expand Down Expand Up @@ -257,6 +269,15 @@ class CmdRes {
return "-ERR syntax error\r\n";
case kInvalidInt:
return "-ERR value is not an integer or out of range\r\n";
case kInvalidBitInt:
return "-ERR bit is not an integer or out of range\r\n";
case kInvalidBitOffsetInt:
return "-ERR bit offset is not an integer or out of range\r\n";
case kWrongBitOpNotNum:
return "-ERR BITOP NOT must be called with a single source key.\r\n";

case kInvalidBitPosArgument:
return "-ERR The bit argument must be 1 or 0.\r\n";
case kInvalidFloat:
return "-ERR value is not an float\r\n";
case kOverFlow:
Expand Down
2 changes: 2 additions & 0 deletions include/pika_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ const std::string kManifest = "manifest";
const std::string kInnerReplOk = "ok";
const std::string kInnerReplWait = "wait";

const unsigned int kMaxBitOpInputKey = 12800;
const int kMaxBitOpInputBit = 21;
/*
* db sync
*/
Expand Down
222 changes: 222 additions & 0 deletions src/pika_bit.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#include <limits>
#include "slash_string.h"
#include "nemo.h"
#include "pika_bit.h"
#include "pika_server.h"

extern PikaServer *g_pika_server;

void BitSetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
if (!ptr_info->CheckArg(argv.size())) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameBitSet);
return;
}
key_ = argv[1];
if (!slash::string2l(argv[2].data(), argv[2].size(), &bit_offset_)) {
res_.SetRes(CmdRes::kInvalidBitOffsetInt);
return;
}
if (!slash::string2l(argv[3].data(), argv[3].size(), &on_)) {
res_.SetRes(CmdRes::kInvalidBitInt);
return;
}
if (bit_offset_ < 0) {
res_.SetRes(CmdRes::kInvalidBitOffsetInt);
return;
}
// value no bigger than 2^18
if ( (bit_offset_ >> kMaxBitOpInputBit) > 0) {
res_.SetRes(CmdRes::kInvalidBitOffsetInt);
return;
}
if (on_ & ~1) {
res_.SetRes(CmdRes::kInvalidBitInt);
return;
}
return;
}

void BitSetCmd::Do() {
std::string value;
int64_t bit_val;
nemo::Status s = g_pika_server->db()->BitSet(key_, bit_offset_, on_, &bit_val);
if (s.ok()){
res_.AppendInteger((int)bit_val);
} else {
res_.SetRes(CmdRes::kErrOther, s.ToString());
}
}

void BitGetCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
if (!ptr_info->CheckArg(argv.size())) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameBitGet);
return;
}
key_ = argv[1];
if (!slash::string2l(argv[2].data(), argv[2].size(), &bit_offset_)) {
res_.SetRes(CmdRes::kInvalidBitOffsetInt);
return;
}
if (bit_offset_ < 0) {
res_.SetRes(CmdRes::kInvalidBitOffsetInt);
return;
}
return;
}

void BitGetCmd::Do() {
int64_t bit_val;
nemo::Status s = g_pika_server->db()->BitGet(key_, bit_offset_, &bit_val);
if (s.ok()) {
res_.AppendInteger((int)bit_val);
} else {
res_.SetRes(CmdRes::kErrOther, s.ToString());
}
}

void BitCountCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
if (!ptr_info->CheckArg(argv.size())) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameSet);
return;
}
key_ = argv[1];
if (argv.size() == 4) {
count_all_ = false;
if (!slash::string2l(argv[2].data(), argv[2].size(), &start_offset_)) {
res_.SetRes(CmdRes::kInvalidInt);
return;
}
if (!slash::string2l(argv[3].data(), argv[3].size(), &end_offset_)) {
res_.SetRes(CmdRes::kInvalidInt);
return;
}
} else if (argv.size() == 2) {
count_all_ = true;
} else {
res_.SetRes(CmdRes::kSyntaxErr, kCmdNameBitCount);
}
return;
}

void BitCountCmd::Do() {
int64_t bit_val;
nemo::Status s;
if (count_all_)
s = g_pika_server->db()->BitCount(key_, &bit_val);
else if (!count_all_)
s = g_pika_server->db()->BitCount(key_, start_offset_, end_offset_, &bit_val);
if (s.ok()) {
res_.AppendInteger((int)bit_val);
} else {
res_.SetRes(CmdRes::kErrOther, s.ToString());
}
}

void BitPosCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
if (!ptr_info->CheckArg(argv.size())) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameBitPos);
return;
}
key_ = argv[1];
if (!slash::string2l(argv[2].data(), argv[2].size(), &bit_val_)) {
res_.SetRes(CmdRes::kInvalidInt);
return;
}
if (bit_val_ & ~1) {
res_.SetRes(CmdRes::kInvalidBitPosArgument);
return;
}
if (argv.size() == 3) {
pos_all_ = true;
endoffset_set_ = false;
} else if (argv.size() == 4) {
pos_all_ = false;
endoffset_set_ = false;
if (!slash::string2l(argv[3].data(), argv[3].size(), &start_offset_)) {
res_.SetRes(CmdRes::kInvalidInt);
return;
}
} else if (argv.size() == 5) {
pos_all_ = false;
endoffset_set_ = true;
if (!slash::string2l(argv[3].data(), argv[3].size(), &start_offset_)) {
res_.SetRes(CmdRes::kInvalidInt);
return;
}
if (!slash::string2l(argv[4].data(), argv[4].size(), &end_offset_)) {
res_.SetRes(CmdRes::kInvalidInt);
return;
}
} else
res_.SetRes(CmdRes::kSyntaxErr, kCmdNameBitPos);
return;
}

void BitPosCmd::Do() {
int64_t pos;
nemo::Status s;
if (pos_all_) {
s = g_pika_server->db()->BitPos(key_, bit_val_, &pos);
}
else if (!pos_all_ && !endoffset_set_) {
s = g_pika_server->db()->BitPos(key_, bit_val_, start_offset_, &pos);
} else if (!pos_all_ && endoffset_set_) {
s = g_pika_server->db()->BitPos(key_, bit_val_, start_offset_, end_offset_, &pos);
}
if (s.ok()) {
res_.AppendInteger((int)pos);
} else {
res_.SetRes(CmdRes::kErrOther, s.ToString());
}
}

void BitOpCmd::DoInitial(PikaCmdArgsType &argv, const CmdInfo* const ptr_info) {
if (!ptr_info->CheckArg(argv.size())) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameBitOp);
return;
}
std::string op_str = slash::StringToLower(argv[1]);
if (op_str == "not") {
op_ = nemo::kBitOpNot;
} else if (op_str == "and") {
op_ = nemo::kBitOpAnd;
} else if (op_str == "or") {
op_ = nemo::kBitOpOr;
} else if (op_str == "xor") {
op_ = nemo::kBitOpXor;
} else {
res_.SetRes(CmdRes::kSyntaxErr, kCmdNameBitOp);
return;
}
if (op_ == nemo::kBitOpNot && argv.size() != 4) {
res_.SetRes(CmdRes::kWrongBitOpNotNum, kCmdNameBitOp);
return;
} else if (op_ != nemo::kBitOpNot && argv.size() < 4) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameBitOp);
return;
} else if (argv.size() >= kMaxBitOpInputKey) {
res_.SetRes(CmdRes::kWrongNum, kCmdNameBitOp);
return;
}

dest_key_ = argv[2].data();
for(unsigned int i = 3; i <= argv.size() - 1; i++) {
src_keys_.push_back(argv[i].data());
}
return;
}

void BitOpCmd::Do() {
std::int64_t result_length;
nemo::Status s;
s = g_pika_server->db()->BitOp(op_, dest_key_, src_keys_, &result_length);
if (s.ok()) {
res_.AppendInteger((int)result_length);
} else {
res_.SetRes(CmdRes::kErrOther, s.ToString());
}

}



Loading

0 comments on commit 7f7ce0c

Please sign in to comment.