Compare commits

...

34 commits

Author SHA1 Message Date
c9s f746030d3f -lpthread 2014-05-24 12:34:55 +08:00
c9s 2a25cfdf01 use CK_VERBOSE 2014-05-24 10:39:07 +08:00
c9s 56bda02997 suite rename 2014-05-24 10:30:35 +08:00
c9s 5d376a9592 use typedef 2014-05-24 10:29:54 +08:00
c9s 7074e89fd0 more queue tests 2014-05-24 10:27:47 +08:00
c9s def79a810b improve queue interface 2014-05-24 10:24:57 +08:00
c9s 9c6902ed57 Improve queue interface 2014-05-24 10:20:37 +08:00
c9s e27740688a Add a basic pthread mutex queue 2014-05-24 10:17:54 +08:00
c9s 5d4b0dc3c9 Add basic worker and its tests 2014-05-24 00:05:50 +08:00
c9s e877dc7f0d Add workers.c to Makefile.am 2014-05-24 00:00:49 +08:00
c9s 0f5ebed73c Merge branch 'master' into feature/stats 2014-05-23 23:39:58 +08:00
c9s 0b499c9158 append new records 2014-05-23 23:28:50 +08:00
c9s 76e4b15787 Merge branch 'master' into feature/stats
Conflicts:
	bench.html
	bench_str.csv
	config.h
	config.h.in
	include/r3.h
	src/node.c
2014-05-23 23:27:10 +08:00
c9s 546fcb14af let tooltip display flags 2014-05-22 23:14:46 +08:00
c9s faaaeb5f90 Merge branch 'master' into feature/stats
Conflicts:
	config.h
	tests/bench.c
	tests/bench.h
	tests/bench_str.csv
	tests/check_tree.c
2014-05-22 22:31:48 +08:00
c9s 8471f42579 edge alignment 2014-05-22 20:26:27 +08:00
c9s 3cbffb645c /= 100.0 2014-05-22 19:42:37 +08:00
c9s 1563bd5a78 fix syntax 2014-05-22 19:24:04 +08:00
c9s adbe71d336 Add _root node for mutex/spin 2014-05-22 19:20:21 +08:00
c9s d73a3aa89a Add a basic feedback system 2014-05-22 17:22:54 +08:00
c9s a4378fdaf2 Add test_feedback 2014-05-22 17:07:02 +08:00
c9s 3121937da5 Add bench_duration function 2014-05-22 17:03:33 +08:00
c9s c421bea11f free tree at the end of benchmarking 2014-05-22 17:00:22 +08:00
c9s 5ada611182 refactor Benchmark related macros 2014-05-22 16:59:40 +08:00
c9s ba270b5948 setting up parent and child. 2014-05-22 16:53:52 +08:00
c9s 24aaa881b1 set node's parent edge 2014-05-22 16:44:56 +08:00
c9s 595dadba15 Merge branch 'master' into feature/stats
Conflicts:
	config.h
	configure.ac
	tests/bench_str.csv
2014-05-22 16:41:46 +08:00
c9s d6b2e52567 Add hits, score fields to edge struct 2014-05-22 16:37:53 +08:00
c9s 2b331ecc8f use uint8_t for endpoint 2014-05-22 16:33:41 +08:00
c9s 21a8c0c891 include config.h in r3.h 2014-05-22 16:32:06 +08:00
c9s a5035ad962 safer uint define 2014-05-22 16:30:09 +08:00
c9s 3500e19316 include stdint.h 2014-05-22 16:29:22 +08:00
c9s 58b74b9126 check stdint.h header 2014-05-22 16:26:55 +08:00
c9s f8154b23e9 Add --enable-stats option 2014-05-22 16:24:24 +08:00
17 changed files with 765 additions and 51 deletions

View file

@ -70,10 +70,43 @@
},
tooltip: {
// headerFormat: '<span style="font-size: 10px">{point.key}: </span><br/>',
formatter: function() {
var s = '';
var comment = this.points[1].point.comment;
// new Date(this.x) + ':';
if (comment) {
s += '<span style="font-size: 10px;">';
s += comment;
s += '</span><br/>';
}
$.each(this.points, function(i, point) {
s += '<span style="color:' + point.series.color + '">\u25CF</span> ' + point.series.name + ': <b>' + point.y + '</b><br/>';
});
return s;
},
shared: true,
crosshairs: true
},
/*
tooltip: {
formatter: function() {
var s = '';
$.each(this.points, function(i, point) {
s += point.series.name +': '+ point.y + '<br/>';
});
if (this.points[1] && this.points[1].comment) {
s += '<b>'+ this.points[1].comment +'</b>';
}
return s;
},
shared: true
},
*/
plotOptions: {
/*
area: {
@ -148,19 +181,23 @@
var lines = data.split(/\n/);
$(lines).each(function(i,line) {
/*
{ marker: {
fillColor: '#FF0000',
lineWidth: 3,
lineColor: "#FF0000" // inherit from series
}
*/
var columns = line.split(/,/);
var a;
a = parseInt(columns[1]);
options.series[0].data.push(a || 0);
a = parseInt(columns[2]);
options.series[1].data.push(a || 0);
a = parseInt(columns[3]);
options.series[2].data.push(a || 0);
a = parseInt(columns[4]);
options.series[3].data.push(a || 0);
var commentText = columns[5];
for (var i = 1; i < 5; i++ ) {
var a = parseInt(columns[i]);
var args = a ?
(commentText ? { y: a, comment: commentText } : a)
: 0;
options.series[i-1].data.push(args);
}
});
$('#chart').highcharts(options);

View file

@ -443,6 +443,23 @@
1400668574,13632260.72
1400681414,10832905.89
1400685490,13185955.87
1400748100,12609470.07
1400748288,13317009.48
1400748727,12973679.22
1400748826,12902583.84
1400748965,13584323.91
1400749175,13518288.33
1400749320,13445606.30
1400749326,13242705.99
1400749599,13245418.70
1400749614,12494314.81
1400749643,12690632.63
1400750350,10391028.46
1400750424,9445761.22
1400750472,9248611.74
1400750479,10757562.36
1400750512,10126746.58
1400750536,10568568.26
1400762875,10472029.42
1400764426,10066458.45,1590373.41
1400765068,10657617.64,2131810.12
@ -511,3 +528,11 @@
1400837774,11190990.08,4331119.44,45590.26,2587281.10
1400837785,10306507.50,3909290.89,47662.55,2827471.10
1400837797,10323334.38,4221122.48,55924.05,2294463.55
1400858847,10663450.41,4674634.54,66576.25,2653715.59
1400858857,10336003.37,4496145.54,59074.70,2607583.19
1400858869,9640828.18,4607189.58,66576.25,2268341.79
1400858880,10959344.32,4114165.27,41943.04,2405089.57
1400858891,9456420.72,4254882.18,33554.43,2770969.36
1400858902,10904696.64,3989404.21,72315.59,2410755.81
1400858913,9379941.50,4385508.67,49932.19,2595906.55
1400858923,10653302.72,4655704.49,55188.21,2677379.49

Can't render this file because it has a wrong number of fields in line 464.

121
config.h.in Normal file
View file

@ -0,0 +1,121 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* "whether graphviz is enable" */
#undef ENABLE_GRAPHVIZ
/* "whether statistics is enable" */
#undef ENABLE_STATS
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <jemalloc/jemalloc.h> header file. */
#undef HAVE_JEMALLOC_JEMALLOC_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you have the PATH_MAX macro. */
#undef USE_JEMALLOC
/* Version number of package */
#undef VERSION
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View file

@ -7,7 +7,8 @@ LT_INIT
AC_PROG_CC
AC_PROG_CC_STDC
# AM_PATH_CHECK()
AC_CHECK_HEADERS([stdlib.h string.h sys/time.h stdint.h pthread.h])
PKG_CHECK_MODULES(CHECK,[check >= 0.9.4],:,[
ifdef([AM_PATH_CHECK],
[AM_PATH_CHECK(,[have_check="yes"])],
@ -16,8 +17,6 @@ PKG_CHECK_MODULES(CHECK,[check >= 0.9.4],:,[
])
AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")
AC_CHECK_HEADERS([stdlib.h string.h sys/time.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
AC_TYPE_SIZE_T
@ -31,23 +30,10 @@ AC_CHECK_FUNCS([gettimeofday memset strchr strdup strndup strstr])
PKG_PROG_PKG_CONFIG
AC_ARG_ENABLE(graphviz,
AS_HELP_STRING([--enable-graphviz],
[enable graphviz support]),
, enable_graphviz=unset)
if test "x$enable_graphviz" != "xunset" ; then
PKG_CHECK_MODULES(GVC_DEPS, [libgvc])
AC_SUBST(GVC_DEPS_CFLAGS)
AC_SUBST(GVC_DEPS_LIBS)
fi
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
[enable debug]),
, enable_debug=unset)
AC_ARG_WITH([malloc],
AS_HELP_STRING([--without-malloc], [Use the default malloc]))
AC_ARG_WITH([malloc], AS_HELP_STRING([--without-malloc], [Use the default malloc]))
AS_IF([test "x$with_malloc" == "xjemalloc"],
[AC_CHECK_HEADERS([jemalloc/jemalloc.h], [
@ -77,16 +63,32 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <jemalloc/jemalloc.h>]],
)
fi
AM_CONDITIONAL(USE_JEMALLOC, test "x$have_jemalloc" = "xyes")
AM_CONDITIONAL(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes")
# AM_CONDITIONAL(USE_JEMALLOC, test "x$found_jemalloc" = "xyes")
# AC_DEFINE(USE_JEMALLOC, test "x$found_jemalloc" = "xyes" , "use jemalloc")
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [enable debug]), [],[enable_debug=unset])
AM_CONDITIONAL(ENABLE_DEBUG, test "x$enable_debug" = "xyes")
AC_ARG_ENABLE(graphviz,
AS_HELP_STRING([--enable-graphviz],
[enable graphviz support]),
, enable_graphviz=unset)
if test "x$enable_graphviz" != "xunset" ; then
PKG_CHECK_MODULES(GVC_DEPS, [libgvc])
AC_SUBST(GVC_DEPS_CFLAGS)
AC_SUBST(GVC_DEPS_LIBS)
fi
AM_CONDITIONAL(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes")
AC_DEFINE(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes", "whether graphviz is enable")
PKG_CHECK_MODULES(DEPS, [libpcre check])
AC_ARG_ENABLE(stats, AS_HELP_STRING([--enable-stats], [enable statistics]), [] ,[enable_stats=unset])
AC_DEFINE(ENABLE_STATS, test "x$enable_stats" = "xyes", "whether statistics is enable")
PKG_CHECK_MODULES(DEPS, [libpcre])
AC_SUBST(DEPS_CFLAGS)
AC_SUBST(DEPS_LIBS)
AC_CONFIG_FILES([

View file

@ -15,27 +15,40 @@
#include "r3_define.h"
#include "str_array.h"
#include "config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
#endif
#define node_edge_pattern(node,i) node->edges[i]->pattern
#define node_edge_pattern_len(node,i) node->edges[i]->pattern_len
struct _root;
struct _edge;
struct _node;
struct _route;
typedef struct _edge edge;
typedef struct _node node;
typedef struct _route route;
typedef struct _root root;
struct _root {
};
struct _node {
edge ** edges;
route ** routes;
int edge_len;
int edge_cap;
int route_len;
int route_cap;
int endpoint;
edge ** edges;
route ** routes;
edge * parent_edge;
uint32_t edge_len;
uint32_t edge_cap;
uint32_t route_len;
uint32_t route_cap;
/** compile-time variables here.... **/
@ -50,14 +63,20 @@ struct _node {
*/
void * data;
uint8_t endpoint;
};
struct _edge {
/* the child node */
node * child;
/* the parent node */
node * parent;
char * pattern;
int pattern_len;
int opcode;
bool has_slug;
node * child;
float score;
bool has_slug:1;
};
typedef struct {
@ -167,6 +186,8 @@ void r3_route_free(route * route);
route * r3_tree_match_route(const node *n, match_entry * entry);
void r3_tree_feedback(node *tree, node *end);
#define METHOD_GET 2
#define METHOD_POST 2<<1
#define METHOD_PUT 2<<2

48
include/r3_queue.h Normal file
View file

@ -0,0 +1,48 @@
/*
* r3_queue.h
* Copyright (C) 2014 c9s <c9s@c9smba.local>
*
* Distributed under terms of the MIT license.
*/
#ifndef R3_QUEUE_H
#define R3_QUEUE_H
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
struct _queue;
struct _queue_node;
typedef struct _queue_node queue_node;
typedef struct _queue queue;
struct _queue_node {
void *data;
queue * next;
};
// typedef struct _queue_node queue_node;
struct _queue {
queue_node * first;
queue_node * last;
};
// create and return the queue
queue * queue_new(void);
// destory the queue (free all the memory associate with the que even the data)
void queue_free(queue * que);
// queue_push the data into queue
// data is expected to a pointer to a heap allocated memory
int queue_push(queue * que, void * data);
// return the data from the que (FIFO)
// and free up all the internally allocated memory
// but the user have to free the returning data pointer
void * queue_pop(queue * que);
#endif /* !R3_QUEUE_H */

26
include/r3_workers.h Normal file
View file

@ -0,0 +1,26 @@
/*
* r3_workers.h
* Copyright (C) 2014 c9s <c9s@c9smba.local>
*
* Distributed under terms of the MIT license.
*/
#ifndef R3_WORKERS_H
#define R3_WORKERS_H
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct {
int thread_id;
node * matched_node;
} feedback_payload;
void r3_feedback_worker_init(pthread_t * t, feedback_payload * data);
void r3_worker_cancel(pthread_t t);
void r3_worker_exit();
#endif /* !R3_WORKERS_H */

View file

@ -1,10 +1,10 @@
lib_LTLIBRARIES = libr3.la
# lib_LIBRARIES = libr3.a
libr3_la_SOURCES = node.c edge.c str.c token.c zmalloc.c
libr3_la_SOURCES = node.c edge.c str.c token.c zmalloc.c workers.c queue.c
# libr3_la_LDFLAGS = -export-symbols-regex '^r3_|^match_'
libr3_la_LIBADD=$(DEPS_LIBS)
AM_CFLAGS=$(DEPS_CFLAGS) -I$(top_builddir) -I$(top_builddir)/include -Wall -std=c99
AM_CFLAGS=$(DEPS_CFLAGS) -I$(top_builddir) -I$(top_builddir)/include -Wall -std=c99 -lpthread
if USE_JEMALLOC
AM_CFLAGS += -ljemalloc

View file

@ -30,6 +30,14 @@ edge * r3_edge_create(char * pattern, int pattern_len, node * child) {
e->pattern_len = pattern_len;
e->opcode = 0;
e->child = child;
e->parent = NULL;
// update childs parent edge
child->parent_edge = e;
// default stats
// e->hits = 0;
e->score = 0;
return e;
}
@ -55,8 +63,10 @@ node * r3_edge_branch(edge *e, int dl) {
// the suffix edge of the leaf
new_child = r3_tree_create(3);
s1_len = e->pattern_len - dl;
e1 = r3_edge_create(zstrndup(s1, s1_len), s1_len, new_child);
s1_len = e->pattern_len - dl;
/* create the parent edge of new child */
e1 = r3_edge_create(zstrndup(s1, s1_len), s1_len, new_child);
// Migrate the child edges to the new edge we just created.
for ( int i = 0 ; i < tmp_edge_len ; i++ ) {

View file

@ -45,6 +45,8 @@ node * r3_tree_create(int cap) {
n->edge_len = 0;
n->edge_cap = cap;
n->parent_edge = NULL;
n->routes = NULL;
n->route_len = 0;
n->route_cap = 0;
@ -95,6 +97,25 @@ edge * r3_node_connectl(node * n, char * pat, int len, int dupl, node *child) {
return e;
}
void r3_tree_feedback(node *tree, node *end) {
edge * e = end->parent_edge;
node * p = e->parent;
while( p && e ) {
e->score += 0.01;
if (e->score > 10) {
for (int i = 0 ; i < p->edge_len ; i++ ) {
if ( p->edges[i]->score > 0 ) {
p->edges[i]->score /= 10.0;
}
}
}
e = p->parent_edge;
p = e ? e->parent : NULL;
}
}
void r3_node_append_edge(node *n, edge *e) {
if (n->edges == NULL) {
n->edge_cap = 3;
@ -107,6 +128,8 @@ void r3_node_append_edge(node *n, edge *e) {
n->edges = p;
}
}
// when append new edge, we update the parent node of the edge.
e->parent = n;
n->edges[ n->edge_len++ ] = e;
}
@ -408,6 +431,8 @@ node * r3_node_create() {
n->edge_len = 0;
n->edge_cap = 0;
n->parent_edge = NULL;
n->routes = NULL;
n->route_len = 0;
n->route_cap = 0;
@ -636,6 +661,8 @@ void r3_tree_dump(node * n, int level) {
print_indent(level + 1);
printf("|-\"%s\"", e->pattern);
// printf(" hits:%lld score:%.1f ", e->hits, e->score);
printf(" score:%.1f ", e->score);
if (e->opcode ) {
printf(" opcode:%d", e->opcode);
}

128
src/queue.c Normal file
View file

@ -0,0 +1,128 @@
/*
* queue.c
* Copyright (C) 2014 c9s <c9s@c9smba.local>
*
* Distributed under terms of the MIT license.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "r3_queue.h"
#include "zmalloc.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Create and return a new queue
**/
queue * queue_new()
{
queue * q = zmalloc(sizeof(queue));
if(q == NULL) {
fprintf(stderr, "Malloc failed creating the que\n");
return NULL;
}
q->first = NULL;
q->last = NULL;
return q;
}
void queue_free(queue * que)
{
if(que == NULL) {
return;
}
pthread_mutex_lock(&mutex);
if(que->first == NULL) {
// ("que->first == NULL .... \n");
zfree(que);
pthread_mutex_unlock(&mutex);
return;
}
// ("que is there lets try to free it...\n");
queue_node * qn = que->first;
while(qn != NULL) {
// freeing the data coz it's on the heap and no one to free it
// except for this one
// ("freeing : %s\n", (char *)qn->data);
zfree(qn->data);
queue_node *tmp = qn->next;
zfree(qn);
qn = tmp;
}
zfree(que);
pthread_mutex_unlock(&mutex);
}
/**
* que is a queue pointer
* data is a heap allocated memory pointer
*/
int queue_push(queue * que, void * data)
{
queue_node * new_node = zmalloc(sizeof(queue_node));
if (new_node == NULL) {
fprintf(stderr, "Malloc failed creating a queue_node\n");
return -1;
}
// assumming data is in heap
new_node->data = data;
new_node->next = NULL;
pthread_mutex_lock(&mutex);
if (que->first == NULL) {
// new que
que->first = new_node;
que->last = new_node;
} else {
que->last->next = new_node;
que->last = new_node;
}
pthread_mutex_unlock(&mutex);
return 0;
}
void * queue_pop(queue * que)
{
// print("Entered to queue_pop\n");
if (que == NULL) {
// print("que is null exiting...\n");
return NULL;
}
pthread_mutex_lock(&mutex);
if (que->first == NULL) {
pthread_mutex_unlock(&mutex);
// print("que->first is null exiting...\n");
return NULL;
}
void * data;
queue_node * qn = que->first;
if (que->first == que->last) {
que->first = NULL;
que->last = NULL;
} else {
que->first = qn->next;
}
data = qn->data;
// print("Freeing qn@ %p", qn);
zfree(qn);
pthread_mutex_unlock(&mutex);
// print("Exiting queue_pop\n");
return data;
}

41
src/workers.c Normal file
View file

@ -0,0 +1,41 @@
/*
* workers.c
* Copyright (C) 2014 c9s <c9s@c9smba.local>
*
* Distributed under terms of the MIT license.
*/
#include "r3.h"
#include "r3_workers.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *r3_feedback_worker(void * data) {
feedback_payload * payload = (feedback_payload*) data; // pointer cast
pthread_exit(NULL);
}
void r3_feedback_worker_init(pthread_t * t, feedback_payload * data) {
int rc;
// pthread_t worker_thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
rc = pthread_create(t, &attr, r3_feedback_worker, (void*) data);
// if the pthread is created, we may free the attr
pthread_attr_destroy(&attr);
// rc = pthread_join(t, &status);
}
void r3_worker_cancel(pthread_t t) {
pthread_cancel(t);
}
void r3_worker_exit() {
pthread_exit(NULL);
}

View file

@ -6,7 +6,7 @@
# endif
TESTS = check_tree
AM_CFLAGS = -ggdb $(DEPS_CFLAGS) -I$(top_builddir) -I$(top_builddir)/include @CHECK_CFLAGS@
AM_LDFLAGS = $(DEPS_LIBS) -L$(top_builddir)/src -lr3 @CHECK_LIBS@
AM_LDFLAGS = $(DEPS_LIBS) -L$(top_builddir)/src -lpthread -lr3 @CHECK_LIBS@
noinst_HEADERS = \
@ -43,6 +43,11 @@ check_tree_SOURCES = check_tree.c
TESTS += check_slug
check_slug_SOURCES = check_slug.c
TESTS += check_worker
check_worker_SOURCES = check_worker.c
TESTS += check_queue
check_queue_SOURCES = check_queue.c
check_PROGRAMS = $(TESTS)

126
tests/check_queue.c Normal file
View file

@ -0,0 +1,126 @@
/*
* check_queue.c
* Copyright (C) 2014 c9s <c9s@c9smba.local>
*
* Distributed under terms of the MIT license.
*/
#include "r3_queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <check.h>
#include "r3.h"
#include "zmalloc.h"
#define number_of_threads 6
#define number_of_threads_d 5
#define number_of_iters 1000
struct _stru {
int number;
int thread_no;
queue * q;
};
void * producer_thread(void * arg)
{
struct _stru * args = (struct _stru *) arg;
int number = args->number;
//int th_number = args->thread_no;
queue * q = args->q;
int i;
srand(time(NULL));
for(i = 0; i < number; i++) {
char * message = zmalloc(16);
snprintf(message, 15, "rand: %d", rand());
queue_push(q, (void *)message);
}
return NULL;
}
void * consumer_thread(void * args)
{
queue * q = (queue *) args;
void * data;
while((data = queue_pop(q)) != NULL) {
char * string = (char *)data;
zfree(data);
}
return NULL;
}
START_TEST (test_queue)
{
queue * q = queue_new();
for (int i = 0 ; i < 100 ; i++ ) {
queue_push(q, (void*) i);
}
for (int i = 0 ; i < 100 ; i++ ) {
int v = (int) queue_pop(q);
ck_assert_int_eq(i, v);
}
queue_free(q);
}
END_TEST
START_TEST (test_queue_threads)
{
queue * q = queue_new();
pthread_t threads[number_of_threads];
pthread_t thread_d[number_of_threads_d];
int i;
struct _stru arg[number_of_threads];
for(i = 0; i < number_of_threads; i++) {
arg[i].number = number_of_iters;
arg[i].thread_no = i;
arg[i].q = q;
pthread_create(threads+i, NULL, producer_thread, (void *)&arg[i]);
}
for(i = 0; i < number_of_threads_d; i++) {
pthread_create(thread_d+i, NULL, consumer_thread, (void *)q);
}
for(i = 0; i < number_of_threads; i++) {
pthread_join(*(threads+i), NULL);
}
for(i = 0; i < number_of_threads_d; i++) {
pthread_join(*(thread_d+i), NULL);
}
queue_free(q);
}
END_TEST
Suite* r3_suite (void) {
Suite *suite = suite_create("queue");
TCase *tcase = tcase_create("queue_test");
tcase_add_test(tcase, test_queue_threads);
tcase_add_test(tcase, test_queue);
tcase_set_timeout(tcase, 30);
suite_add_tcase(suite, tcase);
return suite;
}
int main (int argc, char *argv[]) {
int number_failed;
Suite *suite = r3_suite();
SRunner *runner = srunner_create(suite);
srunner_run_all(runner, CK_VERBOSE);
number_failed = srunner_ntests_failed(runner);
srunner_free(runner);
return number_failed;
}

View file

@ -125,7 +125,7 @@ int main (int argc, char *argv[]) {
int number_failed;
Suite *suite = r3_suite();
SRunner *runner = srunner_create(suite);
srunner_run_all(runner, CK_NORMAL);
srunner_run_all(runner, CK_VERBOSE);
number_failed = srunner_ntests_failed(runner);
srunner_free(runner);
return number_failed;

View file

@ -361,8 +361,36 @@ START_TEST(test_insert_route)
END_TEST
START_TEST(test_feedback)
{
node * t = r3_tree_create(1);
r3_tree_insert_path(t, "/foo/bar/baz", NULL);
r3_tree_insert_path(t, "/foo/grault/bar", NULL);
r3_tree_insert_path(t, "/garply/corge/grault", NULL);
r3_tree_compile(t);
node * m1 = r3_tree_match(t, "/foo/grault/bar", NULL);
node * m2 = r3_tree_match(t, "/garply/corge/grault", NULL);
ck_assert(m1 != NULL);
ck_assert(m2 != NULL);
for ( int i = 0 ; i < 120 ; i++ ) {
r3_tree_feedback(t, m1);
}
for ( int i = 0 ; i < 200 ; i++ ) {
r3_tree_feedback(t, m2);
}
r3_tree_dump(t, 0);
r3_tree_free(t);
}
END_TEST
Suite* r3_suite (void) {
Suite *suite = suite_create("blah");
Suite *suite = suite_create("route tests");
TCase *tcase = tcase_create("testcase");
tcase_set_timeout(tcase, 30);
@ -379,6 +407,7 @@ Suite* r3_suite (void) {
tcase_add_test(tcase, test_pcre_patterns_insert);
tcase_add_test(tcase, test_pcre_patterns_insert_2);
tcase_add_test(tcase, test_pcre_patterns_insert_3);
tcase_add_test(tcase, test_feedback);
tcase_set_timeout(tcase, 30);
suite_add_tcase(suite, tcase);
@ -390,7 +419,7 @@ int main (int argc, char *argv[]) {
int number_failed;
Suite *suite = r3_suite();
SRunner *runner = srunner_create(suite);
srunner_run_all(runner, CK_NORMAL);
srunner_run_all(runner, CK_VERBOSE);
number_failed = srunner_ntests_failed(runner);
srunner_free(runner);
return number_failed;

68
tests/check_worker.c Normal file
View file

@ -0,0 +1,68 @@
/*
* check_worker.c
* Copyright (C) 2014 c9s <c9s@c9smba.local>
*
* Distributed under terms of the MIT license.
*/
#include "config.h"
#include <stdio.h>
#include <check.h>
#include <stdlib.h>
#include "r3.h"
#include "r3_str.h"
#include "r3_workers.h"
#include "str_array.h"
#include "bench.h"
START_TEST (test_feedback_worker)
{
node * n = r3_tree_create(1);
r3_tree_insert_path(n, "/foo/bar/baz", NULL);
r3_tree_insert_path(n, "/foo/bar/qux", NULL);
r3_tree_insert_path(n, "/foo/bar/quux", NULL);
r3_tree_insert_path(n, "/foo/bar/corge", NULL);
r3_tree_insert_path(n, "/foo/bar/grault", NULL);
r3_tree_insert_path(n, "/garply/grault/foo", NULL);
r3_tree_insert_path(n, "/garply/grault/bar", NULL);
r3_tree_compile(n);
giant_lock *tl = r3_giant_lock_create(n);
node * matched;
matched = r3_tree_matchl_ts(n, "/garply/grault/foo", strlen("/garply/grault/foo"), NULL); // thread-safe
r3_feedback_worker_init();
/*
feedback_payload payload;
payload.matched_node = matched;
r3_feedback_worker_init(&payload);
*/
r3_tree_free(n);
}
END_TEST
Suite* r3_suite (void) {
Suite *suite = suite_create("Worker Test");
TCase *tcase = tcase_create("worker test");
tcase_add_test(tcase, test_feedback_worker);
suite_add_tcase(suite, tcase);
return suite;
}
int main (int argc, char *argv[]) {
int number_failed;
Suite *suite = r3_suite();
SRunner *runner = srunner_create(suite);
srunner_run_all(runner, CK_NORMAL);
number_failed = srunner_ntests_failed(runner);
srunner_free(runner);
return number_failed;
}