Compare commits
34 commits
2.0
...
feature/th
Author | SHA1 | Date | |
---|---|---|---|
|
f746030d3f | ||
|
2a25cfdf01 | ||
|
56bda02997 | ||
|
5d376a9592 | ||
|
7074e89fd0 | ||
|
def79a810b | ||
|
9c6902ed57 | ||
|
e27740688a | ||
|
5d4b0dc3c9 | ||
|
e877dc7f0d | ||
|
0f5ebed73c | ||
|
0b499c9158 | ||
|
76e4b15787 | ||
|
546fcb14af | ||
|
faaaeb5f90 | ||
|
8471f42579 | ||
|
3cbffb645c | ||
|
1563bd5a78 | ||
|
adbe71d336 | ||
|
d73a3aa89a | ||
|
a4378fdaf2 | ||
|
3121937da5 | ||
|
c421bea11f | ||
|
5ada611182 | ||
|
ba270b5948 | ||
|
24aaa881b1 | ||
|
595dadba15 | ||
|
d6b2e52567 | ||
|
2b331ecc8f | ||
|
21a8c0c891 | ||
|
a5035ad962 | ||
|
3500e19316 | ||
|
58b74b9126 | ||
|
f8154b23e9 |
17 changed files with 765 additions and 51 deletions
61
bench.html
61
bench.html
|
@ -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);
|
||||
|
|
|
@ -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
121
config.h.in
Normal 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
|
46
configure.ac
46
configure.ac
|
@ -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([
|
||||
|
|
39
include/r3.h
39
include/r3.h
|
@ -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
48
include/r3_queue.h
Normal 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
26
include/r3_workers.h
Normal 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 */
|
|
@ -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
|
||||
|
|
14
src/edge.c
14
src/edge.c
|
@ -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++ ) {
|
||||
|
|
27
src/node.c
27
src/node.c
|
@ -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
128
src/queue.c
Normal 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
41
src/workers.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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
126
tests/check_queue.c
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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
68
tests/check_worker.c
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue