proxy_internal.c C 305 lines View on github.com → Search inside
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}

Code quality findings 1

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.
warning correctness sizeof-pointer
memcpy(&hdr, ITEM_data(it), sizeof(hdr));

Get this view in your editor

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