event_machine_flush 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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