static void _process_get(struct response *rsp, struct request *req) { struct bstring *key; struct response *r = rsp; uint32_t i; INCR(process_metrics, get); /* use chained responses, move to the next response if key is found. */ for (i = 0; i < array_nelem(req->keys); ++i) { INCR(process_metrics, get_key); key = array_get(req->keys, i); if (_get_key(r, key)) { req->nfound++; r->cas = false; r = STAILQ_NEXT(r, next); if (r == NULL) { INCR(process_metrics, get_ex); log_warn("get response incomplete due to lack of rsp objects"); return; } INCR(process_metrics, get_key_hit); } else { INCR(process_metrics, get_key_miss); } } r->type = RSP_END; log_verb("get req %p processed, %d out of %d keys found", req, req->nfound, i); }
static inline void _klog_write_get(struct request *req, struct response *rsp, char *buf, int len) { struct response *nr = rsp; int suffix_len; uint32_t i; struct bstring *key; for (i = 0; i < array_nelem(req->keys); ++i) { key = array_get(req->keys, i); if (nr->type != RSP_END && bstring_compare(key, &nr->key) == 0) { /* key was found, rsp at nr */ suffix_len = cc_scnprintf(buf + len, KLOG_MAX_LEN - len, KLOG_GET_FMT, req_strings[req->type].len, req_strings[req->type].data, key->len, key->data, rsp->type, _get_val_rsp_len(nr, key)); nr = STAILQ_NEXT(nr, next); } else { /* key not found */ suffix_len = cc_scnprintf(buf + len, KLOG_MAX_LEN - len, KLOG_GET_FMT, req_strings[req->type].len, req_strings[req->type].data, key->len, key->data, RSP_UNKNOWN, 0); } ASSERT(len + suffix_len <= KLOG_MAX_LEN); if (log_write(klogger, buf, len + suffix_len)) { INCR(klog_metrics, klog_logged); } else { INCR(klog_metrics, klog_discard); } } ASSERT(nr ->type == RSP_END); }
int compose_req(struct buf **buf, struct request *req) { request_type_t type = req->type; struct bstring *str = &req_strings[type]; struct bstring *key = req->keys->data; int noreply_len = req->noreply * NOREPLY_LEN; int cas_len = (req->type == REQ_CAS) ? CC_UINT64_MAXLEN : 0; uint32_t i; int sz, n = 0; switch (type) { case REQ_FLUSH: case REQ_QUIT: if (_check_buf_size(buf, str->len) != COMPOSE_OK) { goto error; } n += _write_bstring(buf, str); break; case REQ_GET: case REQ_GETS: for (i = 0, sz = 0; i < array_nelem(req->keys); i++) { key = array_get(req->keys, i); sz += 1 + key->len; } if (_check_buf_size(buf, str->len + sz + CRLF_LEN) != COMPOSE_OK) { goto error; } n += _write_bstring(buf, str); for (i = 0; i < array_nelem(req->keys); i++) { n += _delim(buf); n += _write_bstring(buf, (struct bstring *)array_get(req->keys, i)); } n += _crlf(buf); break; case REQ_DELETE: if (_check_buf_size(buf, str->len + key->len + noreply_len + CRLF_LEN) != COMPOSE_OK) { goto error; } n += _write_bstring(buf, str); n += _write_bstring(buf, key); if (req->noreply) { n += _noreply(buf); } n += _crlf(buf); break; case REQ_SET: case REQ_ADD: case REQ_REPLACE: case REQ_APPEND: case REQ_PREPEND: case REQ_CAS: /* here we may overestimate the size of message header because we * estimate the int size based on max value */ if (_check_buf_size(buf, str->len + key->len + CC_UINT32_MAXLEN * 3 + cas_len + req->vstr.len + noreply_len + CRLF_LEN * 2) != COMPOSE_OK) { goto error; } n += _write_bstring(buf, str); n += _write_bstring(buf, key); n += _delim(buf); n += _write_uint64(buf, req->flag); n += _delim(buf); n += _write_uint64(buf, req->expiry); n += _delim(buf); n += _write_uint64(buf, req->vstr.len); if (type == REQ_CAS) { n += _delim(buf); n += _write_uint64(buf, req->vcas); } if (req->noreply) { n += _noreply(buf); } n += _crlf(buf); n += _write_bstring(buf, &req->vstr); n += _crlf(buf); break; case REQ_INCR: case REQ_DECR: if (_check_buf_size(buf, str->len + key->len + CC_UINT64_MAXLEN + noreply_len + CRLF_LEN) != COMPOSE_OK) { goto error; } n += _write_bstring(buf, str); n += _write_bstring(buf, key); n += _delim(buf); n += _write_uint64(buf, req->delta); if (req->noreply) { n += _noreply(buf); } n += _crlf(buf); break; default: NOT_REACHED(); break; } INCR(compose_req_metrics, request_compose); return n; error: INCR(compose_req_metrics, request_compose_ex); return COMPOSE_ENOMEM; }
int main(void) { array a; size_t i, nelem = 10000; void *dummy; /* First a growable array */ if ((a = array_new(nelem / 10, 1)) == NULL) { perror("array_new"); return 1; } for (i = 0; i < nelem; i++) { dummy = (void*)(i+1); if (!array_add(a, dummy)) { perror("array_add"); return 1; } } if (array_nelem(a) != nelem) { fprintf(stderr, "Mismatch between number of actual and expected items\n"); return 1; } for (i = 0; i < nelem; i++) { if (array_get(a, i) == NULL) { fprintf(stderr, "Could not get array item %lu\n", (unsigned long)i); return 1; } } array_free(a, NULL); /* Now for a non-growable array */ if ((a = array_new(nelem / 10, 0)) == NULL) { perror("array_new"); return 1; } for (i = 0; i < nelem / 10; i++) { dummy = (void*)(i+1); if (!array_add(a, dummy)) { perror("array_add"); return 1; } } /* Now we've filled all slots, the next call should fail */ if (array_add(a, dummy) != 0) { fprintf(stderr, "Able to add to array which is full!\n"); return 1; } if (array_nelem(a) != nelem / 10) { fprintf(stderr, "Mismatch between number of actual and expected items\n"); return 1; } for (i = 0; i < nelem / 10; i++) { if (array_get(a, i) == NULL) { fprintf(stderr, "Could not get array item %lu\n", (unsigned long)i); return 1; } } array_free(a, NULL); return 0; }