Navigation Menu

Skip to content

Commit

Permalink
Add support for setting vbucket id in the operations
Browse files Browse the repository at this point in the history
  • Loading branch information
trondn authored and ingenthr committed Jul 19, 2010
1 parent d3dd0bb commit 7be9d80
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 25 deletions.
5 changes: 3 additions & 2 deletions Makefile.am
Expand Up @@ -7,6 +7,7 @@ memcachetest_SOURCES = \
libmemc.c libmemc.h \
main.c \
metrics.c metrics.h \
timer.c
memcachetest_LDADD = $(LIBMEMCACHED)
timer.c \
vbucket.c vbucket.h
memcachetest_LDADD = $(LIBMEMCACHED) $(LIBVBUCKET)

54 changes: 33 additions & 21 deletions libmemc.c
Expand Up @@ -25,6 +25,7 @@
#include "config.h"

#include "libmemc.h"
#include "vbucket.h"

#ifdef HAVE_MEMCACHED_PROTOCOL_BINARY_H
#include <memcached/protocol_binary.h>
Expand Down Expand Up @@ -426,12 +427,16 @@ static int binary_get(struct Server* server, struct Item* item)
uint16_t keylen = item->keylen;
uint32_t bodylen = keylen;

protocol_binary_request_get request = { .bytes = {0} };
request.message.header.request.magic = PROTOCOL_BINARY_REQ;
request.message.header.request.opcode = PROTOCOL_BINARY_CMD_GET;
request.message.header.request.keylen = htons(keylen);
request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
request.message.header.request.bodylen = htonl(bodylen);
protocol_binary_request_get request = {
.message.header.request = {
.magic = PROTOCOL_BINARY_REQ,
.opcode = PROTOCOL_BINARY_CMD_GET,
.keylen = htons(keylen),
.datatype = PROTOCOL_BINARY_RAW_BYTES,
.vbucket = get_vbucket(item->key, keylen),
.bodylen = htonl(bodylen)
}
};

struct iovec iovec[2];
iovec[0].iov_base = (void*)&request;
Expand Down Expand Up @@ -521,30 +526,37 @@ static int binary_store(struct Server* server,
(void)item;
return -1;
#else
protocol_binary_request_set request = { .bytes = {0} };
request.message.header.request.magic = PROTOCOL_BINARY_REQ;
uint16_t keylen = item->keylen;
uint8_t opcode;

switch (cmd) {
case add :
request.message.header.request.opcode = PROTOCOL_BINARY_CMD_ADD; break;
opcode = PROTOCOL_BINARY_CMD_ADD; break;
case set :
request.message.header.request.opcode = PROTOCOL_BINARY_CMD_SET; break;
opcode = PROTOCOL_BINARY_CMD_SET; break;
case replace :
request.message.header.request.opcode = PROTOCOL_BINARY_CMD_REPLACE; break;
opcode = PROTOCOL_BINARY_CMD_REPLACE; break;
default:
abort();
}

uint16_t keylen = item->keylen;
request.message.header.request.keylen = htons(keylen);
request.message.header.request.extlen = 8;
request.message.header.request.datatype = 0;
request.message.header.request.reserved = 0;
request.message.header.request.bodylen = htonl(keylen + item->size + 8);
request.message.header.request.opaque = 0;
request.message.header.request.cas = swap64(item->cas_id);
request.message.body.flags = 0;
request.message.body.expiration = htonl(item->exptime);
protocol_binary_request_set request = {
.message.header.request = {
.magic = PROTOCOL_BINARY_REQ,
.opcode = opcode,
.keylen = htons(keylen),
.extlen = 8,
.datatype = 0,
.vbucket = get_vbucket(item->key, keylen),
.bodylen = htonl(keylen + item->size + 8),
.opaque = 0,
.cas = swap64(item->cas_id)
},
.message.body = {
.flags = 0,
.expiration = htonl(item->exptime)
}
};

struct iovec iovec[3];
iovec[0].iov_base = (void*)&request;
Expand Down
15 changes: 13 additions & 2 deletions main.c
Expand Up @@ -48,6 +48,7 @@
#include "libmemc.h"
#include "metrics.h"
#include "boxmuller.h"
#include "vbucket.h"

#ifndef MAXINT
/* I couldn't find MAXINT on my MacOSX box.. I should update this... */
Expand Down Expand Up @@ -952,7 +953,7 @@ int main(int argc, char **argv) {
struct timeval starttime = {.tv_sec = 0};
gettimeofday(&starttime, NULL);

while ((cmd = getopt(argc, argv, "QW:M:pL:P:Fm:t:h:i:s:c:VlSvy:xk:")) != EOF) {
while ((cmd = getopt(argc, argv, "QW:MpL:P:Fm:t:h:i:s:c:VlSvy:xk:C:")) != EOF) {
switch (cmd) {
case 'p':
progress = 1;
Expand Down Expand Up @@ -1023,10 +1024,19 @@ int main(int argc, char **argv) {
set_bench = 1;
populate = 0;
break;
case 'C':
#ifndef HAVE_LIBVBUCKET
fprintf(stderr, "You need to rebuild memcachetest with libvbucket\n");
return 1;
#else
if (!initialize_vbuckets(optarg)) {
return -1;
}
#endif
default:
fprintf(stderr, "Usage: test [-h host[:port]] [-t #threads]");
fprintf(stderr, " [-T] [-i #items] [-c #iterations] [-v] ");
fprintf(stderr, "[-V] [-f dir] [-s seed] [-W size] [-x] [-y stddev] [-k keyfile]\n");
fprintf(stderr, "[-V] [-f dir] [-s seed] [-W size] [-x] [-y stddev] [-k keyfile] [-C vbucketconfig]\n");
fprintf(stderr, "\t-h The hostname:port where the memcached server is running\n");
fprintf(stderr, "\t-t The number of threads to use\n");
fprintf(stderr, "\t-m The max message size to operate on\n");
Expand All @@ -1046,6 +1056,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "\t-k The file with keys to be retrieved\n");
fprintf(stderr, "\t-x randomly request from a set in a supplied file\n");
fprintf(stderr, "\t\t(implies -S, requires -k)\n");
fprintf(stderr, "\t-C Read vbucket data\n");
return 1;
}
}
Expand Down
112 changes: 112 additions & 0 deletions vbucket.c
@@ -0,0 +1,112 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* See LICENSE.txt included in this distribution for the specific
* language governing permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/

/*
* Copyright 2010 Trond Norbye
*/
#include "config.h"

#include <unistd.h>
#include <sys/fcntl.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "vbucket.h"

#ifdef HAVE_LIBVBUCKET

VBUCKET_CONFIG_HANDLE vbucket_handle;

bool initialize_vbuckets(const char *location)
{
if (access(location, F_OK) == 0) {
vbucket_handle = vbucket_config_parse_file(location);
if (vbucket_handle == NULL) {
fprintf(stderr, "Failed to parse vbucket config: %s\n",
vbucket_get_error());
}
return vbucket_handle != NULL;
}

const char *p = location;
while (isalpha(*p) || isdigit(*p) || *p == '.' || *p == ':') {
++p;
}

if (*p) {
fprintf(stderr, "%s is not a file, and doesn't look like a URL to me\n",
location);
return false;
}

char cmd[2048];
snprintf(cmd, sizeof(cmd),
"wget -O - http://%s/pools/default/buckets/default", location);

fprintf(stdout, "Downloading vbucket config from %s\n",
location);
fflush(stdout);

FILE *in = popen(cmd, "r");
char *config = malloc(8196);
*config = '\0';

while (fgets(cmd, sizeof(cmd), in) != NULL) {
strcat(config, cmd);
}

pclose(in);

if (strlen(config) == 0) {
return false;
}

vbucket_handle = vbucket_config_parse_string(config);
if (vbucket_handle == NULL) {
fprintf(stderr, "Failed to parse vbucket config: %s\n",
vbucket_get_error());
fprintf(stderr, "Config: [%s]", config);
}
return vbucket_handle != NULL;
}

uint16_t get_vbucket(const char *key, size_t nkey) {
if (vbucket_handle) {
return vbucket_get_vbucket_by_key(vbucket_handle, key, nkey);
}
return 0;
}

#else
bool initialize_vbuckets(const char *location)
{
(void)location;
return false;
}

uint16_t get_vbucket(const char *key, size_t nkey) {
(void)key;
(void)nkey;
return 0;
}

#endif
13 changes: 13 additions & 0 deletions vbucket.h
@@ -0,0 +1,13 @@
#ifndef VBUCKET_H
#define VBUCKET_H 1

#include <stdbool.h>

#ifdef HAVE_LIBVBUCKET
#include "libvbucket/vbucket.h"
#endif

extern bool initialize_vbuckets(const char *location);
extern uint16_t get_vbucket(const char *key, size_t nkey);

#endif

0 comments on commit 7be9d80

Please sign in to comment.