public
Description: A very fast & simple Ruby web server
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin.git
Search Repo:
Refactor all buffer logic into buffer.c
macournoyer (author)
Mon Apr 07 18:48:31 -0700 2008
commit  6965f98d4ee6d29529dedda0974b327736ed0dc4
tree    861338344d725969e8a92f81478441bf7f91ee3e
parent  c9e64894ddd0f67cc5636924f710433d287d2ccf
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
0
@@ -1 +1,49 @@
0
+#include "buffer.h"
0
+
0
+void buffer_init(buffer_t *buf, pool_t *p)
0
+{
0
+ buf->pool = p;
0
+ buf->ptr = palloc(p, 1);
0
+ assert(buf->ptr);
0
+ buf->nalloc = 1;
0
+ buf->salloc = p->size;
0
+ buf->len = 0;
0
+ buf->current = 0;
0
+}
0
+
0
+void buffer_free(buffer_t *buf)
0
+{
0
+ if (buf->ptr != NULL)
0
+ pfree(buf->pool, buf->ptr);
0
+ buf->salloc = 0;
0
+ buf->nalloc = 0;
0
+}
0
+
0
+static inline void buffer_grow(buffer_t *buf, size_t size)
0
+{
0
+ char *new, *old;
0
+
0
+ /* TODO store big body in tempfile */
0
+ /* TODO if last alloc, just alloc next block */
0
+ old = buf->ptr;
0
+ new = (char *) palloc(buf->pool, buf->nalloc + 1);
0
+ assert(new);
0
+
0
+ memcpy(new, old, buf->len);
0
+
0
+ buf->ptr = new;
0
+ buf->nalloc ++;
0
+ buf->salloc += buf->pool->size;
0
+ pfree(buf->pool, old);
0
+}
0
+
0
+void buffer_append(buffer_t *buf, const char *ptr, size_t len)
0
+{
0
+ /* alloc more mem when buffer full */
0
+ if (buf->len >= buf->salloc)
0
+ buffer_grow(buf, len);
0
+
0
+ memcpy(buf->ptr + buf->len, ptr, len);
0
+ buf->len += len;
0
+}
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0
@@ -1 +1,22 @@
0
+#ifndef _BUFFER_H_
0
+#define _BUFFER_H_
0
+
0
+#include "palloc.h"
0
+
0
+typedef struct buffer_s buffer_t;
0
+
0
+struct buffer_s {
0
+ size_t nalloc; /* num slices alloced */
0
+ size_t salloc; /* total size alloced */
0
+ size_t len;
0
+ size_t current;
0
+ pool_t *pool;
0
+ char *ptr;
0
+};
0
+
0
+void buffer_init(buffer_t *buf, pool_t *p);
0
+void buffer_free(buffer_t *buf);
0
+void buffer_append(buffer_t *buf, const char *ptr, size_t len);
0
+
0
+#endif /* _BUFFER_H_ */
...
100
101
102
103
104
105
106
107
108
 
 
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
 
158
159
160
161
162
163
164
165
...
219
220
221
222
223
224
225
 
226
227
228
229
...
231
232
233
234
235
 
 
236
237
238
239
240
241
242
...
275
276
277
278
279
280
281
282
283
284
285
286
 
 
287
288
289
...
100
101
102
 
 
 
 
 
 
103
104
105
106
107
108
109
110
 
 
 
 
 
 
 
 
111
112
113
114
...
125
126
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
129
 
 
 
130
131
132
133
...
187
188
189
 
190
 
 
191
192
193
194
195
...
197
198
199
 
 
200
201
202
 
 
 
203
204
205
...
238
239
240
 
 
 
 
 
 
 
 
 
241
242
243
244
245
0
@@ -100,26 +100,14 @@
0
   rb_gc_register_address(&c->env);
0
   
0
   /* alloc read buffer from pool */
0
- c->read_buffer.ptr = palloc(c->buffer_pool, 1);
0
- assert(c->read_buffer.ptr);
0
- c->read_buffer.nalloc = 1;
0
- c->read_buffer.salloc = c->buffer_pool->size;
0
- c->read_buffer.len = 0;
0
- c->read_buffer.current = 0;
0
+ buffer_init(&c->read_buffer, c->buffer_pool);
0
+ buffer_init(&c->write_buffer, c->buffer_pool);
0
   
0
   /* assign env[rack.input] */
0
   c->input = input_new(&c->read_buffer);
0
   rb_gc_register_address(&c->input);
0
   rb_hash_aset(c->env, sRackInput, c->input);
0
   
0
- /* alloc write buffer from pool */
0
- c->write_buffer.ptr = palloc(c->buffer_pool, 1);
0
- assert(c->write_buffer.ptr);
0
- c->write_buffer.nalloc = 1;
0
- c->write_buffer.salloc = c->buffer_pool->size;
0
- c->write_buffer.len = 0;
0
- c->write_buffer.current = 0;
0
-
0
   /* reinit parser */
0
   http_parser_init(&c->parser);
0
   c->parser.data = c;
0
0
@@ -137,28 +125,8 @@
0
     return;
0
   }
0
   
0
- /* alloc more mem when buffer full */
0
- /* TODO extract this into buffer.c and optimize */
0
- /* TODO store big body in tempfile */
0
- if (c->read_buffer.len >= c->read_buffer.salloc) {
0
- char *new, *old;
0
-
0
- /* TODO if last alloc, just alloc next block */
0
- old = c->read_buffer.ptr;
0
- new = (char *) palloc(c->buffer_pool, c->read_buffer.nalloc + 1);
0
- assert(new);
0
-
0
- memcpy(new, old, c->read_buffer.len);
0
-
0
- c->read_buffer.ptr = new;
0
- c->read_buffer.nalloc ++;
0
- c->read_buffer.salloc += c->buffer_pool->size;
0
- pfree(c->buffer_pool, old);
0
- }
0
+ buffer_append(&c->read_buffer, buf, len);
0
   
0
- memcpy(c->read_buffer.ptr + c->read_buffer.len, buf, len);
0
- c->read_buffer.len += len;
0
-
0
   if (!http_parser_is_finished(&c->parser)) {
0
     /* header not all received, we continue parsing ... */
0
     
0
0
@@ -219,10 +187,8 @@
0
 static VALUE iter_body(VALUE chunk, VALUE *val_conn)
0
 {
0
   connection_t *c = (connection_t *) val_conn;
0
- size_t len = RSTRING_LEN(chunk);
0
   
0
- memcpy(c->write_buffer.ptr + c->write_buffer.len, RSTRING_PTR(chunk), len);
0
- c->write_buffer.len += len;
0
+ buffer_append(&c->write_buffer, RSTRING_PTR(chunk), RSTRING_LEN(chunk));
0
   
0
   return Qnil;
0
 }
0
0
@@ -231,12 +197,9 @@
0
 {
0
   if (TYPE(body) == T_STRING) {
0
     /* Calling String#each creates several other strings which is slower and use more mem,
0
- * also Ruby 1.9 doesn't define that method anymore, so it's better to send one big string. */
0
- size_t len = RSTRING_LEN(body);
0
+ * also Ruby 1.9 doesn't define that method anymore, so it's better to send one big string. */
0
+ buffer_append(&c->write_buffer, RSTRING_PTR(body), RSTRING_LEN(body));
0
     
0
- memcpy(c->write_buffer.ptr + c->write_buffer.len, RSTRING_PTR(body), len);
0
- c->write_buffer.len += len;
0
-
0
   } else {
0
     /* Iterate over body#each and send each yielded chunk */
0
     rb_iterate(rb_each, body, iter_body, (VALUE) c);
0
@@ -275,15 +238,8 @@
0
 
0
   close(c->fd);
0
   
0
- if (c->read_buffer.ptr != NULL)
0
- pfree(c->buffer_pool, c->read_buffer.ptr);
0
- c->read_buffer.salloc = 0;
0
- c->read_buffer.nalloc = 0;
0
-
0
- if (c->write_buffer.ptr != NULL)
0
- pfree(c->buffer_pool, c->write_buffer.ptr);
0
- c->write_buffer.salloc = 0;
0
- c->write_buffer.nalloc = 0;
0
+ buffer_free(&c->read_buffer);
0
+ buffer_free(&c->write_buffer);
0
   
0
   /* tell Ruby GC vars are not used anymore */
0
   rb_gc_unregister_address(&c->env);
...
32
33
34
35
 
36
37
38
 
...
32
33
34
 
35
36
37
 
38
0
@@ -32,8 +32,8 @@
0
 $CFLAGS << " -I#{libev_dir} " << flags.join(' ')
0
 $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
0
 
0
-dir_config("backend")
0
+dir_config("thin_backend")
0
 have_library("c", "main")
0
 
0
-create_makefile("backend")
0
+create_makefile("thin_backend")
...
1
2
3
 
4
5
6
...
1
2
 
3
4
5
6
0
@@ -1,6 +1,6 @@
0
 #include "thin.h"
0
 
0
-void Init__backend()
0
+void Init_thin_backend()
0
 {
0
   /* Initialize internal stuff */
0
   backend_define();
...
1
 
2
3
4
...
 
1
2
3
4
0
@@ -1,4 +1,4 @@
0
-require 'backend'
0
+require 'thin_backend'
0
 
0
 class Thin::Backend
0
   def start
...
20
21
22
 
23
24
25
26
...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
...
20
21
22
23
24
25
26
27
...
41
42
43
 
44
 
 
 
 
 
 
 
 
45
46
47
0
@@ -20,6 +20,7 @@
0
 #include "ruby.h"
0
 #include "ext_help.h"
0
 #include "array.h"
0
+#include "buffer.h"
0
 #include "palloc.h"
0
 #include "parser.h"
0
 #include "status.h"
0
0
@@ -40,16 +41,7 @@
0
 #define CRLF "\x0d\x0a"
0
 
0
 typedef struct backend_s backend_t;
0
-typedef struct buffer_s buffer_t;
0
 typedef struct connection_s connection_t;
0
-
0
-struct buffer_s {
0
- size_t nalloc; /* num slices alloced */
0
- size_t salloc; /* total size alloced */
0
- size_t len;
0
- size_t current;
0
- char *ptr;
0
-};
0
 
0
 struct connection_s {
0
   /* socket */

Comments

    No one has commented yet.