Warning: Potential sizeof() on a pointer instead of the pointed-to type or array. This returns the size of the pointer (typically 4 or 8 bytes), not the data size.
memcpy(&hdr, ITEM_data(it), sizeof(hdr));
1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */2// Functions related to local command execution.34#include "proxy.h"5#include "storage.h"67#define PROXY_STORAGE_GET 08#define PROXY_STORAGE_MG 19#define _DO_CAS true10#define _NO_CAS false11#define _DO_TOUCH true12#define _NO_TOUCH false1314// FIXME: func or macro from storage for crc check15#ifdef EXTSTORE16static void _storage_get_item_cb(void *e, obj_io *eio, int ret) {17 io_pending_proxy_t *io = (io_pending_proxy_t *)eio->data;18 assert(io->active == true);19 mc_resp *resp = io->tresp;20 item *read_it = (item *)eio->buf;21 bool miss = false;2223 if (ret < 1) {24 miss = true;25 } else {26 uint32_t crc2;27 uint32_t crc = (uint32_t) read_it->exptime;28 crc2 = crc32c(0, (char *)read_it+STORE_OFFSET, eio->len-STORE_OFFSET);2930 if (crc != crc2) {31 miss = true;32 io->badcrc = true;33 }34 }3536 if (miss && !resp->skip) {37 resp->iovcnt = 1;38 if (io->gettype == PROXY_STORAGE_GET) {39 resp->iov[0].iov_len = 5;40 resp->iov[0].iov_base = "END\r\n";41 resp->tosend = 5;42 } else if (io->gettype == PROXY_STORAGE_MG) {43 resp->iov[0].iov_len = 4;44 resp->iov[0].iov_base = "EN\r\n";45 resp->tosend = 4;46 } else {47 assert(1 == 0);48 }49 }5051 if (!miss) {52 resp->iov[io->iovec_data].iov_base = ITEM_data(read_it);53 }54 io->miss = miss;55 io->active = false;5657 // in proxy mode we tend to return IO's as they happen so we can keep58 // latency down more.59 return_io_pending((io_pending_t *)io);60}6162// TODO (v2): if the item is smaller than resp->wbuf[] shouldn't we just read63// directly into there? item only necessary for recache.64static int _proxy_storage_get(LIBEVENT_THREAD *t, item *it, mc_resp *resp,65 int type) {66#ifdef NEED_ALIGN67 item_hdr hdr;68 memcpy(&hdr, ITEM_data(it), sizeof(hdr));69#else70 item_hdr *hdr = (item_hdr *)ITEM_data(it);71#endif72 size_t ntotal = ITEM_ntotal(it);7374 io_pending_proxy_t *io = do_cache_alloc(t->io_cache);75 // this is a re-cast structure, so assert that we never outsize it.76 assert(sizeof(io_pending_t) >= sizeof(io_pending_proxy_t));77 memset(io, 0, sizeof(io_pending_proxy_t));78 io->active = true;79 // io_pending owns the reference for this object now.80 io->hdr_it = it;81 io->tresp = resp; // our mc_resp is a temporary object.82 io->io_queue_type = IO_QUEUE_PROXY;83 io->io_sub_type = IO_PENDING_TYPE_EXTSTORE; // proxy specific sub-type.84 io->gettype = type;85 io->thread = t;86 io->return_cb = proxy_return_rctx_cb;87 io->finalize_cb = proxy_finalize_rctx_cb;88 io->payload = offsetof(io_pending_proxy_t, eio);89 obj_io *eio = &io->eio;9091 eio->buf = malloc(ntotal);92 if (eio->buf == NULL) {93 do_cache_free(t->io_cache, io);94 return -1;95 }9697 io->iovec_data = resp->iovcnt;98 resp_add_iov(resp, "", it->nbytes);99100 // We can't bail out anymore, so mc_resp owns the IO from here.101 resp->io_pending = (io_pending_t *)io;102103 // reference ourselves for the callback.104 eio->data = (void *)io;105106 // Now, fill in io->io based on what was in our header.107#ifdef NEED_ALIGN108 eio->page_version = hdr.page_version;109 eio->page_id = hdr.page_id;110 eio->offset = hdr.offset;111#else112 eio->page_version = hdr->page_version;113 eio->page_id = hdr->page_id;114 eio->offset = hdr->offset;115#endif116 eio->len = ntotal;117 eio->mode = OBJ_IO_READ;118 eio->cb = _storage_get_item_cb;119120 pthread_mutex_lock(&t->stats.mutex);121 t->stats.get_extstore++;122 pthread_mutex_unlock(&t->stats.mutex);123124 return 0;125}126127static int proxy_storage_mg(LIBEVENT_THREAD *t, item *it, mc_resp *resp) {128 return _proxy_storage_get(t, it, resp, PROXY_STORAGE_MG);129}130131static int proxy_storage_get(LIBEVENT_THREAD *t, item *it, mc_resp *resp) {132 return _proxy_storage_get(t, it, resp, PROXY_STORAGE_GET);133}134135static void proxy_get_cmd(LIBEVENT_THREAD *t, mcp_parser_t *pr, mc_resp *resp, bool return_cas, bool should_touch) {136 rel_time_t exptime = 0;137 if (should_touch) {138 if (!mc_parse_exptime(resp, pr, 1, &exptime)) {139 // function fills resp with error.140 return;141 }142 }143144 if (process_get_cmd(t, MCP_PARSER_KEY(pr), pr->klen, resp, proxy_storage_get, exptime, return_cas, should_touch) == 0) {145 resp_add_iov(resp, "END\r\n", 5);146 }147}148149#endif // EXTSTORE150151/*** Lua and internal handler ***/152153static inline int _mcplib_internal_run(LIBEVENT_THREAD *t, mcp_request_t *rq, mcp_resp_t *r, mc_resp *resp) {154 mcp_parser_t *pr = &rq->pr;155156 resp->noreply = pr->noreply;157 // TODO: meta no-op isn't handled here. haven't decided how yet.158 switch (pr->command) {159 case CMD_MG:160 process_mget_cmd(t, pr, resp, proxy_storage_mg);161 break;162 case CMD_MS:163 process_mset_cmd(t, pr, resp);164 break;165 case CMD_MD:166 process_mdelete_cmd(t, pr, resp);167 break;168 case CMD_MA:169 process_marithmetic_cmd(t, pr, resp);170 break;171 case CMD_GET:172 proxy_get_cmd(t, pr, resp, _NO_CAS, _NO_TOUCH);173 break;174 case CMD_GETS:175 proxy_get_cmd(t, pr, resp, _DO_CAS, _NO_TOUCH);176 break;177 case CMD_GAT:178 proxy_get_cmd(t, pr, resp, _NO_CAS, _DO_TOUCH);179 break;180 case CMD_GATS:181 proxy_get_cmd(t, pr, resp, _DO_CAS, _DO_TOUCH);182 break;183 case CMD_SET:184 process_update_cmd(t, pr, resp, NREAD_SET, _NO_CAS);185 break;186 case CMD_ADD:187 process_update_cmd(t, pr, resp, NREAD_ADD, _NO_CAS);188 break;189 case CMD_APPEND:190 process_update_cmd(t, pr, resp, NREAD_APPEND, _NO_CAS);191 break;192 case CMD_PREPEND:193 process_update_cmd(t, pr, resp, NREAD_PREPEND, _NO_CAS);194 break;195 case CMD_CAS:196 process_update_cmd(t, pr, resp, NREAD_CAS, _DO_CAS);197 break;198 case CMD_REPLACE:199 process_update_cmd(t, pr, resp, NREAD_REPLACE, _DO_CAS);200 break;201 case CMD_INCR:202 process_arithmetic_cmd(t, pr, resp, true);203 break;204 case CMD_DECR:205 process_arithmetic_cmd(t, pr, resp, false);206 break;207 case CMD_DELETE:208 process_delete_cmd(t, pr, resp);209 break;210 case CMD_TOUCH:211 process_touch_cmd(t, pr, resp);212 break;213 default:214 resp_free(t, resp);215 return -1;216 }217218 // TODO: I'd like to shortcut the parsing here, but if we want the resp219 // object to have full support (ie: resp:line()/etc) it might be necessary220 // to still do a full parsing. It might be possible to221 // wrap the main commands with something that decorates r->resp directly222 // instead of going through a parser to save some CPU.223 // Either way this is a lot less code.224 mcmc_parse_buf(resp->iov[0].iov_base, resp->iov[0].iov_len, &r->resp);225226 r->cresp = resp;227 r->thread = t;228 r->cmd = rq->pr.command;229 // Always return OK from here as this is signalling an internal error.230 r->status = MCMC_OK;231232 return 0;233}234235int mcplib_internal(lua_State *L) {236 luaL_checkudata(L, 1, "mcp.request");237 mcp_resp_t *r = lua_newuserdatauv(L, sizeof(mcp_resp_t), 0);238 memset(r, 0, sizeof(mcp_resp_t));239 luaL_getmetatable(L, "mcp.response");240 lua_setmetatable(L, -2);241242 lua_pushinteger(L, MCP_YIELD_INTERNAL);243 return lua_yield(L, 2);244}245246// V2 API internal handling.247void *mcp_rcontext_internal(mcp_rcontext_t *rctx, mcp_request_t *rq, mcp_resp_t *r) {248 LIBEVENT_THREAD *t = rctx->fgen->thread;249 mc_resp *resp = resp_start_unlinked(rctx->c);250 if (resp == NULL) {251 return NULL;252 }253254 // TODO: release resp here instead on error?255 if (_mcplib_internal_run(t, rq, r, resp) != 0) {256 return NULL;257 }258259 return resp;260}261262// we're pretending to be p_c_ascii(), but reusing our already tokenized code.263// the text parser should eventually move to the new tokenizer and we can264// merge all of this code together.265int mcplib_internal_run(mcp_rcontext_t *rctx) {266 lua_State *L = rctx->Lc;267 mcp_request_t *rq = luaL_checkudata(L, 1, "mcp.request");268 mcp_resp_t *r = luaL_checkudata(L, 2, "mcp.response");269 mc_resp *resp = resp_start_unlinked(rctx->c);270 LIBEVENT_THREAD *t = rctx->c->thread;271 if (resp == NULL) {272 return -1;273 }274275 t->cur_sfd = rctx->conn_fd;276 _mcplib_internal_run(t, rq, r, resp);277278 // resp object is associated with the279 // response object, which is about a280 // kilobyte.281 t->proxy_vm_extra_kb++;282283 if (resp->io_pending) {284 // TODO (v2): here we move the IO from the temporary resp to the top285 // resp, but this feels kludgy so I'm leaving an explicit note to find286 // a better way to do this.287 rctx->resp->io_pending = resp->io_pending;288 resp->io_pending = NULL;289290 // Add io object to extstore submission queue.291 io_queue_t *q = thread_io_queue_get(rctx->fgen->thread, IO_QUEUE_EXTSTORE);292 io_pending_proxy_t *io = (io_pending_proxy_t *)rctx->resp->io_pending;293294 STAILQ_INSERT_TAIL(&q->stack, (io_pending_t *)io, iop_next);295296 io->rctx = rctx;297 io->c = rctx->c;298 // mark the buffer into the mcp_resp for freeing later.299 r->buf = io->eio.buf;300 return 1;301 }302303 return 0;304}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.
Generated by searchcode.com · powered by code_get_file + code_get_findings