Skip to content

Commit

Permalink
single-bit bitset works through bitmap interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Yao Yue committed Apr 24, 2018
1 parent 5868abe commit c688071
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/data_structure/bitmap/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct bitset {

#define bit2byte(_col) ((((_col) - 1) >> 3) + 1)
#define bit2long(_col) ((((_col) - 1) >> 5) + 1)
#define size2bit(_sz) ((_sz) << 5)

void bitset_init(struct bitset *bs, uint16_t ncol);

Expand Down
14 changes: 7 additions & 7 deletions src/protocol/data/redis/cmd_bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/**
* create: create a bitmap of certain size, all bits reset unless value given
* BitMap.create KEY size [value]
* BitMap.create KEY size
* Note: if size is not a multiple of the internal allocation unit (e.g. byte),
* it will be rounded up internally
* TODO: how to transfer value w/o being misrepresented due to endianness?
Expand All @@ -12,10 +12,10 @@
* BitMap.delete KEY
*
* get: get value of a column in a bitmap
* BitMap.get KEY [columnId]
* BitMap.get KEY columnId
*
* set: set value of a column in a bitmap, val optional (defaults to 1)
* BitMap.set KEY columnId [val]
* set: set value of a column in a bitmap
* BitMap.set KEY columnId val
*/

/* TODO:
Expand All @@ -28,7 +28,7 @@

/* type string #arg #opt */
#define REQ_BITMAP(ACTION) \
ACTION( REQ_BITMAP_CREATE, "BitMap.create", 3, 1 )\
ACTION( REQ_BITMAP_CREATE, "BitMap.create", 3, 0 )\
ACTION( REQ_BITMAP_DELETE, "BitMap.delete", 2, 0 )\
ACTION( REQ_BITMAP_GET, "BitMap.get", 2, 1 )\
ACTION( REQ_BITMAP_SET, "BitMap.set", 3, 1 )
ACTION( REQ_BITMAP_GET, "BitMap.get", 3, 0 )\
ACTION( REQ_BITMAP_SET, "BitMap.set", 4, 0 )
4 changes: 3 additions & 1 deletion src/protocol/data/redis/response.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ typedef struct {
* - a RSP_NUMERIC type that doesn't have a corresponding message body.
*/
#define RSP_OK "OK"
#define RSP_NOT_FOUND "NOT_FOUND"
#define RSP_NOTFOUND "NOT_FOUND"
#define RSP_PONG "PONG"
#define RSP_EXIST "EXIST" /* key already exists and op is non-overwriting */

#define RSP_ERR_ARG "Err invalid argument"
#define RSP_ERR_NOSUPPORT "Err command not supported"
#define RSP_ERR_OUTOFRANGE "Err index out of range"
#define RSP_ERR_STORAGE "Err storage failure"
#define RSP_ERR_TYPE "Err type mismatch"

Expand Down
149 changes: 135 additions & 14 deletions src/server/slimredis/data/cmd_bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <cc_debug.h>


#define it2bitset(_it) ((struct bitset *)ITEM_VAL_POS(it))

static inline struct bstring *
_get_key(struct request *req)
{
Expand All @@ -17,30 +19,52 @@ _get_key(struct request *req)
return &key->bstr;
}

static inline uint16_t
_get_col(struct response *rsp, struct request *req)
static inline int32_t
_get_col(struct response *rsp, struct request *req, uint16_t max)
{
uint64_t col = 0;
rstatus_i status;
struct element *reply = (struct element *)array_get(rsp->token, 1);
struct element *reply = (struct element *)array_get(rsp->token, 0);
struct element *arg = (struct element *)array_get(req->token, 2);

status = bstring_atou64(&col, &arg->bstr);
if (status != CC_OK || col > BITSET_COL_MAX) {
if (status != CC_OK || col > max) {
rsp->type = reply->type = ELEM_ERR;
reply->bstr = str2bstr(RSP_ERR_ARG);
log_warn("%.*s is not a valid value for bitmap size", arg->bstr.len,
log_warn("%.*s is not a valid value column id/size", arg->bstr.len,
arg->bstr.data);
INCR(process_metrics, process_ex);
INCR(process_metrics, bitmap_create_ex);

return -1;
}
return (uint16_t)col;
return (int32_t)col;
}

static inline int16_t
_get_bitval(struct response *rsp, struct request *req, uint8_t max)
{
uint64_t val = 0;
rstatus_i status;
struct element *reply = (struct element *)array_get(rsp->token, 0);
struct element *arg = (struct element *)array_get(req->token, 3);

status = bstring_atou64(&val, &arg->bstr);
if (status != CC_OK || val > max) {
rsp->type = reply->type = ELEM_ERR;
reply->bstr = str2bstr(RSP_ERR_ARG);
log_warn("%.*s is not a valid bitmap field value", arg->bstr.len,
arg->bstr.data);
INCR(process_metrics, process_ex);

return -1;
}
return (int16_t)val;
}

static inline struct item *
_add_key(struct response *rsp, struct bstring *key)
{
struct element *reply = (struct element *)array_get(rsp->token, 1);
struct element *reply = (struct element *)array_get(rsp->token, 0);
struct val val = {VAL_TYPE_STR, {null_bstring}};
struct item *it;

Expand All @@ -52,7 +76,7 @@ _add_key(struct response *rsp, struct bstring *key)

return NULL;
} else { /* cuckoo insert current won't fail as long as size is valid */
it = cuckoo_insert(key, &val, 0);
it = cuckoo_insert(key, &val, time_reltime(0));
if (it == NULL) {
rsp->type = reply->type = ELEM_ERR;
reply->bstr = str2bstr(RSP_ERR_STORAGE);
Expand All @@ -70,17 +94,18 @@ void
cmd_bitmap_create(struct response *rsp, struct request *req, struct command *cmd)
{
struct item *it;
uint16_t ncol;
int32_t ncol;
struct bstring *key = _get_key(req);
struct element *reply = (struct element *)array_push(rsp->token);

INCR(process_metrics, bitmap_create);

/* check column size first so we don't have to undo storage op if invalid */
ncol = _get_col(rsp, req);
if (ncol == 0) {
ncol = _get_col(rsp, req, BITSET_COL_MAX);
if (ncol <= 0) {
log_debug("command '%.*s' '%.*s' failed: invalid arg", cmd->bstr.len,
cmd->bstr.data, key->len, key->data);
INCR(process_metrics, bitmap_create_ex);
return;
}

Expand All @@ -92,7 +117,7 @@ cmd_bitmap_create(struct response *rsp, struct request *req, struct command *cmd
}

/* initialize data structure */
bitset_init((struct bitset *)ITEM_VAL_POS(it), ncol);
bitset_init((struct bitset *)ITEM_VAL_POS(it), (uint16_t)ncol);

rsp->type = reply->type = ELEM_STR;
reply->bstr = str2bstr(RSP_OK);
Expand Down Expand Up @@ -121,10 +146,106 @@ cmd_bitmap_delete(struct response *rsp, struct request *req, struct command *cmd
el->bstr = str2bstr(RSP_OK);
INCR(process_metrics, bitmap_delete_deleted);
} else {
el->bstr = str2bstr(RSP_NOT_FOUND);
el->bstr = str2bstr(RSP_NOTFOUND);
INCR(process_metrics, bitmap_delete_notfound);
}

log_verb("command '%.*s' on key '%.*s' returned %d", cmd->bstr.len,
cmd->bstr.data, key->len, key->data, status);
}

void
cmd_bitmap_get(struct response *rsp, struct request *req, struct command *cmd)
{
struct item *it;
int32_t col;
uint8_t val;
struct bstring *key = _get_key(req);
struct element *reply = (struct element *)array_push(rsp->token);
struct bitset *bs;

INCR(process_metrics, bitmap_set);

it = cuckoo_get(key);
if (it == NULL) {
rsp->type = reply->type = ELEM_STR;
reply->bstr = str2bstr(RSP_NOTFOUND);
log_verb("command '%.*s' on key '%.*s' : key not found", cmd->bstr.len,
cmd->bstr.data, key->len, key->data);
INCR(process_metrics, bitmap_get_notfound);

return;
}

bs = it2bitset(it);

col = _get_col(rsp, req, size2bit(bs->size) - 1);
if (col < 0) {
log_warn("command '%.*s' on key '%.*s' failed: invalid column id",
cmd->bstr.len, cmd->bstr.data, key->len, key->data);
INCR(process_metrics, bitmap_get_ex);

return;
}

val = bitset_get(bs, col);

rsp->type = reply->type = ELEM_INT;
reply->num = (int64_t)val;

log_verb("command '%.*s' key '%.*s' succeeded", cmd->bstr.len, cmd->bstr.data,
key->len, key->data);
INCR(process_metrics, bitmap_get_found);
}

void
cmd_bitmap_set(struct response *rsp, struct request *req, struct command *cmd)
{
struct item *it;
int32_t col;
int16_t val;
struct bstring *key = _get_key(req);
struct element *reply = (struct element *)array_push(rsp->token);
struct bitset *bs;

INCR(process_metrics, bitmap_set);

it = cuckoo_get(key);
if (it == NULL) {
rsp->type = reply->type = ELEM_STR;
reply->bstr = str2bstr(RSP_NOTFOUND);
log_verb("command '%.*s' on key '%.*s' : key not found", cmd->bstr.len,
cmd->bstr.data, key->len, key->data);
INCR(process_metrics, bitmap_set_notfound);

return;
}

bs = it2bitset(it);

col = _get_col(rsp, req, size2bit(bs->size) - 1);
if (col < 0) {
log_warn("command '%.*s' on key '%.*s' failed: invalid column id",
cmd->bstr.len, cmd->bstr.data, key->len, key->data);
INCR(process_metrics, bitmap_set_ex);

return;
}

val = _get_bitval(rsp, req, (1 << bs->col_w) - 1);
if (val < 0) {
log_warn("command '%.*s' on key '%.*s' failed: invalid value",
cmd->bstr.len, cmd->bstr.data, key->len, key->data);
INCR(process_metrics, bitmap_set_ex);

return;
}
bitset_set(bs, (uint16_t)col, val);

rsp->type = reply->type = ELEM_STR;
reply->bstr = str2bstr(RSP_OK);

log_verb("command '%.*s' key '%.*s' succeeded", cmd->bstr.len, cmd->bstr.data,
key->len, key->data);
INCR(process_metrics, bitmap_set_stored);
}
8 changes: 7 additions & 1 deletion src/server/slimredis/data/cmd_bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
ACTION( bitmap_delete_deleted, METRIC_COUNTER, "# bitmap delete success" )\
ACTION( bitmap_delete_notfound, METRIC_COUNTER, "# bitmap delete notfound" )\
ACTION( bitmap_get, METRIC_COUNTER, "# bitmap get requests" )\
ACTION( bitmap_set, METRIC_COUNTER, "# bitmap set requests" )
ACTION( bitmap_get_found, METRIC_COUNTER, "# bitmap get found" )\
ACTION( bitmap_get_notfound, METRIC_COUNTER, "# bitmap get notfound" )\
ACTION( bitmap_get_ex, METRIC_COUNTER, "# bitmap get exception" )\
ACTION( bitmap_set, METRIC_COUNTER, "# bitmap set requests" )\
ACTION( bitmap_set_stored, METRIC_COUNTER, "# bitmap set value set" )\
ACTION( bitmap_set_notfound, METRIC_COUNTER, "# bitmap set notfound" )\
ACTION( bitmap_set_ex, METRIC_COUNTER, "# bitmap set exception" )

struct request;
struct response;
Expand Down
14 changes: 14 additions & 0 deletions src/server/slimredis/data/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ process_setup(process_options_st *options, process_metrics_st *metrics)
command_registry[REQ_PING] = cmd_ping;

command_registry[REQ_BITMAP_DELETE] = cmd_bitmap_delete;
command_registry[REQ_BITMAP_CREATE] = cmd_bitmap_create;
command_registry[REQ_BITMAP_SET] = cmd_bitmap_set;
command_registry[REQ_BITMAP_GET] = cmd_bitmap_get;

process_init = true;
}
Expand All @@ -65,6 +68,17 @@ process_request(struct response *rsp, struct request *req)
struct command cmd;
command_fn func = command_registry[req->type];

if (func == NULL) {
struct element *reply = (struct element *)array_push(rsp->token);
log_warn("command is recognized but not implemented");

rsp->type = reply->type = ELEM_ERR;
reply->bstr = str2bstr(RSP_ERR_NOSUPPORT);
INCR(process_metrics, process_ex);

return;
}

cmd = command_table[req->type];
cmd.nopt = req->token->nelem - cmd.narg;

Expand Down

0 comments on commit c688071

Please sign in to comment.