isomorfeus-iodine 0.8.0 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -27,7 +27,6 @@ task :push do
27
27
  system("git push github")
28
28
  system("git push gitlab")
29
29
  system("git push bitbucket")
30
- system("git push gitprep")
31
30
  end
32
31
 
33
32
  task :default => [:compile, :spec]
data/examples/config.ru CHANGED
@@ -1,56 +1,59 @@
1
- # This is a WebSocket / SSE notification broadcasting application.
2
- #
3
- # Running this application from the command line is easy with:
4
- #
5
- # iodine
6
- #
7
- # Or, in single thread and single process:
8
- #
9
- # iodine -t 1 -w 1
10
- #
11
- # Benchmark with `ab` or `wrk` (a 5 seconds benchmark with 2000 concurrent clients):
12
- #
13
- # ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
14
- # wrk -c2000 -d5 -t12 http://localhost:3000/
15
-
16
-
17
- # A simple router - Checks for Websocket Upgrade and answers HTTP.
18
- module MyHTTPRouter
19
- # This is the HTTP response object according to the Rack specification.
20
- HTTP_RESPONSE = [200, { 'Content-Type' => 'text/html',
21
- 'Content-Length' => '77' },
22
- ['Please connect using WebSockets or SSE (send messages only using WebSockets).']]
23
-
24
- WS_RESPONSE = [0, {}, []].freeze
25
-
26
- # this is function will be called by the Rack server (iodine) for every request.
27
- def self.call env
28
- # check if this is an upgrade request (WebsSocket / SSE).
29
- if(env['rack.upgrade?'.freeze])
30
- env['rack.upgrade'.freeze] = BroadcastClient
31
- return WS_RESPONSE
32
- end
33
- # simply return the RESPONSE object, no matter what request was received.
34
- HTTP_RESPONSE
35
- end
36
- end
37
-
38
- # A simple Websocket Callback Object.
39
- module BroadcastClient
40
- # seng a message to new clients.
41
- def on_open client
42
- client.subscribe :broadcast
43
- end
44
- # send a message, letting the client know the server is suggunt down.
45
- def on_shutdown client
46
- client.write "Server shutting down. Goodbye."
47
- end
48
- # perform the echo
49
- def on_message client, data
50
- client.publish :broadcast, data
51
- end
52
- extend self
53
- end
54
-
55
- # this function call links our HelloWorld application with Rack
56
- run MyHTTPRouter
1
+ # This is a WebSocket / SSE notification broadcasting application.
2
+ #
3
+ # Running this application from the command line is easy with:
4
+ #
5
+ # iodine
6
+ #
7
+ # Or, in single thread and single process:
8
+ #
9
+ # iodine -t 1 -w 1
10
+ #
11
+ # Benchmark with `ab` or `wrk` (a 5 seconds benchmark with 2000 concurrent clients):
12
+ #
13
+ # ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
14
+ # wrk -c2000 -d5 -t12 http://localhost:3000/
15
+ #
16
+ # Test websocket echo using the browser. For example:
17
+ # ws = new WebSocket("ws://localhost:3000"); ws.onmessage = function(e) {console.log("Got message!"); console.log(e.data);}; ws.onclose = function(e) {console.log("closed")}; ws.onopen = function(e) {ws.send("hi");};
18
+
19
+
20
+ # A simple router - Checks for Websocket Upgrade and answers HTTP.
21
+ module MyHTTPRouter
22
+ # This is the HTTP response object according to the Rack specification.
23
+ HTTP_RESPONSE = [200, { 'Content-Type' => 'text/html',
24
+ 'Content-Length' => '77' },
25
+ ['Please connect using WebSockets or SSE (send messages only using WebSockets).']]
26
+
27
+ WS_RESPONSE = [0, {}, []].freeze
28
+
29
+ # this is function will be called by the Rack server (iodine) for every request.
30
+ def self.call env
31
+ # check if this is an upgrade request (WebsSocket / SSE).
32
+ if(env['rack.upgrade?'.freeze])
33
+ env['rack.upgrade'.freeze] = BroadcastClient
34
+ return WS_RESPONSE
35
+ end
36
+ # simply return the RESPONSE object, no matter what request was received.
37
+ HTTP_RESPONSE
38
+ end
39
+ end
40
+
41
+ # A simple Websocket Callback Object.
42
+ module BroadcastClient
43
+ # seng a message to new clients.
44
+ def on_open client
45
+ client.subscribe :broadcast
46
+ end
47
+ # send a message, letting the client know the server is suggunt down.
48
+ def on_shutdown client
49
+ client.write "Server shutting down. Goodbye."
50
+ end
51
+ # perform the echo
52
+ def on_message client, data
53
+ client.publish :broadcast, data
54
+ end
55
+ extend self
56
+ end
57
+
58
+ # this function call links our HelloWorld application with Rack
59
+ run MyHTTPRouter
data/examples/rack3.ru ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ # adjusted from the code suggested by @taku0 (GitHub issue #131)
4
+ require 'rack'
5
+ require 'iodine'
6
+
7
+ run { |env|
8
+ response = Rack::Response.new(nil, 204)
9
+ response.set_cookie('aaa', 'aaa')
10
+ response.set_cookie('bbb', 'bbb')
11
+ response.finish
12
+ }
data/exe/iodine CHANGED
@@ -1,64 +1,64 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
- IODINE_PARSE_CLI = true
4
- require 'iodine'
5
-
6
- # Load Rack if available (assume it will be used)
7
-
8
- require 'rack'
9
-
10
- module Iodine
11
- # The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
12
- module Base
13
- # Command line interface. The Ruby CLI might be changed in future versions.
14
- module CLI
15
-
16
- def self.try_file filename
17
- return nil unless File.exist? filename
18
- ::Rack::Builder.parse_file filename
19
- end
20
-
21
- def self.get_app
22
- app = nil
23
- filename = Iodine::DEFAULT_SETTINGS[:filename_]
24
- if filename
25
- app = try_file filename
26
- app = try_file "#{filename}.ru" unless app
27
- unless app
28
- puts "* Couldn't find #{filename}\n testing for config.ru\n"
29
- app = try_file "config.ru"
30
- end
31
- else
32
- app = try_file "config.ru";
33
- end
34
- app
35
- end
36
-
37
- def self.perform_warmup(app)
38
- # load anything marked with `autoload`, since autoload is niether thread safe nor fork friendly.
39
- Iodine.on_state(:on_start) do
40
- Module.constants.each do |n|
41
- begin
42
- Object.const_get(n)
43
- rescue StandardError => _e
44
- end
45
- end
46
- ::Rack::Builder.new(app) do |r|
47
- r.warmup do |a|
48
- client = ::Rack::MockRequest.new(a)
49
- client.get('/')
50
- end
51
- end
52
- end
53
- end
54
-
55
- def self.call
56
- app = get_app
57
- perform_warmup(app) if Iodine::DEFAULT_SETTINGS[:warmup_]
58
- Iodine::Rack.run(app)
59
- end
60
- end
61
- end
62
- end
63
-
64
- Iodine::Base::CLI.call
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ IODINE_PARSE_CLI = true
4
+ require 'iodine'
5
+
6
+ # Load Rack if available (assume it will be used)
7
+
8
+ require 'rack'
9
+
10
+ module Iodine
11
+ # The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
12
+ module Base
13
+ # Command line interface. The Ruby CLI might be changed in future versions.
14
+ module CLI
15
+
16
+ def self.try_file filename
17
+ return nil unless File.exist? filename
18
+ ::Rack::Builder.parse_file filename
19
+ end
20
+
21
+ def self.get_app
22
+ app = nil
23
+ filename = Iodine::DEFAULT_SETTINGS[:filename_]
24
+ if filename
25
+ app = try_file filename
26
+ app = try_file "#{filename}.ru" unless app
27
+ unless app
28
+ puts "* Couldn't find #{filename}\n testing for config.ru\n"
29
+ app = try_file "config.ru"
30
+ end
31
+ else
32
+ app = try_file "config.ru";
33
+ end
34
+ app
35
+ end
36
+
37
+ def self.perform_warmup(app)
38
+ # load anything marked with `autoload`, since autoload is niether thread safe nor fork friendly.
39
+ Iodine.on_state(:on_start) do
40
+ Module.constants.each do |n|
41
+ begin
42
+ Object.const_get(n)
43
+ rescue StandardError => _e
44
+ end
45
+ end
46
+ ::Rack::Builder.new(app) do |r|
47
+ r.warmup do |a|
48
+ client = ::Rack::MockRequest.new(a)
49
+ client.get('/')
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def self.call
56
+ app = get_app
57
+ perform_warmup(app) if Iodine::DEFAULT_SETTINGS[:warmup_]
58
+ Iodine::Rack.run(app)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ Iodine::Base::CLI.call
@@ -1,4 +1,5 @@
1
1
  require 'mkmf'
2
+ require 'fileutils'
2
3
 
3
4
  WIN_PATTERNS = [
4
5
  /bccwin/i,
data/ext/iodine_ext/fio.c CHANGED
@@ -155,7 +155,7 @@ int ioctl (int fd, u_long request, int* argp) {
155
155
  else { return 0; }
156
156
  }
157
157
 
158
- int kill(int pid, int sig) {
158
+ int fio_kill(int pid, int sig) {
159
159
  /* Credit to Jan Biedermann (GitHub: @janbiedermann) */
160
160
  HANDLE handle;
161
161
  DWORD status;
@@ -987,7 +987,7 @@ FIO_FUNC void fio_thread_signal(void) {
987
987
  (void)r;
988
988
  } else if (fd == -1) {
989
989
  /* hardly the best way, but there's a thread sleeping on air */
990
- kill(getpid(), SIGCONT);
990
+ fio_kill(getpid(), SIGCONT);
991
991
  }
992
992
  #endif
993
993
  }
@@ -1025,7 +1025,7 @@ static void fio_defer_thread_wait(void) {
1025
1025
  if (fio_defer_has_queue())
1026
1026
  pthread_setspecific(static_throttle_key, (void *)1);
1027
1027
  else if (static_throttle < FIO_DEFER_THROTTLE_LIMIT)
1028
- pthread_setspecific(static_throttle_key, (void *)(static_throttle << 1));
1028
+ pthread_setspecific(static_throttle_key, (void *)((static_throttle << 1) | 1));
1029
1029
  }
1030
1030
  }
1031
1031
 
@@ -1654,7 +1654,7 @@ void fio_reap_children(void) {
1654
1654
  sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
1655
1655
  if (sigaction(SIGCHLD, &sa, &fio_old_sig_chld) == -1) {
1656
1656
  perror("Child reaping initialization failed");
1657
- kill(0, SIGINT);
1657
+ fio_kill(0, SIGINT);
1658
1658
  exit(errno);
1659
1659
  }
1660
1660
  }
@@ -3689,7 +3689,8 @@ closed:
3689
3689
  return -1;
3690
3690
 
3691
3691
  flush_rw_hook:
3692
- flushed = uuid_data(uuid).rw_hooks->flush(uuid, uuid_data(uuid).rw_udata);
3692
+ if(uuid_data(uuid).rw_hooks)
3693
+ flushed = uuid_data(uuid).rw_hooks->flush(uuid, uuid_data(uuid).rw_udata);
3693
3694
  fio_unlock(&uuid_data(uuid).sock_lock);
3694
3695
  if (!flushed)
3695
3696
  return 0;
@@ -3749,7 +3750,8 @@ size_t fio_flush_all(void) {
3749
3750
  return 0;
3750
3751
  size_t count = 0;
3751
3752
  for (uintptr_t i = 0; i <= fio_data->max_protocol_fd; ++i) {
3752
- if ((fd_data(i).open || fd_data(i).packet) && fio_flush(fd2uuid(i)) > 0)
3753
+ if ((fd_data(i).open || fd_data(i).packet) &&
3754
+ fd_data(i).rw_hooks && fio_flush(fd2uuid(i)) > 0)
3753
3755
  ++count;
3754
3756
  }
3755
3757
  return count;
@@ -4603,7 +4605,7 @@ static void *fio_sentinel_worker_thread(void *arg) {
4603
4605
  if (child == -1) {
4604
4606
  FIO_LOG_FATAL("couldn't spawn worker.");
4605
4607
  perror("\n errno");
4606
- kill(fio_parent_pid(), SIGINT);
4608
+ fio_kill(fio_parent_pid(), SIGINT);
4607
4609
  fio_stop();
4608
4610
  return NULL;
4609
4611
  } else if (child) {
@@ -4617,7 +4619,7 @@ static void *fio_sentinel_worker_thread(void *arg) {
4617
4619
  } else {
4618
4620
  FIO_LOG_FATAL("Child worker (%d) shutdown. Stopping services.", child);
4619
4621
  }
4620
- kill(0, SIGINT);
4622
+ fio_kill(0, SIGINT);
4621
4623
  }
4622
4624
  #else
4623
4625
  if (fio_data->active) {
@@ -6879,7 +6881,7 @@ static void fio_cluster_on_close(intptr_t uuid, fio_protocol_s *pr_) {
6879
6881
  #ifndef __MINGW32__
6880
6882
  fio_cluster_data_cleanup(1);
6881
6883
  #endif
6882
- kill(getpid(), SIGINT);
6884
+ fio_kill(getpid(), SIGINT);
6883
6885
  }
6884
6886
  }
6885
6887
  if (c->msg)
@@ -7155,7 +7157,7 @@ static void fio_cluster_on_connect(intptr_t uuid, void *udata) {
7155
7157
  static void fio_cluster_on_fail(intptr_t uuid, void *udata) {
7156
7158
  FIO_LOG_FATAL("(facil.io) unknown cluster connection error");
7157
7159
  perror(" errno");
7158
- kill(fio_parent_pid(), SIGINT);
7160
+ fio_kill(fio_parent_pid(), SIGINT);
7159
7161
  fio_stop();
7160
7162
  // exit(errno ? errno : 1);
7161
7163
  (void)udata;
data/ext/iodine_ext/fio.h CHANGED
@@ -263,10 +263,12 @@ Version and helper macros
263
263
  #define pipe(fds) _pipe(fds, 65536, _O_BINARY)
264
264
 
265
265
  int fork(void);
266
- int kill(int, int);
266
+ int fio_kill(int, int);
267
267
  ssize_t pread(int, void*, size_t, off_t);
268
268
  ssize_t pwrite(int, const void *, size_t, off_t);
269
269
  int fio_osffd4fd(unsigned int);
270
+ #else
271
+ #define fio_kill kill
270
272
  #endif
271
273
 
272
274
  /* *****************************************************************************
@@ -523,7 +525,7 @@ FIO_LOG2STDERR(const char *format, ...) {
523
525
  if (!(ptr)) { \
524
526
  FIO_LOG_FATAL("memory allocation error "__FILE__ \
525
527
  ":" FIO_MACRO2STR(__LINE__)); \
526
- kill(0, SIGINT); \
528
+ fio_kill(0, SIGINT); \
527
529
  exit(errno); \
528
530
  }
529
531
  #endif
@@ -6048,7 +6050,7 @@ FIO_NAME(_insert_or_overwrite_)(FIO_NAME(s) * set, FIO_SET_HASH_TYPE hash_value,
6048
6050
  pos->hash = hash_value;
6049
6051
  pos->pos->hash = hash_value;
6050
6052
  FIO_SET_COPY(pos->pos->obj, obj);
6051
-
6053
+
6052
6054
  return pos->pos->obj;
6053
6055
  }
6054
6056
 
@@ -922,7 +922,7 @@ intptr_t http_listen(const char *port, const char *binding,
922
922
  if (arg_settings.on_request == NULL) {
923
923
  FIO_LOG_ERROR("http_listen requires the .on_request parameter "
924
924
  "to be set\n");
925
- kill(0, SIGINT);
925
+ fio_kill(0, SIGINT);
926
926
  exit(11);
927
927
  }
928
928