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,"<<ENTERING RGET COMMAND\n");
+ 
+     do {
+         while(key_token->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,"<<RGET[%s] has %d items in %d buckets\n",key,item_count,occupied_count);
+                 for(item_number = 0;item_number < occupied_count; item_number++) {
+                     if(ring->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,"<<RGET[%s] item %d is [%s]\n",key,item_number,subkey);
+ 
+                     if(!subkey) {
+                         out_string(c,"SERVER_ERROR null subkey");
+                         return;
+                     }
+                     it = get_item(subkey,strlen(subkey));
+                     if(!it) {
+                         out_string(c,"SERVER_ERROR lost subkey");
+                         return;
+                     }
+ 
+                     //fprintf(stderr,"<<RGET[%s] item %d is [%s] continued...\n",key,item_number,subkey);
+ 
+                     if (i >= 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,"<<RGET[%s] item %d is [%s] continued 2...\n",key,item_number,subkey);
+                     
+                     /*
+                      * Construct the response. Each hit adds three elements to the
+                      * outgoing data list:
+                      *   "VALUE "
+                      *   key
+                      *   " " + flags + " " + data length + "\r\n" + data (with \r\n)
+                      */
+                     add_iov(c, ITEM_data(it),it->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,"<<RGET[%s] item %d is [%s] continued 3...\n",key,item_number,subkey);
+ 
+                 }
+             } else stats.get_misses++;
+             
+             key_token++;
+         }
+ 
+         /*
+          * If the command string hasn't been fully processed, get the next set
+          * of tokens.
+          */
+         if(key_token->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,"<<OK, it's a push[%s]>>\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,"<<OK, push far enough along that we're ready to just SET>>\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;i<RING_nitems(ring);i++) {
+         char *subkey = RING_key_buffer_pointer(ring,i);
+         if(*subkey) {
+             item *subitem = get_item(subkey,strlen(subkey));
+             if(subitem) {
+                 item_unlink(subitem);
+             }
+         }
+     }
+ }
+ void ring_dump_info(item *ring) { 
+     int offset; 
+     char * key_array; 
+     char * item_key_slot; 
+     char edge[] = "\n|\t"; 
+  
+     fprintf(stderr,edge); 
+     fprintf(stderr,"ring info:"); 
+     fprintf(stderr,edge); 
+     fprintf(stderr,"ring:0x%08x",ring); 
+     fprintf(stderr,edge); 
+     fprintf(stderr,"nbytes:%u",ring->nbytes); 
+     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<RING_capacity(ring);offset++) { 
+         fprintf(stderr,edge); 
+         item_key_slot = RING_key_buffer_pointer(ring,offset); 
+         if(item_key_slot[0]) { 
+             fprintf(stderr,"%u:'%s'",offset,item_key_slot); 
+         } else { 
+             fprintf(stderr,"%u:nil"); 
+         } 
+     } 
+  
+     fprintf(stderr,"\n---\n"); 
+     int fudge = 20; 
+     for(offset=0;offset<KEY_MAX_LENGTH*RING_capacity(ring);offset++) { 
+         unsigned char c = *(ITEM_data(ring) + offset); 
+         fprintf(stderr,"%c",(isalnum(c)||(c=='_')||(c=='~'))?c:'`'); 
+     } 
+     for(offset;offset<KEY_MAX_LENGTH*RING_capacity(ring) + fudge;offset++) { 
+         unsigned char c = *(ITEM_data(ring) + offset); 
+         if(c) { 
+             fprintf(stderr,"[%c]",isalnum(c)?c:'`'); 
+         } else { 
+             fprintf(stderr,"[`]"); 
+         } 
+     } 
+     fprintf(stderr,"\n---\n"); 
+  
+     fprintf(stderr,"\n\n"); 
+  
+ } 
+ 
+ 
+ 
  void process_command(conn *c, char *command) {
      
      token_t tokens[MAX_TOKENS];
***************
*** 1254,1259 ****
--- 1562,1569 ----
      } else if (ntokens == 6 && 
                 ((strcmp(tokens[COMMAND_TOKEN].value, "add") == 0 && (comm = NREAD_ADD)) || 
                  (strcmp(tokens[COMMAND_TOKEN].value, "set") == 0 && (comm = NREAD_SET)) ||
+                 (strcmp(tokens[COMMAND_TOKEN].value, "ring") == 0 && (comm = NREAD_RING)) ||
+                 (strcmp(tokens[COMMAND_TOKEN].value, "push") == 0 && (comm = NREAD_PUSH)) ||
                  (strcmp(tokens[COMMAND_TOKEN].value, "replace") == 0 && (comm = NREAD_REPLACE)))) {
          
          process_update_command(c, tokens, ntokens, comm);
***************
*** 1270,1275 ****
--- 1580,1589 ----
  
          process_delete_command(c, tokens, ntokens);
  
+     } else if(ntokens >= 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
