event_machine_flush 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.0.2 2010-04-26
2
+
3
+ * Flush all pages, don't die if none.
4
+ * Stop when no more data can be written.
5
+
1
6
  == 0.0.1 2010-04-22
2
7
 
3
8
  * Hi.
@@ -1,11 +1,116 @@
1
1
  #include "ruby.h"
2
2
  #include "project.h"
3
3
 
4
+
5
+ static void push_back_data(ConnectionDescriptor *ed, char *data, int len) {
6
+ char *buffer = (char*)malloc(len + 1);
7
+ if (!buffer)
8
+ throw std::runtime_error("bad alloc throwing back data");
9
+ memcpy(buffer, data, len);
10
+ buffer[len] = 0;
11
+ ed->OutboundPages.push_front(ConnectionDescriptor::OutboundPage(buffer, len));
12
+ }
13
+
4
14
  extern "C" {
5
15
  VALUE EventMachineFlush_flush(VALUE self, VALUE connection) {
6
16
  unsigned long signature = NUM2ULONG(rb_iv_get(connection, "@signature"));
7
17
  ConnectionDescriptor *ed = dynamic_cast<ConnectionDescriptor*>(Bindable_t::GetObject(signature));
8
- ed->Write();
18
+
19
+ // Based on ConnectionDescriptor::_WriteOutboundData.
20
+ while (ed->OutboundPages.size() > 0) {
21
+ int sd = ed->GetSocket();
22
+
23
+ if (sd == INVALID_SOCKET)
24
+ break;
25
+
26
+ size_t nbytes = 0;
27
+ #ifdef HAVE_WRITEV
28
+ int iovcnt = ed->OutboundPages.size();
29
+ if (iovcnt > 16) iovcnt = 16;
30
+
31
+ # ifdef CC_SUNWspro
32
+ struct iovec iov[16];
33
+ # else
34
+ struct iovec iov[iovcnt];
35
+ # endif
36
+
37
+ for(int i = 0; i < iovcnt; i++){
38
+ ConnectionDescriptor::OutboundPage *op = &(ed->OutboundPages[i]);
39
+ # ifdef CC_SUNWspro
40
+ iov[i].iov_base = (char *)(op->Buffer + op->Offset);
41
+ # else
42
+ iov[i].iov_base = (void *)(op->Buffer + op->Offset);
43
+ # endif
44
+ iov[i].iov_len = op->Length - op->Offset;
45
+
46
+ nbytes += iov[i].iov_len;
47
+ }
48
+ #else
49
+ char output_buffer[16 * 1024];
50
+
51
+ while ((ed->OutboundPages.size() > 0) && (nbytes < sizeof(output_buffer))) {
52
+ ConnectionDescriptor::OutboundPage *op = &(OutboundPages[0]);
53
+ if ((nbytes + op->Length - op->Offset) < sizeof(output_buffer)) {
54
+ memcpy(output_buffer + nbytes, op->Buffer + op->Offset, op->Length - op->Offset);
55
+ nbytes += (op->Length - op->Offset);
56
+ op->Free();
57
+ ed->OutboundPages.pop_front();
58
+ } else {
59
+ int len = sizeof(output_buffer) - nbytes;
60
+ memcpy(output_buffer + nbytes, op->Buffer + op->Offset, len);
61
+ op->Offset += len;
62
+ nbytes += len;
63
+ }
64
+ }
65
+ #endif
66
+
67
+ // Noop if only empty pages have been queued.
68
+ if (nbytes == 0)
69
+ break;
70
+
71
+ #ifdef HAVE_WRITEV
72
+ int bytes_written = writev(ed->GetSocket(), iov, iovcnt);
73
+ #else
74
+ int bytes_written = write(ed->GetSocket(), output_buffer, nbytes);
75
+ #endif
76
+
77
+ // Noop if we couldn't write. Since we didn't select on the
78
+ // socket, it mightn't be writable.
79
+ if (bytes_written <= 0) {
80
+ #ifndef HAVE_WRITEV
81
+ push_back_data(ed, output_buffer, nbytes);
82
+ #endif
83
+ break;
84
+ }
85
+ ed->OutboundDataSize -= bytes_written;
86
+
87
+ #ifdef HAVE_WRITEV
88
+ unsigned int sent = bytes_written;
89
+ deque<ConnectionDescriptor::OutboundPage>::iterator op = ed->OutboundPages.begin();
90
+
91
+ for (int i = 0; i < iovcnt; i++) {
92
+ if (iov[i].iov_len <= sent) {
93
+ // Sent this page in full, free it.
94
+ op->Free();
95
+ ed->OutboundPages.pop_front();
96
+
97
+ sent -= iov[i].iov_len;
98
+ } else {
99
+ // Sent part (or none) of this page, increment offset to send the remainder
100
+ op->Offset += sent;
101
+ break;
102
+ }
103
+
104
+ // Shouldn't be possible run out of pages before the loop ends
105
+ assert(op != ed->OutboundPages.end());
106
+ *op++;
107
+ }
108
+ #else
109
+ if ((size_t)bytes_written < nbytes)
110
+ push_back_data(ed, output_buffer + bytes_written, nbytes - bytes_written);
111
+ #endif
112
+ }
113
+
9
114
  return Qnil;
10
115
  }
11
116
 
data/ext/extconf.rb CHANGED
@@ -5,16 +5,17 @@ require 'rubygems'
5
5
  specs = Gem.source_index.find_name('eventmachine')
6
6
  specs.size > 0 or
7
7
  abort "can't find eventmachine gem"
8
- @event_machine_path = specs.first.full_gem_path
8
+ event_machine_path = specs.first.full_gem_path
9
9
 
10
10
  # Stub out create_makefile and load EventMachine's extconf.rb. This
11
11
  # ensures our build environment matches.
12
12
  require 'mkmf'
13
13
  alias original_create_makefile create_makefile
14
14
  def create_makefile(*) end
15
- require "#@event_machine_path/ext/extconf.rb"
15
+ require "#{event_machine_path}/ext/extconf.rb"
16
16
  alias create_makefile original_create_makefile
17
17
 
18
18
  # Create our makefile.
19
- $INCFLAGS << " -I#@event_machine_path/ext"
19
+ $CPPFLAGS << " -Dprivate=public -Dprotected=public"
20
+ $INCFLAGS << " -I#{event_machine_path}/ext"
20
21
  create_makefile "event_machine_flush_ext"
@@ -1,3 +1,11 @@
1
1
  module EventMachineFlush
2
- VERSION = [0, 0, 1]
2
+ VERSION = [0, 0, 2]
3
+
4
+ class << VERSION
5
+ include Comparable
6
+
7
+ def to_s
8
+ join('.')
9
+ end
10
+ end
3
11
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - George Ogata
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-22 00:00:00 -04:00
17
+ date: 2010-04-26 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency