static void asc_process_verbosity(struct conn *c, struct token *token, int ntoken) { uint32_t level; asc_set_noreply_maybe(c, token, ntoken); if (ntoken != 3 && ntoken != 4) { log_hexdump(LOG_NOTICE, c->req, c->req_len, "client error on c %d for " "req of type %d with %d invalid tokens", c->sd, c->req_type, ntoken); asc_write_client_error(c); return; } if (!mc_strtoul(token[TOKEN_SUBCOMMAND].val, &level)) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d with " "invalid level '%.*s'", c->sd, c->req_type, token[TOKEN_SUBCOMMAND].len, token[TOKEN_SUBCOMMAND].val); asc_write_client_error(c); return; } log_level_set(level); asc_write_ok(c); }
static void asc_process_stats(struct conn *c, struct token *token, int ntoken) { struct token *t = &token[TOKEN_SUBCOMMAND]; if (!stats_enabled()) { log_warn("server error on c %d for req of type %d because stats is " "disabled", c->sd, c->req_type); asc_write_server_error(c); return; } if (!asc_ntoken_valid(c, ntoken)) { log_hexdump(LOG_NOTICE, c->req, c->req_len, "client error on c %d for " "req of type %d with %d invalid tokens", c->sd, c->req_type, ntoken); asc_write_client_error(c); return; } if (ntoken == 2) { stats_default(c); } else if (strncmp(t->val, "reset", t->len) == 0) { log_warn("server error on c %d for req of type %d because stats reset " "is not supported", c->sd, c->req_type); asc_write_server_error(c); return; } else if (strncmp(t->val, "settings", t->len) == 0) { stats_settings(c); } else if (strncmp(t->val, "cachedump", t->len) == 0) { char *buf; unsigned int bytes, id, limit = 0; if (ntoken < 5) { log_hexdump(LOG_NOTICE, c->req, c->req_len, "client error on c %d " "for req of type %d with %d invalid tokens", c->sd, c->req_type, ntoken); asc_write_client_error(c); return; } if (!mc_strtoul(token[TOKEN_CACHEDUMP_ID].val, &id) || !mc_strtoul(token[TOKEN_CACHEDUMP_LIMIT].val, &limit)) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d " "because either id '%.*s' or limit '%.*s' is invalid", c->sd, c->req_type, token[TOKEN_CACHEDUMP_ID].len, token[TOKEN_CACHEDUMP_ID].val, token[TOKEN_CACHEDUMP_LIMIT].len, token[TOKEN_CACHEDUMP_LIMIT].val); asc_write_client_error(c); return; } if (id < SLABCLASS_MIN_ID || id > SLABCLASS_MAX_ID) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d " "because %d is an illegal slab id", c->sd, c->req_type, id); asc_write_client_error(c); return; } buf = item_cache_dump(id, limit, &bytes); core_write_and_free(c, buf, bytes); return; } else { /* * Getting here means that the sub command is either engine specific * or is invalid. query the engine and see */ if (strncmp(t->val, "slabs", t->len) == 0) { stats_slabs(c); } else if (strncmp(t->val, "sizes", t->len) == 0) { stats_sizes(c); } else { log_debug(LOG_NOTICE, "client error on c %d for req of type %d with " "invalid stats subcommand '%.*s", c->sd, c->req_type, t->len, t->val); asc_write_client_error(c); return; } if (c->stats.buffer == NULL) { log_warn("server error on c %d for req of type %d because of oom " "writing stats", c->sd, c->req_type); asc_write_server_error(c); } else { core_write_and_free(c, c->stats.buffer, c->stats.offset); c->stats.buffer = NULL; } return; } /* append terminator and start the transfer */ stats_append(c, NULL, 0, NULL, 0); if (c->stats.buffer == NULL) { log_warn("server error on c %d for req of type %d because of oom " "writing stats", c->sd, c->req_type); asc_write_server_error(c); } else { core_write_and_free(c, c->stats.buffer, c->stats.offset); c->stats.buffer = NULL; } }
static void asc_process_update(struct conn *c, struct token *token, int ntoken) { char *key; size_t nkey; uint32_t flags, vlen; int32_t exptime_int; time_t exptime; uint64_t req_cas_id = 0; struct item *it; bool handle_cas; req_type_t type; uint8_t id; asc_set_noreply_maybe(c, token, ntoken); if (!asc_ntoken_valid(c, ntoken)) { log_hexdump(LOG_NOTICE, c->req, c->req_len, "client error on c %d for " "req of type %d with %d invalid tokens", c->sd, c->req_type, ntoken); asc_write_client_error(c); return; } type = c->req_type; handle_cas = (type == REQ_CAS) ? true : false; key = token[TOKEN_KEY].val; nkey = token[TOKEN_KEY].len; if (nkey > KEY_MAX_LEN) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d and %d " "length key", c->sd, c->req_type, nkey); asc_write_client_error(c); return; } if (!mc_strtoul(token[TOKEN_FLAGS].val, &flags)) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d and " "invalid flags '%.*s'", c->sd, c->req_type, token[TOKEN_FLAGS].len, token[TOKEN_FLAGS].val); asc_write_client_error(c); return; } if (!mc_strtol(token[TOKEN_EXPIRY].val, &exptime_int)) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d and " "invalid expiry '%.*s'", c->sd, c->req_type, token[TOKEN_EXPIRY].len, token[TOKEN_EXPIRY].val); asc_write_client_error(c); return; } if (!mc_strtoul(token[TOKEN_VLEN].val, &vlen)) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d and " "invalid vlen '%.*s'", c->sd, c->req_type, token[TOKEN_VLEN].len, token[TOKEN_VLEN].val); asc_write_client_error(c); return; } id = item_slabid(nkey, vlen); if (id == SLABCLASS_INVALID_ID) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d and " "slab id out of range for key size %"PRIu8" and value size " "%"PRIu32, c->sd, c->req_type, nkey, vlen); asc_write_client_error(c); return; } exptime = (time_t)exptime_int; /* does cas value exist? */ if (handle_cas) { if (!mc_strtoull(token[TOKEN_CAS].val, &req_cas_id)) { log_debug(LOG_NOTICE, "client error on c %d for req of type %d and " "invalid cas '%.*s'", c->sd, c->req_type, token[TOKEN_CAS].len, token[TOKEN_CAS].val); asc_write_client_error(c); return; } } it = item_alloc(id, key, nkey, flags, time_reltime(exptime), vlen); if (it == NULL) { log_warn("server error on c %d for req of type %d because of oom in " "storing item", c->sd, c->req_type); asc_write_server_error(c); /* swallow the data line */ c->write_and_go = CONN_SWALLOW; c->sbytes = vlen + CRLF_LEN; /* * Avoid stale data persisting in cache because we failed alloc. * Unacceptable for SET. Anywhere else too? * * FIXME: either don't delete anything or should be unacceptable for * all but add. */ if (type == REQ_SET) { it = item_get(key, nkey); if (it != NULL) { item_delete(it); } } return; } item_set_cas(it, req_cas_id); c->item = it; c->ritem = item_data(it); c->rlbytes = it->nbyte + CRLF_LEN; conn_set_state(c, CONN_NREAD); }
static void asc_process_update(struct conn *c, struct token *token, int ntoken) { char *key; size_t nkey; unsigned int flags; int32_t exptime_int; time_t exptime; int vlen; uint64_t req_cas_id = 0; struct item *it; bool handle_cas; req_type_t type; asc_set_noreply_maybe(c, token, ntoken); if (!asc_ntoken_valid(c, ntoken)) { log_hexdump(LOG_INFO, c->req, c->req_len, "client error on c %d for " "req of type %d with %d invalid tokens", c->sd, c->req_type, ntoken); asc_write_client_error(c); return; } type = c->req_type; handle_cas = (type == REQ_CAS) ? true : false; key = token[TOKEN_KEY].val; nkey = token[TOKEN_KEY].len; if (nkey > KEY_MAX_LEN) { log_debug(LOG_INFO, "client error on c %d for req of type %d and %d " "length key", c->sd, c->req_type, nkey); asc_write_client_error(c); return; } if (!mc_strtoul(token[TOKEN_FLAGS].val, (uint32_t *)&flags)) { log_debug(LOG_INFO, "client error on c %d for req of type %d and " "invalid flags '%.*s'", c->sd, c->req_type, token[TOKEN_FLAGS].len, token[TOKEN_FLAGS].val); asc_write_client_error(c); return; } if (!mc_strtol(token[TOKEN_EXPIRY].val, &exptime_int)) { log_debug(LOG_INFO, "client error on c %d for req of type %d and " "invalid expiry '%.*s'", c->sd, c->req_type, token[TOKEN_EXPIRY].len, token[TOKEN_EXPIRY].val); asc_write_client_error(c); return; } if (!mc_strtol(token[TOKEN_VLEN].val, (int32_t *)&vlen)) { log_debug(LOG_INFO, "client error on c %d for req of type %d and " "invalid vlen '%.*s'", c->sd, c->req_type, token[TOKEN_VLEN].len, token[TOKEN_VLEN].val); asc_write_client_error(c); return; } exptime = (time_t)exptime_int; /* does cas value exist? */ if (handle_cas) { if (!mc_strtoull(token[TOKEN_CAS].val, &req_cas_id)) { log_debug(LOG_INFO, "client error on c %d for req of type %d and " "invalid cas '%.*s'", c->sd, c->req_type, token[TOKEN_CAS].len, token[TOKEN_CAS].val); asc_write_client_error(c); return; } } if (vlen < 0) { log_debug(LOG_INFO, "client error on c %d for req of type %d and " "invalid vlen %d", c->sd, c->req_type, vlen); asc_write_client_error(c); return; } vlen += CRLF_LEN; it = item_alloc(key, nkey, flags, time_reltime(exptime), vlen); if (it == NULL) { log_debug(LOG_DEBUG, "server error on c %d for req of type %d because " "of oom in storing item", c->sd, c->req_type); asc_write_server_error(c); /* swallow the data line */ c->write_and_go = CONN_SWALLOW; c->sbytes = vlen; /* * Avoid stale data persisting in cache because we failed alloc. * Unacceptable for SET. Anywhere else too? */ if (type == REQ_SET) { it = item_get(key, nkey); if (it != NULL) { item_unlink(it); item_remove(it); } } return; } item_set_cas(it, req_cas_id); c->item = it; c->ritem = item_data(it); c->rlbytes = it->nbyte; conn_set_state(c, CONN_NREAD); }