agoo 1.2.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +11 -9
- data/ext/agoo/agoo.c +45 -0
- data/ext/agoo/base64.c +107 -0
- data/ext/agoo/base64.h +15 -0
- data/ext/agoo/ccache.c +301 -0
- data/ext/agoo/ccache.h +53 -0
- data/ext/agoo/con.c +522 -82
- data/ext/agoo/con.h +7 -5
- data/ext/agoo/debug.c +121 -7
- data/ext/agoo/debug.h +11 -6
- data/ext/agoo/error_stream.c +5 -6
- data/ext/agoo/error_stream.h +1 -1
- data/ext/agoo/extconf.rb +2 -1
- data/ext/agoo/hook.c +4 -4
- data/ext/agoo/hook.h +1 -0
- data/ext/agoo/http.c +2 -2
- data/ext/agoo/http.h +2 -0
- data/ext/agoo/log.c +604 -219
- data/ext/agoo/log.h +20 -7
- data/ext/agoo/page.c +20 -23
- data/ext/agoo/page.h +2 -0
- data/ext/agoo/pub.c +111 -0
- data/ext/agoo/pub.h +40 -0
- data/ext/agoo/queue.c +2 -2
- data/ext/agoo/rack_logger.c +15 -71
- data/ext/agoo/rack_logger.h +1 -1
- data/ext/agoo/request.c +96 -21
- data/ext/agoo/request.h +23 -12
- data/ext/agoo/res.c +5 -2
- data/ext/agoo/res.h +4 -0
- data/ext/agoo/response.c +13 -12
- data/ext/agoo/response.h +1 -2
- data/ext/agoo/server.c +290 -428
- data/ext/agoo/server.h +10 -10
- data/ext/agoo/sha1.c +148 -0
- data/ext/agoo/sha1.h +10 -0
- data/ext/agoo/sse.c +26 -0
- data/ext/agoo/sse.h +12 -0
- data/ext/agoo/sub.c +111 -0
- data/ext/agoo/sub.h +36 -0
- data/ext/agoo/subscription.c +54 -0
- data/ext/agoo/subscription.h +18 -0
- data/ext/agoo/text.c +26 -4
- data/ext/agoo/text.h +2 -0
- data/ext/agoo/types.h +13 -0
- data/ext/agoo/upgraded.c +148 -0
- data/ext/agoo/upgraded.h +13 -0
- data/ext/agoo/websocket.c +248 -0
- data/ext/agoo/websocket.h +27 -0
- data/lib/agoo/version.rb +1 -1
- data/lib/rack/handler/agoo.rb +13 -6
- data/test/base_handler_test.rb +24 -22
- data/test/log_test.rb +146 -199
- data/test/rack_handler_test.rb +19 -20
- data/test/static_test.rb +30 -28
- metadata +23 -7
- data/test/rrr/test.rb +0 -26
- data/test/tests.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e5b92639ed425d8f0f8d33b8da3b5dd81a11249c5addcaec2707fd8d8917d5b
|
4
|
+
data.tar.gz: 84c94c8566135a06165d707c0f8f71f5728c347ae35e4deabcdb1c339f1756d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe77ec0550fe15e3ba8eb63d42c670d6738ce295bbf7dbc59e2566cbfba4a58768fc2d98af1720a73f32970d18cf92967686cc5330bac7b395dd7248a156a45e
|
7
|
+
data.tar.gz: 49f218eae4272aeda0e915279dc69fed7225e6bcdc07b6382a7a189b451a954b6685e6ce0195cf64c3efa0fb25df4dd1faa0e2e75cb071edfe4e2a24918371c4
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ A High Performance HTTP Server for Ruby
|
|
11
11
|
```ruby
|
12
12
|
require 'agoo'
|
13
13
|
|
14
|
-
|
14
|
+
Agoo::Server.init(6464, 'root')
|
15
15
|
|
16
16
|
class MyHandler
|
17
17
|
def call(req)
|
@@ -20,8 +20,8 @@ class MyHandler
|
|
20
20
|
end
|
21
21
|
|
22
22
|
handler = MyHandler.new
|
23
|
-
|
24
|
-
|
23
|
+
Agoo::Server.handle(:GET, "/hello", handler)
|
24
|
+
Agoo::Server.start()
|
25
25
|
# To run this example type the following then go to a browser and enter a URL of localhost:6464/hello.
|
26
26
|
# ruby hello.rb
|
27
27
|
```
|
@@ -38,14 +38,14 @@ performance HTTP server that serves static resource at hundreds of thousands
|
|
38
38
|
of fetchs per second. A a simple hello world Ruby handler at over 100,000
|
39
39
|
requests per second on a desktop computer. That places Agoo at about 85 times
|
40
40
|
faster than Sinatra and 1000 times faster than Rails. In both cases the
|
41
|
-
latency was two orders of magnitude lower or more. Checkout the benchmarks on
|
42
|
-
href="http://opo.technology/benchmarks.html#web_benchmarks">OpO
|
43
|
-
benchmarks</a>. Note that the benchmarks had to use a C program called
|
44
|
-
|
45
|
-
|
41
|
+
latency was two orders of magnitude lower or more. Checkout the benchmarks on
|
42
|
+
<a href="http://opo.technology/benchmarks.html#web_benchmarks">OpO
|
43
|
+
benchmarks</a>. Note that the benchmarks had to use a C program called <a
|
44
|
+
href="https://github.com/ohler55/perfer">Perfer</a> to hit the Agoo
|
45
|
+
limits. Ruby benchmarks driver could not push Agoo hard enough.
|
46
46
|
|
47
47
|
Agoo supports the [Ruby rack API](https://rack.github.io) which allows for the
|
48
|
-
use of rack compatible gems.
|
48
|
+
use of rack compatible gems. Agoo also supports WebSockets and SSE.
|
49
49
|
|
50
50
|
## Releases
|
51
51
|
|
@@ -64,4 +64,6 @@ the develop branch. Pull requests should be made against the develop branch.
|
|
64
64
|
|
65
65
|
- *WABuR* *repo*: https://github.com/ohler55/wabur has an option to use Agoo
|
66
66
|
|
67
|
+
- *Perfer* *repo*: https://github.com/ohler55/perfer
|
68
|
+
|
67
69
|
Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announcements and news about the Agoo gem.
|
data/ext/agoo/agoo.c
CHANGED
@@ -1,13 +1,49 @@
|
|
1
1
|
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
2
|
|
3
|
+
#include <signal.h>
|
3
4
|
#include <stdio.h>
|
5
|
+
|
4
6
|
#include <ruby.h>
|
5
7
|
|
8
|
+
#include "debug.h"
|
6
9
|
#include "error_stream.h"
|
10
|
+
#include "log.h"
|
7
11
|
#include "rack_logger.h"
|
8
12
|
#include "request.h"
|
9
13
|
#include "response.h"
|
10
14
|
#include "server.h"
|
15
|
+
#include "subscription.h"
|
16
|
+
#include "upgraded.h"
|
17
|
+
|
18
|
+
void
|
19
|
+
agoo_shutdown() {
|
20
|
+
server_shutdown();
|
21
|
+
log_close();
|
22
|
+
}
|
23
|
+
|
24
|
+
/* Document-method: shutdown
|
25
|
+
*
|
26
|
+
* call-seq: shutdown()
|
27
|
+
*
|
28
|
+
* Shutdown the server and logger.
|
29
|
+
*/
|
30
|
+
static VALUE
|
31
|
+
ragoo_shutdown(VALUE self) {
|
32
|
+
agoo_shutdown();
|
33
|
+
debug_rreport();
|
34
|
+
return Qnil;
|
35
|
+
}
|
36
|
+
|
37
|
+
static void
|
38
|
+
sig_handler(int sig) {
|
39
|
+
agoo_shutdown();
|
40
|
+
|
41
|
+
debug_report();
|
42
|
+
// Use exit instead of rb_exit as rb_exit segfaults most of the time.
|
43
|
+
//rb_exit(0);
|
44
|
+
exit(0);
|
45
|
+
}
|
46
|
+
|
11
47
|
|
12
48
|
/* Document-module: Agoo
|
13
49
|
*
|
@@ -18,9 +54,18 @@ void
|
|
18
54
|
Init_agoo() {
|
19
55
|
VALUE mod = rb_define_module("Agoo");
|
20
56
|
|
57
|
+
log_init(mod);
|
21
58
|
error_stream_init(mod);
|
22
59
|
rack_logger_init(mod);
|
23
60
|
request_init(mod);
|
24
61
|
response_init(mod);
|
25
62
|
server_init(mod);
|
63
|
+
subscription_init(mod);
|
64
|
+
upgraded_init(mod);
|
65
|
+
|
66
|
+
rb_define_module_function(mod, "shutdown", ragoo_shutdown, 0);
|
67
|
+
|
68
|
+
signal(SIGINT, sig_handler);
|
69
|
+
signal(SIGTERM, sig_handler);
|
70
|
+
signal(SIGPIPE, SIG_IGN);
|
26
71
|
}
|
data/ext/agoo/base64.c
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
// Copyright 2011, 2016, 2018 by Peter Ohler, All Rights Reserved
|
2
|
+
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
|
6
|
+
#include "base64.h"
|
7
|
+
|
8
|
+
static char digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
9
|
+
|
10
|
+
/* invalid or terminating characters are set to 'X' or \x58 */
|
11
|
+
static uchar s_digits[257] = "\
|
12
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
13
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
14
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x3E\x58\x58\x58\x3F\
|
15
|
+
\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x58\x58\x58\x58\x58\x58\
|
16
|
+
\x58\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\
|
17
|
+
\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x58\x58\x58\x58\x58\
|
18
|
+
\x58\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\
|
19
|
+
\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x58\x58\x58\x58\x58\
|
20
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
21
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
22
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
23
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
24
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
25
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
26
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
|
27
|
+
\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58";
|
28
|
+
|
29
|
+
int
|
30
|
+
b64_to(const uchar *src, int len, char *b64) {
|
31
|
+
const uchar *end3;
|
32
|
+
int len3 = len % 3;
|
33
|
+
uchar b1, b2, b3;
|
34
|
+
char *start = b64;
|
35
|
+
|
36
|
+
end3 = src + (len - len3);
|
37
|
+
while (src < end3) {
|
38
|
+
b1 = *src++;
|
39
|
+
b2 = *src++;
|
40
|
+
b3 = *src++;
|
41
|
+
*b64++ = digits[(uchar)(b1 >> 2)];
|
42
|
+
*b64++ = digits[(uchar)(((b1 & 0x03) << 4) | (b2 >> 4))];
|
43
|
+
*b64++ = digits[(uchar)(((b2 & 0x0F) << 2) | (b3 >> 6))];
|
44
|
+
*b64++ = digits[(uchar)(b3 & 0x3F)];
|
45
|
+
}
|
46
|
+
if (1 == len3) {
|
47
|
+
b1 = *src++;
|
48
|
+
*b64++ = digits[b1 >> 2];
|
49
|
+
*b64++ = digits[(b1 & 0x03) << 4];
|
50
|
+
*b64++ = '=';
|
51
|
+
*b64++ = '=';
|
52
|
+
} else if (2 == len3) {
|
53
|
+
b1 = *src++;
|
54
|
+
b2 = *src++;
|
55
|
+
*b64++ = digits[b1 >> 2];
|
56
|
+
*b64++ = digits[((b1 & 0x03) << 4) | (b2 >> 4)];
|
57
|
+
*b64++ = digits[(b2 & 0x0F) << 2];
|
58
|
+
*b64++ = '=';
|
59
|
+
}
|
60
|
+
*b64 = '\0';
|
61
|
+
|
62
|
+
return (int)(b64 - start);
|
63
|
+
}
|
64
|
+
|
65
|
+
unsigned long
|
66
|
+
b64_orig_size(const char *text) {
|
67
|
+
const char *start = text;
|
68
|
+
unsigned long size = 0;
|
69
|
+
|
70
|
+
if ('\0' != *text) {
|
71
|
+
for (; 0 != *text; text++) { }
|
72
|
+
size = (text - start) * 3 / 4;
|
73
|
+
text--;
|
74
|
+
if ('=' == *text) {
|
75
|
+
size--;
|
76
|
+
text--;
|
77
|
+
if ('=' == *text) {
|
78
|
+
size--;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
return size;
|
83
|
+
}
|
84
|
+
|
85
|
+
void
|
86
|
+
b64_from(const char *b64, uchar *str) {
|
87
|
+
uchar b0, b1, b2, b3;
|
88
|
+
|
89
|
+
while (1) {
|
90
|
+
if ('X' == (b0 = s_digits[(uchar)*b64++])) {
|
91
|
+
break;
|
92
|
+
}
|
93
|
+
if ('X' == (b1 = s_digits[(uchar)*b64++])) {
|
94
|
+
break;
|
95
|
+
}
|
96
|
+
*str++ = (b0 << 2) | ((b1 >> 4) & 0x03);
|
97
|
+
if ('X' == (b2 = s_digits[(uchar)*b64++])) {
|
98
|
+
break;
|
99
|
+
}
|
100
|
+
*str++ = (b1 << 4) | ((b2 >> 2) & 0x0F);
|
101
|
+
if ('X' == (b3 = s_digits[(uchar)*b64++])) {
|
102
|
+
break;
|
103
|
+
}
|
104
|
+
*str++ = (b2 << 6) | b3;
|
105
|
+
}
|
106
|
+
*str = '\0';
|
107
|
+
}
|
data/ext/agoo/base64.h
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
// Copyright 2011, 2016, 2018 by Peter Ohler, All Rights Reserved
|
2
|
+
|
3
|
+
#ifndef __AGOO_BASE64_H__
|
4
|
+
#define __AGOO_BASE64_H__
|
5
|
+
|
6
|
+
typedef unsigned char uchar;
|
7
|
+
|
8
|
+
#define b64_size(len) ((len + 2) / 3 * 4)
|
9
|
+
|
10
|
+
extern unsigned long b64_orig_size(const char *text);
|
11
|
+
|
12
|
+
extern int b64_to(const uchar *src, int len, char *b64);
|
13
|
+
extern void b64_from(const char *b64, uchar *str);
|
14
|
+
|
15
|
+
#endif /* __AGOO_BASE64_H__ */
|
data/ext/agoo/ccache.c
ADDED
@@ -0,0 +1,301 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <string.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
#include <stdio.h>
|
7
|
+
|
8
|
+
#include "ccache.h"
|
9
|
+
#include "con.h"
|
10
|
+
#include "debug.h"
|
11
|
+
|
12
|
+
static void
|
13
|
+
cc_mark(void *ptr) {
|
14
|
+
if (NULL != ptr) {
|
15
|
+
CCache cc = (CCache)ptr;
|
16
|
+
CSlot slot;
|
17
|
+
CSlot *bp = cc->buckets;
|
18
|
+
CSlot *end = bp + CC_BUCKET_SIZE;
|
19
|
+
|
20
|
+
if (Qnil != cc->wrap) {
|
21
|
+
rb_gc_mark(cc->wrap);
|
22
|
+
}
|
23
|
+
pthread_mutex_lock(&cc->lock);
|
24
|
+
for (bp = cc->buckets; bp < end; bp++) {
|
25
|
+
for (slot = *bp; NULL != slot; slot = slot->next) {
|
26
|
+
if (Qnil != slot->handler) {
|
27
|
+
rb_gc_mark(slot->handler);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
pthread_mutex_unlock(&cc->lock);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
void
|
37
|
+
cc_init(CCache cc) {
|
38
|
+
memset(cc, 0, sizeof(struct _CCache));
|
39
|
+
pthread_mutex_init(&cc->lock, 0);
|
40
|
+
cc->wrap = Data_Wrap_Struct(rb_cObject, cc_mark, NULL, cc);
|
41
|
+
}
|
42
|
+
|
43
|
+
void
|
44
|
+
cc_cleanup(CCache cc) {
|
45
|
+
CSlot *sp = cc->buckets;
|
46
|
+
CSlot s;
|
47
|
+
CSlot n;
|
48
|
+
int i;
|
49
|
+
|
50
|
+
for (i = CC_BUCKET_SIZE; 0 < i; i--, sp++) {
|
51
|
+
for (s = *sp; NULL != s; s = n) {
|
52
|
+
n = s->next;
|
53
|
+
DEBUG_FREE(mem_cslot, s);
|
54
|
+
free(s);
|
55
|
+
}
|
56
|
+
*sp = NULL;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
CSlot
|
61
|
+
cc_set_con(CCache cc, Con con) {
|
62
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & con->id);
|
63
|
+
CSlot slot;
|
64
|
+
|
65
|
+
pthread_mutex_lock(&cc->lock);
|
66
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
67
|
+
if (con->id = slot->cid) {
|
68
|
+
slot->con = con;
|
69
|
+
break;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
if (NULL == slot) {
|
73
|
+
if (NULL != (slot = (CSlot)malloc(sizeof(struct _CSlot)))) {
|
74
|
+
DEBUG_ALLOC(mem_cslot, slot);
|
75
|
+
slot->cid = con->id;
|
76
|
+
slot->con = con;
|
77
|
+
slot->handler = Qnil;
|
78
|
+
slot->on_empty = false;
|
79
|
+
slot->on_close = false;
|
80
|
+
slot->on_shut = false;
|
81
|
+
slot->on_msg = false;
|
82
|
+
atomic_init(&slot->pending, 0);
|
83
|
+
atomic_init(&slot->ref_cnt, 1);
|
84
|
+
slot->next = *bucket;
|
85
|
+
*bucket = slot;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
pthread_mutex_unlock(&cc->lock);
|
89
|
+
|
90
|
+
return slot;
|
91
|
+
}
|
92
|
+
|
93
|
+
void
|
94
|
+
cc_set_handler(CCache cc, uint64_t cid, VALUE handler, bool on_empty, bool on_close, bool on_shut, bool on_msg) {
|
95
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
96
|
+
CSlot slot;
|
97
|
+
|
98
|
+
pthread_mutex_lock(&cc->lock);
|
99
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
100
|
+
if (cid = slot->cid) {
|
101
|
+
slot->handler = handler;
|
102
|
+
break;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
if (NULL == slot) {
|
106
|
+
// TBD is is faster to lock twice or allocate while locked?
|
107
|
+
if (NULL != (slot = (CSlot)malloc(sizeof(struct _CSlot)))) {
|
108
|
+
DEBUG_ALLOC(mem_cslot, slot);
|
109
|
+
slot->cid = cid;
|
110
|
+
slot->con = NULL;
|
111
|
+
slot->handler = handler;
|
112
|
+
slot->on_empty = on_empty;
|
113
|
+
slot->on_close = on_close;
|
114
|
+
slot->on_shut = on_shut;
|
115
|
+
slot->on_msg = on_msg;
|
116
|
+
atomic_init(&slot->pending, 0);
|
117
|
+
atomic_init(&slot->ref_cnt, 1);
|
118
|
+
slot->next = *bucket;
|
119
|
+
slot->on_empty = on_empty;
|
120
|
+
slot->on_close = on_close;
|
121
|
+
slot->on_shut = on_shut;
|
122
|
+
slot->on_msg = on_msg;
|
123
|
+
*bucket = slot;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
pthread_mutex_unlock(&cc->lock);
|
127
|
+
}
|
128
|
+
|
129
|
+
void
|
130
|
+
cc_remove(CCache cc, uint64_t cid) {
|
131
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
132
|
+
CSlot slot;
|
133
|
+
CSlot prev = NULL;
|
134
|
+
|
135
|
+
pthread_mutex_lock(&cc->lock);
|
136
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
137
|
+
if (cid = slot->cid) {
|
138
|
+
if (NULL == prev) {
|
139
|
+
*bucket = slot->next;
|
140
|
+
} else {
|
141
|
+
prev->next = slot->next;
|
142
|
+
}
|
143
|
+
break;
|
144
|
+
}
|
145
|
+
prev = slot;
|
146
|
+
}
|
147
|
+
pthread_mutex_unlock(&cc->lock);
|
148
|
+
if (NULL != slot) {
|
149
|
+
DEBUG_FREE(mem_cslot, slot)
|
150
|
+
free(slot);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
void
|
155
|
+
cc_remove_con(CCache cc, uint64_t cid) {
|
156
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
157
|
+
CSlot slot;
|
158
|
+
CSlot prev = NULL;
|
159
|
+
|
160
|
+
pthread_mutex_lock(&cc->lock);
|
161
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
162
|
+
if (cid = slot->cid) {
|
163
|
+
if (atomic_fetch_sub(&slot->ref_cnt, 1) <= 1) {
|
164
|
+
if (NULL == prev) {
|
165
|
+
*bucket = slot->next;
|
166
|
+
} else {
|
167
|
+
prev->next = slot->next;
|
168
|
+
}
|
169
|
+
} else {
|
170
|
+
atomic_store(&slot->pending, -1);
|
171
|
+
slot = NULL;
|
172
|
+
}
|
173
|
+
break;
|
174
|
+
}
|
175
|
+
prev = slot;
|
176
|
+
}
|
177
|
+
pthread_mutex_unlock(&cc->lock);
|
178
|
+
if (NULL != slot) {
|
179
|
+
DEBUG_FREE(mem_cslot, slot)
|
180
|
+
free(slot);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
VALUE
|
185
|
+
cc_ref_dec(CCache cc, uint64_t cid) {
|
186
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
187
|
+
CSlot slot;
|
188
|
+
VALUE handler = Qnil;
|
189
|
+
CSlot prev = NULL;
|
190
|
+
|
191
|
+
pthread_mutex_lock(&cc->lock);
|
192
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
193
|
+
if (cid = slot->cid) {
|
194
|
+
int rcnt = atomic_fetch_sub(&slot->ref_cnt, 1);
|
195
|
+
|
196
|
+
handler = slot->handler;
|
197
|
+
if (rcnt <= 1) {
|
198
|
+
if (NULL == prev) {
|
199
|
+
*bucket = slot->next;
|
200
|
+
} else {
|
201
|
+
prev->next = slot->next;
|
202
|
+
}
|
203
|
+
} else {
|
204
|
+
slot = NULL;
|
205
|
+
}
|
206
|
+
break;
|
207
|
+
}
|
208
|
+
prev = slot;
|
209
|
+
}
|
210
|
+
pthread_mutex_unlock(&cc->lock);
|
211
|
+
if (NULL != slot) {
|
212
|
+
DEBUG_FREE(mem_cslot, slot)
|
213
|
+
free(slot);
|
214
|
+
}
|
215
|
+
return handler;
|
216
|
+
}
|
217
|
+
|
218
|
+
Con
|
219
|
+
cc_get_con(CCache cc, uint64_t cid) {
|
220
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
221
|
+
CSlot slot;
|
222
|
+
Con con = NULL;
|
223
|
+
|
224
|
+
pthread_mutex_lock(&cc->lock);
|
225
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
226
|
+
if (cid = slot->cid) {
|
227
|
+
con = slot->con;
|
228
|
+
break;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
pthread_mutex_unlock(&cc->lock);
|
232
|
+
|
233
|
+
return con;
|
234
|
+
}
|
235
|
+
|
236
|
+
VALUE
|
237
|
+
cc_get_handler(CCache cc, uint64_t cid) {
|
238
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
239
|
+
CSlot slot;
|
240
|
+
VALUE handler = Qnil;
|
241
|
+
|
242
|
+
pthread_mutex_lock(&cc->lock);
|
243
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
244
|
+
if (cid = slot->cid) {
|
245
|
+
handler = slot->handler;
|
246
|
+
break;
|
247
|
+
}
|
248
|
+
}
|
249
|
+
pthread_mutex_unlock(&cc->lock);
|
250
|
+
|
251
|
+
return handler;
|
252
|
+
}
|
253
|
+
|
254
|
+
int
|
255
|
+
cc_get_pending(CCache cc, uint64_t cid) {
|
256
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
257
|
+
CSlot slot;
|
258
|
+
int pending = -1;
|
259
|
+
|
260
|
+
pthread_mutex_lock(&cc->lock);
|
261
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
262
|
+
if (cid = slot->cid) {
|
263
|
+
pending = atomic_load(&slot->pending);
|
264
|
+
break;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
pthread_mutex_unlock(&cc->lock);
|
268
|
+
|
269
|
+
return pending;
|
270
|
+
}
|
271
|
+
|
272
|
+
CSlot
|
273
|
+
cc_get_slot(CCache cc, uint64_t cid) {
|
274
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
275
|
+
CSlot slot;
|
276
|
+
|
277
|
+
pthread_mutex_lock(&cc->lock);
|
278
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
279
|
+
if (cid = slot->cid) {
|
280
|
+
break;
|
281
|
+
}
|
282
|
+
}
|
283
|
+
pthread_mutex_unlock(&cc->lock);
|
284
|
+
|
285
|
+
return slot;
|
286
|
+
}
|
287
|
+
|
288
|
+
void
|
289
|
+
cc_pending_inc(CCache cc, uint64_t cid) {
|
290
|
+
CSlot *bucket = cc->buckets + (CC_BUCKET_MASK & cid);
|
291
|
+
CSlot slot;
|
292
|
+
|
293
|
+
pthread_mutex_lock(&cc->lock);
|
294
|
+
for (slot = *bucket; NULL != slot; slot = slot->next) {
|
295
|
+
if (cid = slot->cid) {
|
296
|
+
atomic_fetch_add(&slot->pending, 1);
|
297
|
+
break;
|
298
|
+
}
|
299
|
+
}
|
300
|
+
pthread_mutex_unlock(&cc->lock);
|
301
|
+
}
|