summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2023-03-09 21:42:25 -0800
committerdormando <dormando@rydia.net>2023-03-26 16:48:37 -0700
commit5910b652428ac96dc6d9917d4bc73d8d400ab0f3 (patch)
tree0797e6bb8b048d03f88cf21d817c7ff317fcf206
parentdb0e5b33b0d1043bb51346e7d7cf9bd317a64921 (diff)
downloadmemcached-5910b652428ac96dc6d9917d4bc73d8d400ab0f3.tar.gz
mcmc: upstream updates
-rw-r--r--vendor/mcmc/mcmc.c49
-rw-r--r--vendor/mcmc/mcmc.h9
2 files changed, 55 insertions, 3 deletions
diff --git a/vendor/mcmc/mcmc.c b/vendor/mcmc/mcmc.c
index cdd5142..902e704 100644
--- a/vendor/mcmc/mcmc.c
+++ b/vendor/mcmc/mcmc.c
@@ -115,6 +115,33 @@ static int _mcmc_parse_value_line(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
return MCMC_CODE_OK;
}
+static int _mcmc_parse_stat_line(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
+ char *buf = ctx->buffer_head;
+ char *p = buf+5; // pass "STAT "
+ size_t l = ctx->buffer_request_len;
+
+ // STAT key value
+ char *sname = p;
+ p = memchr(p, ' ', l-5);
+ if (p == NULL) {
+ return -MCMC_ERR_VALUE;
+ }
+
+ int snamelen = p - sname;
+ while (*p == ' ') {
+ p++;
+ }
+ char *stat = p;
+ int statlen = l - (p - ctx->buffer_head) - 2;
+
+ r->sname = sname;
+ r->snamelen = snamelen;
+ r->stat = stat;
+ r->statlen = statlen;
+
+ return MCMC_CODE_OK;
+}
+
// FIXME: This is broken for ASCII multiget.
// if we get VALUE back, we need to stay in ASCII GET read mode until an END
// is seen.
@@ -125,7 +152,7 @@ static int _mcmc_parse_response(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
int rlen; // response code length.
int more = 0;
r->reslen = ctx->buffer_request_len;
- r->type = MCMC_RESP_GENERIC;
+ r->type = MCMC_RESP_FAIL;
// walk until the \r\n
while (l-- > 2) {
@@ -213,6 +240,7 @@ static int _mcmc_parse_response(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
char *n = NULL;
uint32_t vsize = strtoul(cur, &n, 10);
if ((errno == ERANGE) || (cur == n)) {
+ r->type = MCMC_RESP_FAIL;
code = -MCMC_ERR_PARSE;
} else {
r->vlen = vsize + 2; // tag in the \r\n.
@@ -230,6 +258,7 @@ static int _mcmc_parse_response(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
code = MCMC_CODE_OK;
}
} else {
+ r->type = MCMC_RESP_FAIL;
code = -MCMC_ERR_PARSE;
}
}
@@ -257,7 +286,7 @@ static int _mcmc_parse_response(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
if (memcmp(buf, "STAT", 4) == 0) {
r->type = MCMC_RESP_STAT;
ctx->state = STATE_STAT_RESP;
- // TODO: initialize stat reader mode.
+ code = _mcmc_parse_stat_line(ctx, r);
}
break;
case 5:
@@ -268,20 +297,27 @@ static int _mcmc_parse_response(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
} else {
code = -MCMC_ERR_PARSE;
}
+ } else if (memcmp(buf, "ERROR", 5) == 0) {
+ r->type = MCMC_RESP_ERRMSG;
+ code = -MCMC_CODE_ERROR;
}
break;
case 6:
if (memcmp(buf, "STORED", 6) == 0) {
+ r->type = MCMC_RESP_GENERIC;
code = MCMC_CODE_STORED;
} else if (memcmp(buf, "EXISTS", 6) == 0) {
+ r->type = MCMC_RESP_GENERIC;
code = MCMC_CODE_EXISTS;
// TODO: type -> ASCII?
}
break;
case 7:
if (memcmp(buf, "DELETED", 7) == 0) {
+ r->type = MCMC_RESP_GENERIC;
code = MCMC_CODE_DELETED;
} else if (memcmp(buf, "TOUCHED", 7) == 0) {
+ r->type = MCMC_RESP_GENERIC;
code = MCMC_CODE_TOUCHED;
} else if (memcmp(buf, "VERSION", 7) == 0) {
code = MCMC_CODE_VERSION;
@@ -291,16 +327,25 @@ static int _mcmc_parse_response(mcmc_ctx_t *ctx, mcmc_resp_t *r) {
break;
case 9:
if (memcmp(buf, "NOT_FOUND", 9) == 0) {
+ r->type = MCMC_RESP_GENERIC;
code = MCMC_CODE_NOT_FOUND;
}
break;
case 10:
if (memcmp(buf, "NOT_STORED", 10) == 0) {
+ r->type = MCMC_RESP_GENERIC;
code = MCMC_CODE_NOT_STORED;
}
break;
default:
// Unknown code, assume error.
+ if (memcmp(buf, "SERVER_ERROR", 12) == 0) {
+ r->type = MCMC_RESP_ERRMSG;
+ code = -MCMC_CODE_SERVER_ERROR;
+ } else if (memcmp(buf, "CLIENT_ERROR", 12) == 0) {
+ r->type = MCMC_RESP_ERRMSG;
+ code = -MCMC_CODE_CLIENT_ERROR;
+ }
break;
}
diff --git a/vendor/mcmc/mcmc.h b/vendor/mcmc/mcmc.h
index d6c426e..132ed1a 100644
--- a/vendor/mcmc/mcmc.h
+++ b/vendor/mcmc/mcmc.h
@@ -27,6 +27,9 @@
#define MCMC_ERR_SHORT 18
#define MCMC_ERR_PARSE 19
#define MCMC_ERR_VALUE 20
+#define MCMC_CODE_ERROR 21
+#define MCMC_CODE_CLIENT_ERROR 22
+#define MCMC_CODE_SERVER_ERROR 23
// response types
#define MCMC_RESP_GET 100
@@ -36,6 +39,8 @@
#define MCMC_RESP_END 105
#define MCMC_RESP_VERSION 106
#define MCMC_RESP_NUMERIC 107 // for weird incr/decr syntax.
+#define MCMC_RESP_ERRMSG 108 // ERROR, CLIENT_ERROR, SERVER_ERRROR
+#define MCMC_RESP_FAIL 109 // Complete failure to parse, garbage, etc
#define MCMC_OPTION_BLANK 0
#define MCMC_OPTION_NONBLOCK 1
@@ -69,8 +74,10 @@ typedef struct {
};
// STAT response
struct {
+ char *sname;
+ size_t snamelen;
char *stat;
- size_t slen;
+ size_t statlen;
};
};
} mcmc_resp_t;