Common subdirectories: memcached-1.2.1/.deps and memcached-1.2.1-rbuf/.deps diff -w -c memcached-1.2.1/Makefile memcached-1.2.1-rbuf/Makefile *** memcached-1.2.1/Makefile Sun May 6 08:46:29 2007 --- memcached-1.2.1-rbuf/Makefile Sun May 6 01:33:58 2007 *************** *** 38,50 **** build_triplet = i686-pc-linux-gnu host_triplet = i686-pc-linux-gnu target_triplet = i686-pc-linux-gnu ! ACLOCAL = ${SHELL} /home/nathan/build/memcached-1.2.1/missing --run aclocal-1.7 AMDEP_FALSE = # AMDEP_TRUE = ! AMTAR = ${SHELL} /home/nathan/build/memcached-1.2.1/missing --run tar ! AUTOCONF = ${SHELL} /home/nathan/build/memcached-1.2.1/missing --run autoconf ! AUTOHEADER = ${SHELL} /home/nathan/build/memcached-1.2.1/missing --run autoheader ! AUTOMAKE = ${SHELL} /home/nathan/build/memcached-1.2.1/missing --run automake-1.7 AWK = mawk CC = gcc CCDEPMODE = depmode=gcc3 --- 38,50 ---- build_triplet = i686-pc-linux-gnu host_triplet = i686-pc-linux-gnu target_triplet = i686-pc-linux-gnu ! ACLOCAL = ${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run aclocal-1.7 AMDEP_FALSE = # AMDEP_TRUE = ! AMTAR = ${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run tar ! AUTOCONF = ${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run autoconf ! AUTOHEADER = ${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run autoheader ! AUTOMAKE = ${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run automake-1.7 AWK = mawk CC = gcc CCDEPMODE = depmode=gcc3 *************** *** 67,73 **** LIBOBJS = LIBS = -levent LTLIBOBJS = ! MAKEINFO = ${SHELL} /home/nathan/build/memcached-1.2.1/missing --run makeinfo OBJEXT = o PACKAGE = memcached PACKAGE_BUGREPORT = brad@danga.com --- 67,73 ---- LIBOBJS = LIBS = -levent LTLIBOBJS = ! MAKEINFO = ${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run makeinfo OBJEXT = o PACKAGE = memcached PACKAGE_BUGREPORT = brad@danga.com *************** *** 102,108 **** host_vendor = pc includedir = ${prefix}/include infodir = ${prefix}/info ! install_sh = /home/nathan/build/memcached-1.2.1/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localstatedir = ${prefix}/var --- 102,108 ---- host_vendor = pc includedir = ${prefix}/include infodir = ${prefix}/info ! install_sh = /home/nathan/build/memcached-1.2.1-rbuf/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localstatedir = ${prefix}/var *************** *** 730,735 **** --- 730,738 ---- test: memcached-debug prove t + testr: memcached-debug + prove t/01-ring.t + dist-hook: rm -rf $(distdir)/doc/.svn/ rm -rf $(distdir)/scripts/.svn/ Only in memcached-1.2.1-rbuf/: Makefile~ diff -w -c memcached-1.2.1/config.log memcached-1.2.1-rbuf/config.log *** memcached-1.2.1/config.log Sun May 6 08:46:30 2007 --- memcached-1.2.1-rbuf/config.log Sun May 6 00:04:03 2007 *************** *** 467,480 **** ## Output variables. ## ## ----------------- ## ! ACLOCAL='${SHELL} /home/nathan/build/memcached-1.2.1/missing --run aclocal-1.7' AMDEPBACKSLASH='\' AMDEP_FALSE='#' AMDEP_TRUE='' ! AMTAR='${SHELL} /home/nathan/build/memcached-1.2.1/missing --run tar' ! AUTOCONF='${SHELL} /home/nathan/build/memcached-1.2.1/missing --run autoconf' ! AUTOHEADER='${SHELL} /home/nathan/build/memcached-1.2.1/missing --run autoheader' ! AUTOMAKE='${SHELL} /home/nathan/build/memcached-1.2.1/missing --run automake-1.7' AWK='mawk' CC='gcc' CCDEPMODE='depmode=gcc3' --- 467,480 ---- ## Output variables. ## ## ----------------- ## ! ACLOCAL='${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run aclocal-1.7' AMDEPBACKSLASH='\' AMDEP_FALSE='#' AMDEP_TRUE='' ! AMTAR='${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run tar' ! AUTOCONF='${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run autoconf' ! AUTOHEADER='${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run autoheader' ! AUTOMAKE='${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run automake-1.7' AWK='mawk' CC='gcc' CCDEPMODE='depmode=gcc3' *************** *** 497,503 **** LIBOBJS='' LIBS=' -levent' LTLIBOBJS='' ! MAKEINFO='${SHELL} /home/nathan/build/memcached-1.2.1/missing --run makeinfo' OBJEXT='o' PACKAGE='memcached' PACKAGE_BUGREPORT='brad@danga.com' --- 497,503 ---- LIBOBJS='' LIBS=' -levent' LTLIBOBJS='' ! MAKEINFO='${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run makeinfo' OBJEXT='o' PACKAGE='memcached' PACKAGE_BUGREPORT='brad@danga.com' *************** *** 532,538 **** host_vendor='pc' includedir='${prefix}/include' infodir='${prefix}/info' ! install_sh='/home/nathan/build/memcached-1.2.1/install-sh' libdir='${exec_prefix}/lib' libexecdir='${exec_prefix}/libexec' localstatedir='${prefix}/var' --- 532,538 ---- host_vendor='pc' includedir='${prefix}/include' infodir='${prefix}/info' ! install_sh='/home/nathan/build/memcached-1.2.1-rbuf/install-sh' libdir='${exec_prefix}/lib' libexecdir='${exec_prefix}/libexec' localstatedir='${prefix}/var' *************** *** 577,579 **** --- 577,615 ---- #define VERSION "1.2.1" configure: exit 0 + + ## ---------------------- ## + ## Running config.status. ## + ## ---------------------- ## + + This file was extended by memcached config.status 1.2.1, which was + generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = + CONFIG_HEADERS = + CONFIG_LINKS = + CONFIG_COMMANDS = + $ ./config.status Makefile depfiles + + on foxtrot + + config.status:738: creating Makefile + config.status:1100: executing depfiles commands + + ## ---------------------- ## + ## Running config.status. ## + ## ---------------------- ## + + This file was extended by memcached config.status 1.2.1, which was + generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = + CONFIG_HEADERS = + CONFIG_LINKS = + CONFIG_COMMANDS = + $ ./config.status config.h + + on foxtrot + + config.status:804: creating config.h + config.status:920: config.h is unchanged diff -w -c memcached-1.2.1/config.status memcached-1.2.1-rbuf/config.status *** memcached-1.2.1/config.status Sun May 6 08:46:29 2007 --- memcached-1.2.1-rbuf/config.status Sat May 5 23:53:45 2007 *************** *** 501,513 **** s,@CYGPATH_W@,echo,;t t s,@PACKAGE@,memcached,;t t s,@VERSION@,1.2.1,;t t ! s,@ACLOCAL@,${SHELL} /home/nathan/build/memcached-1.2.1/missing --run aclocal-1.7,;t t ! s,@AUTOCONF@,${SHELL} /home/nathan/build/memcached-1.2.1/missing --run autoconf,;t t ! s,@AUTOMAKE@,${SHELL} /home/nathan/build/memcached-1.2.1/missing --run automake-1.7,;t t ! s,@AUTOHEADER@,${SHELL} /home/nathan/build/memcached-1.2.1/missing --run autoheader,;t t ! s,@MAKEINFO@,${SHELL} /home/nathan/build/memcached-1.2.1/missing --run makeinfo,;t t ! s,@AMTAR@,${SHELL} /home/nathan/build/memcached-1.2.1/missing --run tar,;t t ! s,@install_sh@,/home/nathan/build/memcached-1.2.1/install-sh,;t t s,@STRIP@,,;t t s,@ac_ct_STRIP@,,;t t s,@INSTALL_STRIP_PROGRAM@,${SHELL} $(install_sh) -c -s,;t t --- 501,513 ---- s,@CYGPATH_W@,echo,;t t s,@PACKAGE@,memcached,;t t s,@VERSION@,1.2.1,;t t ! s,@ACLOCAL@,${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run aclocal-1.7,;t t ! s,@AUTOCONF@,${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run autoconf,;t t ! s,@AUTOMAKE@,${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run automake-1.7,;t t ! s,@AUTOHEADER@,${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run autoheader,;t t ! s,@MAKEINFO@,${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run makeinfo,;t t ! s,@AMTAR@,${SHELL} /home/nathan/build/memcached-1.2.1-rbuf/missing --run tar,;t t ! s,@install_sh@,/home/nathan/build/memcached-1.2.1-rbuf/install-sh,;t t s,@STRIP@,,;t t s,@ac_ct_STRIP@,,;t t s,@INSTALL_STRIP_PROGRAM@,${SHELL} $(install_sh) -c -s,;t t Common subdirectories: memcached-1.2.1/doc and memcached-1.2.1-rbuf/doc diff -w -c memcached-1.2.1/memcached.c memcached-1.2.1-rbuf/memcached.c *** memcached-1.2.1/memcached.c Tue Dec 5 09:34:10 2006 --- memcached-1.2.1-rbuf/memcached.c Sun May 6 08:45:03 2007 *************** *** 1011,1023 **** return; } void process_update_command(conn *c, token_t* tokens, size_t ntokens, int comm) { char *key; size_t nkey; int flags; time_t exptime; int vlen; ! item *it; if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { out_string(c, "CLIENT_ERROR bad command line format"); --- 1011,1163 ---- return; } + /* get ring data */ + inline void process_rget_command(conn *c, token_t* tokens, size_t ntokens) { + char *key; + char *subkey; + size_t nkey; + int i = 0; + int offset = 0; + item *it; + item *ring; + token_t* key_token = &tokens[KEY_TOKEN]; + + //fprintf(stderr,"<length != 0) { + + key = key_token->value; + nkey = key_token->length; + + if(nkey > KEY_MAX_LENGTH) { + out_string(c, "CLIENT_ERROR bad command line format"); + return; + } + + stats.get_cmds++; + ring = get_item(key, nkey); + if (ring) { + if(!ring->ring_capacity) { + out_string(c,"CLIENT_ERROR not a ring buffer"); + return; + } + int occupied_count = RING_nitems(ring); + int item_count = ring->ring_count; + int item_number = 0; + char len_buffer[32]; + + sprintf(len_buffer," 0 %u\r\n",ring->ring_child_lengths); + + add_iov(c, "VALUE ", 6); + add_iov(c, ITEM_key(ring), ring->nkey); + add_iov(c, len_buffer, strlen(len_buffer)); + + //fprintf(stderr,"<ring_count >= ring->ring_capacity) { + offset = (item_number + item_count) % (ring->ring_capacity); + } else { + offset = item_number; + } + + subkey = RING_key_buffer_pointer(ring,offset); + //fprintf(stderr,"<= c->isize) { + item **new_list = realloc(c->ilist, sizeof(item *)*c->isize*2); + if (new_list) { + c->isize *= 2; + c->ilist = new_list; + } else break; + } + + //fprintf(stderr,"<nbytes - 2); + /* + if (add_iov(c, "VALUE ", 6) || + add_iov(c, ITEM_key(it), it->nkey) || + add_iov(c, ITEM_suffix(it), it->nsuffix + it->nbytes)) + { + break; + } + */ + if (settings.verbose > 1) + fprintf(stderr, ">%d sending key %s (as part of %s)\n", c->sfd, ITEM_key(it),ITEM_key(ring)); + + stats.get_hits++; + it->refcount++; + item_update(it); + *(c->ilist + i) = it; + i++; + + //fprintf(stderr,"<value != NULL) { + ntokens = tokenize_command(key_token->value, tokens, MAX_TOKENS); + key_token = tokens; + } + + } while(key_token->value != NULL); + + c->icurr = c->ilist; + c->ileft = i; + + if (settings.verbose > 1) + fprintf(stderr, ">%d END\n", c->sfd); + + if(i) { + add_iov(c, "\r\n", 2); + } + add_iov(c, "END\r\n", 5); + + if (c->udp && build_udp_headers(c)) { + out_string(c, "SERVER_ERROR out of memory"); + } + else { + conn_set_state(c, conn_mwrite); + c->msgcurr = 0; + } + return; + } + void process_update_command(conn *c, token_t* tokens, size_t ntokens, int comm) { char *key; size_t nkey; int flags; time_t exptime; int vlen; ! item *it = 0; if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { out_string(c, "CLIENT_ERROR bad command line format"); *************** *** 1049,1055 **** --- 1189,1220 ---- } } + if(comm == NREAD_RING) { + vlen *= KEY_MAX_LENGTH; + } else if(comm == NREAD_PUSH) { + //fprintf(stderr,"<>\n",key); + + item *ring = get_item(key,nkey); + if(!ring) { + out_string(c, "NOT_FOUND"); + c->write_and_go = conn_swallow; + c->sbytes = vlen+2; + return; + } + //makes a new item + it = ring_push(ring,vlen); + if(!it) { + out_string(c,"SERVER_ERROR inconsistent ring item map or alloc"); + return; + } + //fprintf(stderr,"<>\n"); + //after initial housekeeping, push now looks just like a set op + comm = NREAD_SET; + } + + if(!it) { it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2); + } if (it == 0) { if (! item_size_ok(key, nkey, flags, vlen + 2)) *************** *** 1062,1067 **** --- 1227,1252 ---- return; } + if(comm == NREAD_RING) { + it->ring_capacity = vlen / KEY_MAX_LENGTH; + it->ring_count = 0; + it->ring_child_lengths = 0; + memset(ITEM_data(it), 0, it->nbytes); + int delete_locked = 0; + item *old_it = get_item_notedeleted(key, it->nkey, &delete_locked); + if (old_it) { + if(settings.verbose > 1) + fprintf(stderr, "[dropping old_it, was ring]\n"); + + ring_delete_children(old_it); + item_replace(old_it, it); + } else { + item_link(it); + } + out_string(c, "STORED"); + return; + } + c->item_comm = comm; c->item = it; c->ritem = ITEM_data(it); *************** *** 1192,1197 **** --- 1377,1386 ---- return; } + if(it->ring_count) { + ring_delete_children(it); + } + if (exptime == 0) { item_unlink(it); out_string(c, "DELETED"); *************** *** 1221,1226 **** --- 1410,1534 ---- return; } + + + void ring_make_synthetic_key(item *ring,char *buffer,int item_number) { + char item_number_buffer[KEY_MAX_LENGTH]; + int capacity_len = sprintf(buffer,"%d",ring->ring_capacity); + memset(buffer,0,KEY_MAX_LENGTH); + strncpy(buffer,ITEM_key(ring),KEY_MAX_LENGTH - capacity_len - 1); + sprintf(item_number_buffer,"~%d",item_number); + strcat(buffer,item_number_buffer); + } + + item *ring_push(item *ring,int vlen) { + item *new_item; + char *existing_key; + item *existing_item; + char key_buffer[KEY_MAX_LENGTH]; + int bucket = ring->ring_count % ring->ring_capacity; + + existing_key = RING_key_buffer_pointer(ring,bucket); + if(*existing_key) { + existing_item = get_item(existing_key,strlen(existing_key)); + if(existing_item) { + //minus two for \r\n + ring->ring_child_lengths -= (existing_item->nbytes - 2); + if(settings.verbose > 1) + fprintf(stderr, "[Expelling '%s' from ring buffer, %d bytes. Ring now owns %d bytes.]\n",existing_key,existing_item->nbytes - 2,ring->ring_child_lengths); + + } else { + return NULL; + } + } + + + ring_make_synthetic_key(ring,key_buffer,ring->ring_count); + new_item = item_alloc(key_buffer,strlen(key_buffer),0,realtime(0),vlen+2); + + if(!new_item) { + return NULL; + } + + new_item->is_ring = 1; + strncpy(RING_key_buffer_pointer(ring,bucket),key_buffer,KEY_MAX_LENGTH); + ring->ring_count++; + ring->ring_child_lengths += vlen; + + if(settings.verbose > 1) + fprintf(stderr, "[Take '%s' into ring buffer, %d bytes. Ring now owns %d bytes.]\n",key_buffer,vlen,ring->ring_child_lengths); + + return new_item; + } + + void ring_delete_children(item *ring) { + /* is a ring, has children */ + int i; + for(i=0;inbytes); + fprintf(stderr,edge); + fprintf(stderr,"capacity:%u",ring->ring_capacity); + fprintf(stderr,edge); + fprintf(stderr,"count:%u",ring->ring_count); + fprintf(stderr,edge); + fprintf(stderr,"key:'%s'",ITEM_key(ring)); + + fprintf(stderr,edge); + + + fprintf(stderr,"ring-keys:%d",RING_nitems(ring)); + for(offset=0;offset= 3 && (strcmp(tokens[COMMAND_TOKEN].value, "rget") == 0)) { + + process_rget_command(c, tokens, ntokens); + } else if (ntokens == 3 && strcmp(tokens[COMMAND_TOKEN].value, "own") == 0) { unsigned int bucket, gen; if (!settings.managed) { diff -w -c memcached-1.2.1/memcached.h memcached-1.2.1-rbuf/memcached.h *** memcached-1.2.1/memcached.h Tue Dec 5 09:34:10 2006 --- memcached-1.2.1-rbuf/memcached.h Sun May 6 07:04:36 2007 *************** *** 75,80 **** --- 75,84 ---- unsigned char nsuffix; /* length of flags-and-length string */ unsigned char it_flags; /* ITEM_* above */ unsigned char slabs_clsid;/* which slab class we're in */ + unsigned int ring_capacity; /* number of slots in this if it's a ring buffer container */ + unsigned int ring_count; /* number of items */ + unsigned int ring_child_lengths; /* net payload size */ + unsigned char is_ring; /* child of a ring buffer */ unsigned char nkey; /* key length, w/terminating null and padding */ void * end[0]; /* then null-terminated key */ *************** *** 102,107 **** --- 106,113 ---- #define NREAD_ADD 1 #define NREAD_SET 2 #define NREAD_REPLACE 3 + #define NREAD_RING 4 + #define NREAD_PUSH 5 typedef struct { int sfd; *************** *** 282,284 **** --- 288,300 ---- void set_current_time (); /* update the global variable holding global 32-bit seconds-since-start time (to avoid 64 bit time_t) */ + + + /* ring buffers */ + + #define RING_key_buffer_pointer(ring,n) ((char*)(ITEM_data(ring) + (n * KEY_MAX_LENGTH))) + #define RING_nitems(ring) ((ring->ring_count > ring->ring_capacity)?(ring->ring_capacity):(ring->ring_count)) + #define RING_capacity(ring) (ring->ring_capacity) + + item *ring_push(item *ring,int vlen); + void ring_delete_children(item *ring); Common subdirectories: memcached-1.2.1/scripts and memcached-1.2.1-rbuf/scripts Common subdirectories: memcached-1.2.1/t and memcached-1.2.1-rbuf/t