Esempio n. 1
0
END_TEST

START_TEST (test_safe_strtoull)
{
    uint64_t val;

    fail_unless(safe_strtoull("123", &val), "Failed parsing 123");
    fail_unless(val == 123, "Didn't parse 123 to 123");
    fail_unless(safe_strtoull("+123", &val), "Failed parsing +123");
    fail_unless(val == 123, "Didn't parse +123 to 123");
    fail_if(safe_strtoull("", &val), "Unexpectedly parsed an empty string.");
    fail_if(safe_strtoull("123BOGUS", &val), "Parsed 123BOGUS");

    fail_if(safe_strtoull("92837498237498237498029383", &val),
            "Parsed out of range value.");

    /* extremes: */
    fail_unless(safe_strtoull("18446744073709551615", &val),
                "Failed parsing 18446744073709551615"); /* 2**64 - 1 */
    fail_unless(val == 18446744073709551615ULL,
                "18446744073709551615 != 18446744073709551615ULL");
    fail_if(safe_strtoull("18446744073709551616", &val),
            "Parsed 18446744073709551616"); /* 2**64 */
    fail_if(safe_strtoull("-1", &val), "Parsed a negative number as unsigned.");
}
Esempio n. 2
0
/*
 * adds a delta value to a numeric item.
 *
 * c     connection requesting the operation
 * it    item to adjust
 * incr  true to increment value, false to decrement
 * delta amount to adjust value by
 * @param ritem The resulting item after adding the delta. Only valid if
 *              ENGINE_SUCCESS is returned. Caller is responsible for calling
 *              do_item_release() on this when finished with it.
 *
 * returns a response code to send back to the client.
 */
static ENGINE_ERROR_CODE do_add_delta(struct default_engine *engine,
                                      hash_item *it, const bool incr,
                                      const int64_t delta, item** ritem,
                                      uint64_t *result, const void *cookie) {
    const char *ptr;
    uint64_t value;
    char buf[80];
    int res;

    if (it->nbytes >= (sizeof(buf) - 1)) {
        return ENGINE_EINVAL;
    }

    ptr = item_get_data(it);
    memcpy(buf, ptr, it->nbytes);
    buf[it->nbytes] = '\0';

    if (!safe_strtoull(buf, &value)) {
        return ENGINE_EINVAL;
    }

    if (incr) {
        value += delta;
    } else {
        if ((uint64_t)delta > value) {
            value = 0;
        } else {
            value -= delta;
        }
    }

    *result = value;

    res = snprintf(buf, sizeof(buf), "%" PRIu64, value);
    if (res < 0 || res >= sizeof(buf)) {
        return ENGINE_EINVAL;
    }

    if (it->refcount == 1 && res <= (int)it->nbytes) {
        /* we can do inline replacement */
        memcpy(item_get_data(it), buf, res);
        memset(item_get_data(it) + res, ' ', it->nbytes - res);
        item_set_cas(NULL, NULL, it, get_cas_id());
        *ritem = it;
    } else {
        hash_item *new_it = do_item_alloc(engine, item_get_key(it),
                                          it->flags,
                                          it->exptime, res,
                                          cookie, it->datatype);
        if (new_it == NULL) {
            do_item_unlink(engine, it);
            return ENGINE_ENOMEM;
        }
        memcpy(item_get_data(new_it), buf, res);
        do_item_replace(engine, it, new_it);
        *ritem = new_it;
    }

    return ENGINE_SUCCESS;
}
Esempio n. 3
0
bool protocol_stats_merge_smallest(char *v1, int v1len,
                                   char *v2, int v2len,
                                   char *out, int outlen) {
    int dot = count_dot_pair(v1, v1len, v2, v2len);
    if (dot > 0) {
        float v1f = strtof(v1, NULL);
        float v2f = strtof(v2, NULL);
        sprintf(out, "%f", (v1f > v2f ? v1f : v2f));
        return true;
    } else {
        uint64_t v1i = 0;
        uint64_t v2i = 0;

        if (safe_strtoull(v1, &v1i) &&
            safe_strtoull(v2, &v2i)) {
            sprintf(out, "%"PRIu64"", (v1i > v2i ? v1i : v2i));
            return true;
        }
    }

    (void)outlen;
    return false;
}
Esempio n. 4
0
static enum test_return test_safe_strtoull(void) {
    uint64_t val;
    assert(safe_strtoull("123", &val));
    assert(val == 123);
    assert(safe_strtoull("+123", &val));
    assert(val == 123);
    assert(!safe_strtoull("", &val));  /* empty */
    assert(!safe_strtoull("123BOGUS", &val));  /* non-numeric */
    assert(!safe_strtoull("92837498237498237498029383", &val)); /* out of range */

    /* extremes: */
    assert(safe_strtoull("18446744073709551615", &val)); /* 2**64 - 1 */
    assert(val == 18446744073709551615ULL);
    assert(!safe_strtoull("18446744073709551616", &val)); /* 2**64 */
    assert(!safe_strtoull("-1", &val));  /* negative */
    return TEST_PASS;
}
Esempio n. 5
0
void cproxy_process_a2a_downstream(conn *c, char *line) {
    assert(c != NULL);
    assert(c->next == NULL);
    assert(c->extra != NULL);
    assert(c->cmd == -1);
    assert(c->item == NULL);
    assert(line != NULL);
    assert(line == c->rcurr);
    assert(IS_ASCII(c->protocol));
    assert(IS_PROXY(c->protocol));

    if (settings.verbose > 1)
        fprintf(stderr, "<%d cproxy_process_a2a_downstream %s\n",
                c->sfd, line);

    downstream *d = c->extra;

    assert(d != NULL);
    assert(d->ptd != NULL);
    assert(d->ptd->proxy != NULL);

    if (strncmp(line, "VALUE ", 6) == 0) {
        token_t      tokens[MAX_TOKENS];
        size_t       ntokens;
        unsigned int flags;
        int          clen = 0;
        int          vlen;
        uint64_t     cas = CPROXY_NOT_CAS;

        ntokens = scan_tokens(line, tokens, MAX_TOKENS, &clen);
        if (ntokens >= 5 && // Accounts for extra termimation token.
            ntokens <= 6 &&
            tokens[KEY_TOKEN].length <= KEY_MAX_LENGTH &&
            safe_strtoul(tokens[2].value, (uint32_t *) &flags) &&
            safe_strtoul(tokens[3].value, (uint32_t *) &vlen)) {
            char  *key  = tokens[KEY_TOKEN].value;
            size_t nkey = tokens[KEY_TOKEN].length;

            item *it = item_alloc(key, nkey, flags, 0, vlen + 2);
            if (it != NULL) {
                if (ntokens == 5 ||
                    safe_strtoull(tokens[4].value, &cas)) {
                    ITEM_set_cas(it, cas);

                    c->item = it;
                    c->ritem = ITEM_data(it);
                    c->rlbytes = it->nbytes;
                    c->cmd = -1;

                    conn_set_state(c, conn_nread);

                    return; // Success.
                } else {
                    if (settings.verbose > 1)
                        fprintf(stderr, "cproxy could not parse cas\n");
                }
            } else {
                if (settings.verbose > 1)
                    fprintf(stderr, "cproxy could not item_alloc size %u\n",
                            vlen + 2);
            }

            if (it != NULL)
                item_remove(it);
            it = NULL;

            c->sbytes = vlen + 2; // Number of bytes to swallow.

            conn_set_state(c, conn_swallow);

            // Note, eventually, we'll see an END later.
        } else {
            // We don't know how much to swallow, so close the downstream.
            // The conn_closing should release the downstream,
            // which should write a suffix/error to the upstream.
            //
            conn_set_state(c, conn_closing);
        }
    } else if (strncmp(line, "END", 3) == 0) {
        conn_set_state(c, conn_pause);
    } else if (strncmp(line, "OK", 2) == 0) {
        conn_set_state(c, conn_pause);

        // TODO: Handle flush_all's expiration parameter against
        // the front_cache.
        //
        // TODO: We flush the front_cache too often, inefficiently
        // on every downstream flush_all OK response, rather than
        // on just the last flush_all OK response.
        //
        conn *uc = d->upstream_conn;
        if (uc != NULL &&
            uc->cmd_curr == PROTOCOL_BINARY_CMD_FLUSH) {
            mcache_flush_all(&d->ptd->proxy->front_cache, 0);
        }
    } else if (strncmp(line, "STAT ", 5) == 0 ||
               strncmp(line, "ITEM ", 5) == 0 ||
               strncmp(line, "PREFIX ", 7) == 0) {
        assert(d->merger != NULL);

        conn *uc = d->upstream_conn;
        if (uc != NULL) {
            assert(uc->next == NULL);

            if (protocol_stats_merge_line(d->merger, line) == false) {
                // Forward the line as-is if we couldn't merge it.
                //
                int nline = strlen(line);

                item *it = item_alloc("s", 1, 0, 0, nline + 2);
                if (it != NULL) {
                    strncpy(ITEM_data(it), line, nline);
                    strncpy(ITEM_data(it) + nline, "\r\n", 2);

                    if (add_conn_item(uc, it)) {
                        add_iov(uc, ITEM_data(it), nline + 2);

                        it = NULL;
                    }

                    if (it != NULL)
                        item_remove(it);
                }
            }
        }

        conn_set_state(c, conn_new_cmd);
    } else {
        conn_set_state(c, conn_pause);

        // The upstream conn might be NULL when closed already
        // or while handling a noreply.
        //
        conn *uc = d->upstream_conn;
        if (uc != NULL) {
            assert(uc->next == NULL);

            out_string(uc, line);

            if (!update_event(uc, EV_WRITE | EV_PERSIST)) {
                if (settings.verbose > 1)
                    fprintf(stderr,
                            "Can't update upstream write event\n");

                d->ptd->stats.stats.err_oom++;
                cproxy_close_conn(uc);
            }

            cproxy_del_front_cache_key_ascii_response(d, line,
                                                      uc->cmd_start);
        }
    }
}
Esempio n. 6
0
static int parseFirstLineRequest(fallocator_t fallocator, requestParserImpl_t* pParser, char** tokens, int ntokens) {
	int returnValue = 0;

	if (ntokens >= 2 && (((strcmp(tokens[0], "get") == 0) && (pParser->pCommand->command
			= COMMAND_GET)) || ((strcmp(tokens[0], "bget") == 0)
			&& (pParser->pCommand->command = COMMAND_BGET)))) {

		if (ntokens > 2) {
			//copy the keys ...
			pParser->pCommand->multiGetKeys = fallocatorMalloc(fallocator, (ntokens-1) * sizeof(char*));
			IfTrue(pParser->pCommand->multiGetKeys, WARN, "Error allocating memory");
			pParser->pCommand->multiGetKeysCount = ntokens -1 ;
			for (int i = 1; i < ntokens; i++) {
				pParser->pCommand->multiGetKeys[i-1] = tokens[i];
				tokens[i] = 0;
			}
		}else {
			pParser->pCommand->key = tokens[1];
			pParser->pCommand->keySize = strlen(tokens[1]);
			tokens[1] = 0;
		}
	} else if ((ntokens == 5 || ntokens == 6) && ((strcmp(tokens[0], "add")
			== 0 && (pParser->pCommand->command = COMMAND_ADD)) || (strcmp(tokens[0],
			"set") == 0 && (pParser->pCommand->command = COMMAND_SET)) || (strcmp(
			tokens[0], "replace") == 0 && (pParser->pCommand->command = COMMAND_REPLACE))
			|| (strcmp(tokens[0], "prepend") == 0 && (pParser->pCommand->command
					= COMMAND_PREPEND)) || (strcmp(tokens[0], "append") == 0
			&& (pParser->pCommand->command = COMMAND_APPEND)))) {
		pParser->pCommand->key = tokens[1];
		pParser->pCommand->keySize = strlen(tokens[1]);
		tokens[1] = 0;
		IfTrue(safe_strtoul(tokens[2], &pParser->pCommand->flags), INFO, "Error parsing flags");
		IfTrue(safe_strtoul(tokens[3], &pParser->pCommand->expiryTime), INFO, "Error parsing expiry time ");
		IfTrue(safe_strtoul(tokens[4], &pParser->pCommand->dataLength), INFO, "Error parsing data length");

		if (tokens[5] != NULL) {
			if (strcmp(tokens[5], "noreply") == 0) {
				pParser->pCommand->noreply = 1;
			}
		}

	} else if ((ntokens == 6 || ntokens == 7)
			&& (strcmp(tokens[0], "cas") == 0)) {
		pParser->pCommand->command = COMMAND_CAS;

		pParser->pCommand->key = tokens[1];
		pParser->pCommand->keySize = strlen(tokens[1]);
		tokens[1] = 0;
		IfTrue(safe_strtoul(tokens[2], &pParser->pCommand->flags), INFO, "Error parsing flags");
		IfTrue(safe_strtoul(tokens[3], &pParser->pCommand->expiryTime), INFO, "Error parsing expiry time ");
		IfTrue(safe_strtoul(tokens[4], &pParser->pCommand->dataLength), INFO, "Error parsing data length");
		IfTrue(safe_strtoull(tokens[5], &pParser->pCommand->cas), INFO, "Error parsing cas id");

		if (tokens[6] != NULL) {
			if (strcmp(tokens[6], "noreply") == 0) {
				pParser->pCommand->noreply = 1;
			}
		}

	} else if ((ntokens == 3 || ntokens == 4) && (strcmp(tokens[0], "incr")
			== 0)) {
		pParser->pCommand->command = COMMAND_INCR;
		pParser->pCommand->key = tokens[1];
		pParser->pCommand->keySize = strlen(tokens[1]);
		tokens[1] = 0;

		IfTrue(safe_strtoull(tokens[2], &pParser->pCommand->delta), INFO, "Error parsing delta");
		if (tokens[3] != NULL) {
			if (strcmp(tokens[3], "noreply") == 0) {
				pParser->pCommand->noreply = 1;
			}
		}
	} else if (ntokens >= 2 && (strcmp(tokens[0], "gets") == 0)) {
		pParser->pCommand->command = COMMAND_GETS;
		pParser->pCommand->key = tokens[1];
		pParser->pCommand->keySize = strlen(tokens[1]);
		tokens[1] = 0;
		//TODO - only suport one key per get for now

	} else if ((ntokens == 4 || ntokens == 5) && (strcmp(tokens[0], "decr")
			== 0)) {
		pParser->pCommand->command = COMMAND_DECR;
		pParser->pCommand->key = tokens[1];
		pParser->pCommand->keySize = strlen(tokens[1]);
		tokens[1] = 0;

		IfTrue(safe_strtoull(tokens[2], &pParser->pCommand->delta), INFO, "Error parsing delta");
		if (tokens[3] != NULL) {
			if (strcmp(tokens[3], "noreply") == 0) {
				pParser->pCommand->noreply = 1;
			}
		}
	} else if (ntokens >= 2 && ntokens <= 4 && (strcmp(tokens[0], "delete")
			== 0)) {
		pParser->pCommand->command = COMMAND_DELETE;
		pParser->pCommand->key = tokens[1];
		pParser->pCommand->keySize = strlen(tokens[1]);
		tokens[1] = 0;
		if (tokens[2] != NULL) {
			if (strcmp(tokens[2], "noreply") == 0) {
				pParser->pCommand->noreply = 1;
			}
		}
	} else if (ntokens >= 2 && (strcmp(tokens[0], "stats") == 0)) {
		pParser->pCommand->command = COMMAND_STATS;
		//TODO - later
	} else if (ntokens >= 1 && ntokens <= 2 && (strcmp(tokens[0], "flush_all")
			== 0)) {
		pParser->pCommand->command = COMMAND_FLUSH_ALL;
		//TODO - later
	} else if (ntokens == 1 && (strcmp(tokens[0], "version") == 0)) {
		pParser->pCommand->command = COMMAND_VERSION;
		//TODO - later
	} else if (ntokens == 1 && (strcmp(tokens[0], "quit") == 0)) {
		pParser->pCommand->command = COMMAND_QUIT;
		//TODO - later
	} else if ((ntokens == 2 || ntokens == 3)
			&& (strcmp(tokens[0], "verbosity") == 0)) {
		pParser->pCommand->command = COMMAND_VERBOSITY;
		IfTrue(safe_strtoul(tokens[2], &pParser->pCommand->flags), INFO,
				"Error parsing verosity level");
	} else {
		//this is error
	}
	goto OnSuccess;
OnError:
	returnValue = -1;
OnSuccess:
	return returnValue;
}