eventmachine 1.0.0.beta.4 → 1.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -18,7 +18,7 @@ This unique combination makes EventMachine a premier choice for designers of cri
18
18
  applications, including Web servers and proxies, email and IM production systems, authentication/authorization
19
19
  processors, and many more.
20
20
 
21
- EventMachine has been around since yearly 2000s and is a mature and battle tested library.
21
+ EventMachine has been around since the early 2000s and is a mature and battle tested library.
22
22
 
23
23
 
24
24
  ## What EventMachine is good for? ##
data/Rakefile CHANGED
@@ -1,10 +1,6 @@
1
- require 'rubygems' unless defined?(Gem)
2
- require 'rake' unless defined?(Rake)
3
- import *Dir['tasks/*.rake']
1
+ require 'rubygems'
2
+ GEMSPEC = Gem::Specification.load('eventmachine.gemspec')
4
3
 
5
- GEMSPEC = eval(File.read(File.expand_path('../eventmachine.gemspec', __FILE__)))
6
-
7
- require 'yard'
8
4
  require 'rake/clean'
9
5
  task :clobber => :clean
10
6
 
@@ -12,8 +8,13 @@ desc "Build eventmachine, then run tests."
12
8
  task :default => [:compile, :test]
13
9
 
14
10
  desc 'Generate documentation'
15
- YARD::Rake::YardocTask.new do |t|
16
- t.files = ['lib/**/*.rb', '-', 'docs/*.md']
17
- t.options = ['--main', 'README.md', '--no-private']
18
- t.options = ['--exclude', 'lib/jeventmachine', '--exclude', 'lib/pr_eventmachine']
11
+ begin
12
+ require 'yard'
13
+ YARD::Rake::YardocTask.new do |t|
14
+ t.files = ['lib/**/*.rb', '-', 'docs/*.md']
15
+ t.options = ['--main', 'README.md', '--no-private']
16
+ t.options = ['--exclude', 'lib/jeventmachine', '--exclude', 'lib/pr_eventmachine']
17
+ end
18
+ rescue LoadError
19
+ task :yard do puts "Please install yard first!"; end
19
20
  end
@@ -13,9 +13,9 @@ Gem::Specification.new do |s|
13
13
  s.files = `git ls-files`.split("\n")
14
14
  s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
15
15
 
16
- s.add_development_dependency 'rake-compiler', '0.7.6'
16
+ s.add_development_dependency 'rake-compiler', '0.7.9'
17
17
  s.add_development_dependency 'yard', ">= 0.7.2"
18
- s.add_development_dependency 'bluecloth'
18
+ #s.add_development_dependency 'bluecloth'
19
19
 
20
20
  s.summary = 'Ruby/EventMachine library'
21
21
  s.description = "EventMachine implements a fast, single-threaded engine for arbitrary network
@@ -253,6 +253,15 @@ extern "C" int evma_is_paused (const unsigned long binding)
253
253
  return 0;
254
254
  }
255
255
 
256
+ /************************
257
+ evma_num_close_scheduled
258
+ ************************/
259
+
260
+ extern "C" int evma_num_close_scheduled ()
261
+ {
262
+ return EventMachine->NumCloseScheduled;
263
+ }
264
+
256
265
  /**********************
257
266
  evma_create_tcp_server
258
267
  **********************/
@@ -804,6 +813,35 @@ extern "C" void evma_stop_proxy (const unsigned long from)
804
813
  ed->StopProxy();
805
814
  }
806
815
 
816
+ /******************
817
+ evma_proxied_bytes
818
+ *******************/
819
+
820
+ extern "C" unsigned long evma_proxied_bytes (const unsigned long from)
821
+ {
822
+ ensure_eventmachine("evma_proxied_bytes");
823
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (from));
824
+ if (ed)
825
+ return ed->GetProxiedBytes();
826
+ else
827
+ return 0;
828
+ }
829
+
830
+
831
+ /***************************
832
+ evma_get_last_activity_time
833
+ ****************************/
834
+
835
+ extern "C" uint64_t evma_get_last_activity_time(const unsigned long from)
836
+ {
837
+ ensure_eventmachine("evma_get_last_activity_time");
838
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (from));
839
+ if (ed)
840
+ return ed->GetLastActivity();
841
+ else
842
+ return 0;
843
+ }
844
+
807
845
 
808
846
  /***************************
809
847
  evma_get_heartbeat_interval
data/ext/ed.cpp CHANGED
@@ -54,12 +54,14 @@ EventableDescriptor::EventableDescriptor (int sd, EventMachine_t *em):
54
54
  bCloseNow (false),
55
55
  bCloseAfterWriting (false),
56
56
  MySocket (sd),
57
+ bAttached (false),
57
58
  bWatchOnly (false),
58
59
  EventCallback (NULL),
59
60
  bCallbackUnbind (true),
60
61
  UnbindReasonCode (0),
61
62
  ProxyTarget(NULL),
62
63
  ProxiedFrom(NULL),
64
+ ProxiedBytes(0),
63
65
  MaxOutboundBufSize(0),
64
66
  MyEventMachine (em),
65
67
  PendingConnectTimeout(20000000),
@@ -115,6 +117,7 @@ EventableDescriptor::~EventableDescriptor()
115
117
  (*EventCallback)(ProxiedFrom->GetBinding(), EM_PROXY_TARGET_UNBOUND, NULL, 0);
116
118
  ProxiedFrom->StopProxy();
117
119
  }
120
+ MyEventMachine->NumCloseScheduled--;
118
121
  StopProxy();
119
122
  Close();
120
123
  }
@@ -179,7 +182,7 @@ void EventableDescriptor::Close()
179
182
  MyEventMachine->Deregister (this);
180
183
 
181
184
  // Do not close STDIN, STDOUT, STDERR
182
- if (MySocket > 2 && !bWatchOnly) {
185
+ if (MySocket > 2 && !bAttached) {
183
186
  shutdown (MySocket, 1);
184
187
  close (MySocket);
185
188
  }
@@ -214,6 +217,7 @@ EventableDescriptor::ScheduleClose
214
217
 
215
218
  void EventableDescriptor::ScheduleClose (bool after_writing)
216
219
  {
220
+ MyEventMachine->NumCloseScheduled++;
217
221
  // KEEP THIS SYNCHRONIZED WITH ::IsCloseScheduled.
218
222
  if (after_writing)
219
223
  bCloseAfterWriting = true;
@@ -244,6 +248,7 @@ void EventableDescriptor::StartProxy(const unsigned long to, const unsigned long
244
248
  StopProxy();
245
249
  ProxyTarget = ed;
246
250
  BytesToProxy = length;
251
+ ProxiedBytes = 0;
247
252
  ed->SetProxiedFrom(this, bufsize);
248
253
  return;
249
254
  }
@@ -290,6 +295,7 @@ void EventableDescriptor::_GenericInboundDispatch(const char *buf, int size)
290
295
  if (BytesToProxy > 0) {
291
296
  unsigned long proxied = min(BytesToProxy, (unsigned long) size);
292
297
  ProxyTarget->SendOutboundData(buf, proxied);
298
+ ProxiedBytes += (unsigned long) proxied;
293
299
  BytesToProxy -= proxied;
294
300
  if (BytesToProxy == 0) {
295
301
  StopProxy();
@@ -300,6 +306,7 @@ void EventableDescriptor::_GenericInboundDispatch(const char *buf, int size)
300
306
  }
301
307
  } else {
302
308
  ProxyTarget->SendOutboundData(buf, size);
309
+ ProxiedBytes += (unsigned long) size;
303
310
  }
304
311
  } else {
305
312
  (*EventCallback)(GetBinding(), EM_CONNECTION_READ, buf, size);
@@ -457,6 +464,16 @@ void ConnectionDescriptor::SetConnectPending(bool f)
457
464
  }
458
465
 
459
466
 
467
+ /**********************************
468
+ ConnectionDescriptor::SetAttached
469
+ ***********************************/
470
+
471
+ void ConnectionDescriptor::SetAttached(bool state)
472
+ {
473
+ bAttached = state;
474
+ }
475
+
476
+
460
477
  /**********************************
461
478
  ConnectionDescriptor::SetWatchOnly
462
479
  ***********************************/
data/ext/ed.h CHANGED
@@ -79,6 +79,7 @@ class EventableDescriptor: public Bindable_t
79
79
  virtual int SetCommInactivityTimeout (uint64_t value) {return 0;}
80
80
  uint64_t GetPendingConnectTimeout();
81
81
  int SetPendingConnectTimeout (uint64_t value);
82
+ uint64_t GetLastActivity() { return LastActivity; }
82
83
 
83
84
  #ifdef HAVE_EPOLL
84
85
  struct epoll_event *GetEpollEvent() { return &EpollEvent; }
@@ -86,6 +87,7 @@ class EventableDescriptor: public Bindable_t
86
87
 
87
88
  virtual void StartProxy(const unsigned long, const unsigned long, const unsigned long);
88
89
  virtual void StopProxy();
90
+ virtual unsigned long GetProxiedBytes(){ return ProxiedBytes; };
89
91
  virtual void SetProxiedFrom(EventableDescriptor*, const unsigned long);
90
92
  virtual int SendOutboundData(const char*,int){ return -1; }
91
93
  virtual bool IsPaused(){ return bPaused; }
@@ -103,6 +105,7 @@ class EventableDescriptor: public Bindable_t
103
105
 
104
106
  protected:
105
107
  int MySocket;
108
+ bool bAttached;
106
109
  bool bWatchOnly;
107
110
 
108
111
  EMCallback EventCallback;
@@ -115,6 +118,7 @@ class EventableDescriptor: public Bindable_t
115
118
  unsigned long BytesToProxy;
116
119
  EventableDescriptor *ProxyTarget;
117
120
  EventableDescriptor *ProxiedFrom;
121
+ unsigned long ProxiedBytes;
118
122
 
119
123
  unsigned long MaxOutboundBufSize;
120
124
 
@@ -169,6 +173,7 @@ class ConnectionDescriptor: public EventableDescriptor
169
173
 
170
174
  void SetNotifyReadable (bool);
171
175
  void SetNotifyWritable (bool);
176
+ void SetAttached (bool);
172
177
  void SetWatchOnly (bool);
173
178
 
174
179
  bool Pause();
data/ext/em.cpp CHANGED
@@ -73,6 +73,7 @@ EventMachine_t::EventMachine_t (EMCallback event_callback):
73
73
  NextHeartbeatTime (0),
74
74
  LoopBreakerReader (-1),
75
75
  LoopBreakerWriter (-1),
76
+ NumCloseScheduled (0),
76
77
  bTerminateSignalReceived (false),
77
78
  bEpoll (false),
78
79
  epfd (-1),
@@ -197,10 +198,9 @@ EventMachine_t::SetTimerQuantum
197
198
  void EventMachine_t::SetTimerQuantum (int interval)
198
199
  {
199
200
  /* We get a timer-quantum expressed in milliseconds.
200
- * Don't set a quantum smaller than 5 or larger than 2500.
201
201
  */
202
202
 
203
- if ((interval < 5) || (interval > 2500))
203
+ if ((interval < 5) || (interval > 5*60*1000))
204
204
  throw std::runtime_error ("invalid timer-quantum");
205
205
 
206
206
  Quantum.tv_sec = interval / 1000;
@@ -673,7 +673,13 @@ EventMachine_t::_TimeTilNextEvent
673
673
 
674
674
  timeval EventMachine_t::_TimeTilNextEvent()
675
675
  {
676
+ // 29jul11: Changed calculation base from MyCurrentLoopTime to the
677
+ // real time. As MyCurrentLoopTime is set at the beginning of an
678
+ // iteration and this calculation is done at the end, evenmachine
679
+ // will potentially oversleep by the amount of time the iteration
680
+ // took to execute.
676
681
  uint64_t next_event = 0;
682
+ uint64_t current_time = GetRealTime();
677
683
 
678
684
  if (!Heartbeats.empty()) {
679
685
  multimap<uint64_t,EventableDescriptor*>::iterator heartbeats = Heartbeats.begin();
@@ -687,16 +693,16 @@ timeval EventMachine_t::_TimeTilNextEvent()
687
693
  }
688
694
 
689
695
  if (!NewDescriptors.empty() || !ModifiedDescriptors.empty()) {
690
- next_event = MyCurrentLoopTime;
696
+ next_event = current_time;
691
697
  }
692
-
698
+
693
699
  timeval tv;
694
700
 
695
- if (next_event == 0) {
701
+ if (next_event == 0 || NumCloseScheduled > 0) {
696
702
  tv = Quantum;
697
703
  } else {
698
- if (next_event > MyCurrentLoopTime) {
699
- uint64_t duration = next_event - MyCurrentLoopTime;
704
+ if (next_event > current_time) {
705
+ uint64_t duration = next_event - current_time;
700
706
  tv.tv_sec = duration / 1000000;
701
707
  tv.tv_usec = duration % 1000000;
702
708
  } else {
@@ -1257,7 +1263,7 @@ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
1257
1263
 
1258
1264
  #ifdef OS_WIN32
1259
1265
  throw std::runtime_error ("unix-domain connection unavailable on this platform");
1260
- return NULL;
1266
+ return 0;
1261
1267
  #endif
1262
1268
 
1263
1269
  // The whole rest of this function is only compiled on Unix systems.
@@ -1356,6 +1362,7 @@ const unsigned long EventMachine_t::AttachFD (int fd, bool watch_mode)
1356
1362
  if (!cd)
1357
1363
  throw std::runtime_error ("no connection allocated");
1358
1364
 
1365
+ cd->SetAttached(true);
1359
1366
  cd->SetWatchOnly(watch_mode);
1360
1367
  cd->SetConnectPending (false);
1361
1368
 
@@ -1395,7 +1402,11 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1395
1402
  if (bKqueue) {
1396
1403
  // remove any read/write events for this fd
1397
1404
  struct kevent k;
1405
+ #ifdef __NetBSD__
1406
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t)ed);
1407
+ #else
1398
1408
  EV_SET (&k, ed->GetSocket(), EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, ed);
1409
+ #endif
1399
1410
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1400
1411
  if (t < 0 && (errno != ENOENT) && (errno != EBADF)) {
1401
1412
  char buf [200];
@@ -1651,7 +1662,11 @@ void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed)
1651
1662
  if (!ed)
1652
1663
  throw std::runtime_error ("added bad descriptor");
1653
1664
  struct kevent k;
1665
+ #ifdef __NetBSD__
1666
+ EV_SET (&k, ed->GetSocket(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, (intptr_t)ed);
1667
+ #else
1654
1668
  EV_SET (&k, ed->GetSocket(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, ed);
1669
+ #endif
1655
1670
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1656
1671
  if (t < 0) {
1657
1672
  char buf [200];
@@ -1673,7 +1688,11 @@ void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed)
1673
1688
  if (!ed)
1674
1689
  throw std::runtime_error ("added bad descriptor");
1675
1690
  struct kevent k;
1691
+ #ifdef __NetBSD__
1692
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, (intptr_t)ed);
1693
+ #else
1676
1694
  EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1695
+ #endif
1677
1696
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1678
1697
  if (t < 0) {
1679
1698
  char buf [200];
@@ -1724,7 +1743,11 @@ void EventMachine_t::_AddNewDescriptors()
1724
1743
  // INCOMPLETE. Some descriptors don't want to be readable.
1725
1744
  assert (kqfd != -1);
1726
1745
  struct kevent k;
1746
+ #ifdef __NetBSD__
1747
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, (intptr_t)ed);
1748
+ #else
1727
1749
  EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1750
+ #endif
1728
1751
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1729
1752
  assert (t == 0);
1730
1753
  }
data/ext/em.h CHANGED
@@ -44,10 +44,10 @@ See the file COPYING for complete licensing information.
44
44
  #define RUBY_UBF_IO RB_UBF_DFL
45
45
  #endif
46
46
  #ifndef RSTRING_PTR
47
- #define RSTRING_PTR(str) RString(str)->ptr
47
+ #define RSTRING_PTR(str) RSTRING(str)->ptr
48
48
  #endif
49
49
  #ifndef RSTRING_LEN
50
- #define RSTRING_LEN(str) RString(str)->len
50
+ #define RSTRING_LEN(str) RSTRING(str)->len
51
51
  #endif
52
52
  #ifndef RSTRING_LENINT
53
53
  #define RSTRING_LENINT(str) RSTRING_LEN(str)
@@ -161,6 +161,7 @@ class EventMachine_t
161
161
  public:
162
162
  void _ReadLoopBreaker();
163
163
  void _ReadInotifyEvents();
164
+ int NumCloseScheduled;
164
165
 
165
166
  private:
166
167
  enum {
@@ -59,6 +59,8 @@ extern "C" {
59
59
  int evma_is_paused(const unsigned long binding);
60
60
  int evma_resume(const unsigned long binding);
61
61
 
62
+ int evma_num_close_scheduled();
63
+
62
64
  void evma_stop_tcp_server (const unsigned long signature);
63
65
  const unsigned long evma_create_tcp_server (const char *address, int port);
64
66
  const unsigned long evma_create_unix_domain_server (const char *filename);
@@ -84,6 +86,7 @@ extern "C" {
84
86
  float evma_get_pending_connect_timeout (const unsigned long binding);
85
87
  int evma_set_pending_connect_timeout (const unsigned long binding, float value);
86
88
  int evma_get_outbound_data_size (const unsigned long binding);
89
+ uint64_t evma_get_last_activity_time (const unsigned long);
87
90
  int evma_send_file_data_to_connection (const unsigned long binding, const char *filename);
88
91
 
89
92
  void evma_close_connection (const unsigned long binding, int after_writing);
@@ -107,6 +110,7 @@ extern "C" {
107
110
 
108
111
  void evma_start_proxy(const unsigned long, const unsigned long, const unsigned long, const unsigned long);
109
112
  void evma_stop_proxy(const unsigned long);
113
+ unsigned long evma_proxied_bytes(const unsigned long);
110
114
 
111
115
  int evma_set_rlimit_nofile (int n_files);
112
116
 
@@ -25,7 +25,7 @@ end
25
25
  def manual_ssl_config
26
26
  ssl_libs_heads_args = {
27
27
  :unix => [%w[ssl crypto], %w[openssl/ssl.h openssl/err.h]],
28
- :mswin => [%w[ssleay32 libeay32], %w[openssl/ssl.h openssl/err.h]],
28
+ :mswin => [%w[ssleay32 eay32], %w[openssl/ssl.h openssl/err.h]],
29
29
  }
30
30
 
31
31
  dc_flags = ['ssl']
@@ -57,7 +57,7 @@ if ENV['CROSS_COMPILING']
57
57
  end
58
58
 
59
59
  # Try to use pkg_config first, fixes #73
60
- if pkg_config('openssl') || manual_ssl_config
60
+ if (!ENV['CROSS_COMPILING'] and pkg_config('openssl')) || manual_ssl_config
61
61
  add_define "WITH_SSL"
62
62
  else
63
63
  add_define "WITHOUT_SSL"
@@ -76,7 +76,7 @@ have_func('rb_time_new')
76
76
  # Minor platform details between *nix and Windows:
77
77
 
78
78
  if RUBY_PLATFORM =~ /(mswin|mingw|bccwin)/
79
- GNU_CHAIN = $1 == 'mingw'
79
+ GNU_CHAIN = ENV['CROSS_COMPILING'] or $1 == 'mingw'
80
80
  OS_WIN32 = true
81
81
  add_define "OS_WIN32"
82
82
  else
@@ -139,6 +139,15 @@ when /linux/
139
139
  when /aix/
140
140
  CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G -Wl,-brtl"
141
141
 
142
+ when /cygwin/
143
+ # For rubies built with Cygwin, CXX may be set to CC, which is just
144
+ # a wrapper for gcc.
145
+ # This will compile, but it will not link to the C++ std library.
146
+ # Explicitly set CXX to use g++.
147
+ CONFIG['CXX'] = "g++"
148
+ # on Unix we need a g++ link, not gcc.
149
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
150
+
142
151
  else
143
152
  # on Unix we need a g++ link, not gcc.
144
153
  CONFIG['LDSHARED'] = "$(CXX) -shared"
@@ -17,7 +17,7 @@ add_define 'BUILD_FOR_RUBY'
17
17
  # Minor platform details between *nix and Windows:
18
18
 
19
19
  if RUBY_PLATFORM =~ /(mswin|mingw|bccwin)/
20
- GNU_CHAIN = $1 == 'mingw'
20
+ GNU_CHAIN = ENV['CROSS_COMPILING'] or $1 == 'mingw'
21
21
  OS_WIN32 = true
22
22
  add_define "OS_WIN32"
23
23
  else
@@ -77,6 +77,15 @@ when /aix/
77
77
  # on Unix we need a g++ link, not gcc.
78
78
  CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G"
79
79
 
80
+ when /cygwin/
81
+ # For rubies built with Cygwin, CXX may be set to CC, which is just
82
+ # a wrapper for gcc.
83
+ # This will compile, but it will not link to the C++ std library.
84
+ # Explicitly set CXX to use g++.
85
+ CONFIG['CXX'] = "g++"
86
+ # on Unix we need a g++ link, not gcc.
87
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
88
+
80
89
  else
81
90
  # on Unix we need a g++ link, not gcc.
82
91
  CONFIG['LDSHARED'] = "$(CXX) -shared"