Permalink
Browse files

first commit

  • Loading branch information...
0 parents commit 860b602c80310ac9d618bae43c63c306ec2f7a03 @antirez committed Sep 20, 2010
Showing with 4,559 additions and 0 deletions.
  1. +40 −0 Makefile
  2. +7 −0 README
  3. +325 −0 adlist.c
  4. +92 −0 adlist.h
  5. +390 −0 ae.c
  6. +117 −0 ae.h
  7. +91 −0 ae_epoll.c
  8. +93 −0 ae_kqueue.c
  9. +72 −0 ae_select.c
  10. +270 −0 anet.c
  11. +49 −0 anet.h
  12. +55 −0 config.h
  13. +15 −0 fmacros.h
  14. +547 −0 mc-benchmark.c
  15. +1,557 −0 redis.c
  16. +480 −0 sds.c
  17. +77 −0 sds.h
  18. +239 −0 zmalloc.c
  19. +43 −0 zmalloc.h
@@ -0,0 +1,40 @@
+# MCbenchmark Makefile
+# Copyright (C) 2010 Salvatore Sanfilippo <antirez at gmail dot com>
+# This file is released under the BSD license, see the COPYING file
+
+uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
+OPTIMIZATION?=-O2
+ifeq ($(uname_S),SunOS)
+ CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6
+ CCLINK?= -ldl -lnsl -lsocket -lm
+else
+ CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -Wall -W $(ARCH) $(PROF)
+ CCLINK?= -lm
+endif
+CCOPT= $(CFLAGS) $(CCLINK) $(ARCH) $(PROF)
+DEBUG?= -g -rdynamic -ggdb
+
+PREFIX= /usr/local
+INSTALL_BIN= $(PREFIX)/bin
+INSTALL= cp -p
+
+BENCHOBJ = ae.o anet.o mc-benchmark.o sds.o adlist.o zmalloc.o
+
+BENCHPRGNAME = mc-benchmark
+
+all: mc-benchmark
+
+mc-benchmark: $(BENCHOBJ)
+ $(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ)
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $<
+
+clean:
+ rm -rf $(BENCHPRGNAME) *.o
+
+dep:
+ $(CC) -MM *.c
+
+bench:
+ ./mc-benchmark
7 README
@@ -0,0 +1,7 @@
+This is a straightforward port of redis-benchmark to memcache protocol.
+
+This way it is possible to test Redis and Memcache with not just an apple to
+apple comparison, but also using the exactly same mouth... :)
+
+For feedbacks please send a message to the Redis Google Group
+Alternatively drop an email t$ antirez at gmail dot com
325 adlist.c
@@ -0,0 +1,325 @@
+/* adlist.c - A generic doubly linked list implementation
+ *
+ * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Redis nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdlib.h>
+#include "adlist.h"
+#include "zmalloc.h"
+
+/* Create a new list. The created list can be freed with
+ * AlFreeList(), but private value of every node need to be freed
+ * by the user before to call AlFreeList().
+ *
+ * On error, NULL is returned. Otherwise the pointer to the new list. */
+list *listCreate(void)
+{
+ struct list *list;
+
+ if ((list = zmalloc(sizeof(*list))) == NULL)
+ return NULL;
+ list->head = list->tail = NULL;
+ list->len = 0;
+ list->dup = NULL;
+ list->free = NULL;
+ list->match = NULL;
+ return list;
+}
+
+/* Free the whole list.
+ *
+ * This function can't fail. */
+void listRelease(list *list)
+{
+ unsigned int len;
+ listNode *current, *next;
+
+ current = list->head;
+ len = list->len;
+ while(len--) {
+ next = current->next;
+ if (list->free) list->free(current->value);
+ zfree(current);
+ current = next;
+ }
+ zfree(list);
+}
+
+/* Add a new node to the list, to head, contaning the specified 'value'
+ * pointer as value.
+ *
+ * On error, NULL is returned and no operation is performed (i.e. the
+ * list remains unaltered).
+ * On success the 'list' pointer you pass to the function is returned. */
+list *listAddNodeHead(list *list, void *value)
+{
+ listNode *node;
+
+ if ((node = zmalloc(sizeof(*node))) == NULL)
+ return NULL;
+ node->value = value;
+ if (list->len == 0) {
+ list->head = list->tail = node;
+ node->prev = node->next = NULL;
+ } else {
+ node->prev = NULL;
+ node->next = list->head;
+ list->head->prev = node;
+ list->head = node;
+ }
+ list->len++;
+ return list;
+}
+
+/* Add a new node to the list, to tail, contaning the specified 'value'
+ * pointer as value.
+ *
+ * On error, NULL is returned and no operation is performed (i.e. the
+ * list remains unaltered).
+ * On success the 'list' pointer you pass to the function is returned. */
+list *listAddNodeTail(list *list, void *value)
+{
+ listNode *node;
+
+ if ((node = zmalloc(sizeof(*node))) == NULL)
+ return NULL;
+ node->value = value;
+ if (list->len == 0) {
+ list->head = list->tail = node;
+ node->prev = node->next = NULL;
+ } else {
+ node->prev = list->tail;
+ node->next = NULL;
+ list->tail->next = node;
+ list->tail = node;
+ }
+ list->len++;
+ return list;
+}
+
+list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
+ listNode *node;
+
+ if ((node = zmalloc(sizeof(*node))) == NULL)
+ return NULL;
+ node->value = value;
+ if (after) {
+ node->prev = old_node;
+ node->next = old_node->next;
+ if (list->tail == old_node) {
+ list->tail = node;
+ }
+ } else {
+ node->next = old_node;
+ node->prev = old_node->prev;
+ if (list->head == old_node) {
+ list->head = node;
+ }
+ }
+ if (node->prev != NULL) {
+ node->prev->next = node;
+ }
+ if (node->next != NULL) {
+ node->next->prev = node;
+ }
+ list->len++;
+ return list;
+}
+
+/* Remove the specified node from the specified list.
+ * It's up to the caller to free the private value of the node.
+ *
+ * This function can't fail. */
+void listDelNode(list *list, listNode *node)
+{
+ if (node->prev)
+ node->prev->next = node->next;
+ else
+ list->head = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
+ else
+ list->tail = node->prev;
+ if (list->free) list->free(node->value);
+ zfree(node);
+ list->len--;
+}
+
+/* Returns a list iterator 'iter'. After the initialization every
+ * call to listNext() will return the next element of the list.
+ *
+ * This function can't fail. */
+listIter *listGetIterator(list *list, int direction)
+{
+ listIter *iter;
+
+ if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
+ if (direction == AL_START_HEAD)
+ iter->next = list->head;
+ else
+ iter->next = list->tail;
+ iter->direction = direction;
+ return iter;
+}
+
+/* Release the iterator memory */
+void listReleaseIterator(listIter *iter) {
+ zfree(iter);
+}
+
+/* Create an iterator in the list private iterator structure */
+void listRewind(list *list, listIter *li) {
+ li->next = list->head;
+ li->direction = AL_START_HEAD;
+}
+
+void listRewindTail(list *list, listIter *li) {
+ li->next = list->tail;
+ li->direction = AL_START_TAIL;
+}
+
+/* Return the next element of an iterator.
+ * It's valid to remove the currently returned element using
+ * listDelNode(), but not to remove other elements.
+ *
+ * The function returns a pointer to the next element of the list,
+ * or NULL if there are no more elements, so the classical usage patter
+ * is:
+ *
+ * iter = listGetIterator(list,<direction>);
+ * while ((node = listNext(iter)) != NULL) {
+ * doSomethingWith(listNodeValue(node));
+ * }
+ *
+ * */
+listNode *listNext(listIter *iter)
+{
+ listNode *current = iter->next;
+
+ if (current != NULL) {
+ if (iter->direction == AL_START_HEAD)
+ iter->next = current->next;
+ else
+ iter->next = current->prev;
+ }
+ return current;
+}
+
+/* Duplicate the whole list. On out of memory NULL is returned.
+ * On success a copy of the original list is returned.
+ *
+ * The 'Dup' method set with listSetDupMethod() function is used
+ * to copy the node value. Otherwise the same pointer value of
+ * the original node is used as value of the copied node.
+ *
+ * The original list both on success or error is never modified. */
+list *listDup(list *orig)
+{
+ list *copy;
+ listIter *iter;
+ listNode *node;
+
+ if ((copy = listCreate()) == NULL)
+ return NULL;
+ copy->dup = orig->dup;
+ copy->free = orig->free;
+ copy->match = orig->match;
+ iter = listGetIterator(orig, AL_START_HEAD);
+ while((node = listNext(iter)) != NULL) {
+ void *value;
+
+ if (copy->dup) {
+ value = copy->dup(node->value);
+ if (value == NULL) {
+ listRelease(copy);
+ listReleaseIterator(iter);
+ return NULL;
+ }
+ } else
+ value = node->value;
+ if (listAddNodeTail(copy, value) == NULL) {
+ listRelease(copy);
+ listReleaseIterator(iter);
+ return NULL;
+ }
+ }
+ listReleaseIterator(iter);
+ return copy;
+}
+
+/* Search the list for a node matching a given key.
+ * The match is performed using the 'match' method
+ * set with listSetMatchMethod(). If no 'match' method
+ * is set, the 'value' pointer of every node is directly
+ * compared with the 'key' pointer.
+ *
+ * On success the first matching node pointer is returned
+ * (search starts from head). If no matching node exists
+ * NULL is returned. */
+listNode *listSearchKey(list *list, void *key)
+{
+ listIter *iter;
+ listNode *node;
+
+ iter = listGetIterator(list, AL_START_HEAD);
+ while((node = listNext(iter)) != NULL) {
+ if (list->match) {
+ if (list->match(node->value, key)) {
+ listReleaseIterator(iter);
+ return node;
+ }
+ } else {
+ if (key == node->value) {
+ listReleaseIterator(iter);
+ return node;
+ }
+ }
+ }
+ listReleaseIterator(iter);
+ return NULL;
+}
+
+/* Return the element at the specified zero-based index
+ * where 0 is the head, 1 is the element next to head
+ * and so on. Negative integers are used in order to count
+ * from the tail, -1 is the last element, -2 the penultimante
+ * and so on. If the index is out of range NULL is returned. */
+listNode *listIndex(list *list, int index) {
+ listNode *n;
+
+ if (index < 0) {
+ index = (-index)-1;
+ n = list->tail;
+ while(index-- && n) n = n->prev;
+ } else {
+ n = list->head;
+ while(index-- && n) n = n->next;
+ }
+ return n;
+}
Oops, something went wrong.

0 comments on commit 860b602

Please sign in to comment.