zmachine 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zmachine.gemspec
4
+ gemspec
5
+
6
+ gem 'ruby-debug'
7
+ gem 'ruby-debug-ide'
8
+ gem 'brice'
9
+ gem 'awesome_print'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Benedikt Böhm
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Zmachine
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'zmachine'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install zmachine
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/echo_client.rb ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'zmachine'
6
+
7
+ java_import org.zeromq.ZMQ
8
+ java_import org.zeromq.ZMsg
9
+ java_import org.zeromq.ZFrame
10
+
11
+ #set_trace_func proc { |event, file, line, id, binding, classname|
12
+ # printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
13
+ #}
14
+
15
+ $i = 0
16
+
17
+ class ZMQEcho < ZMachine::Connection
18
+ def connection_completed
19
+ send_msg
20
+ end
21
+
22
+ def receive_data(data)
23
+ puts "recv(#{data.to_a.map {|f| String.from_java_bytes(f.data) }.inspect})"
24
+ send_msg
25
+ end
26
+
27
+ def send_msg
28
+ msg = ZMsg.new_string_msg($i.to_s)
29
+ msg.wrap(ZFrame.new("server"))
30
+ send_data(msg)
31
+ $i += 1
32
+ end
33
+ end
34
+
35
+ class TCPEcho < ZMachine::Connection
36
+ def connection_completed
37
+ send_data(Time.now.to_s)
38
+ sleep(0.5)
39
+ end
40
+
41
+ def receive_data(data)
42
+ puts "receive_data(#{data.inspect})"
43
+ send_data(Time.now.to_s)
44
+ end
45
+ end
46
+
47
+ ZMachine.run {
48
+ ZMachine.connect("tcp://127.0.0.1:10000", ZMQ::ROUTER, ZMQEcho) do |handler|
49
+ handler.channel.identity = "client"
50
+ end
51
+ #ZMachine.connect("127.0.0.1", 10000, TCPEcho)
52
+ }
53
+
54
+ #ctx = ZContext.new
55
+ #socket = ctx.create_socket(ZMQ::ROUTER)
56
+ #socket.connect("tcp://127.0.0.1:10000")
57
+ #socket.identity = "client".to_java_bytes
58
+
59
+ #sleep(1)
60
+
61
+ #loop do
62
+ # msg = ZMsg.new_string_msg($i.to_s)
63
+ # msg.wrap(ZFrame.new("server"))
64
+ # msg.java_send(:send, [org.zeromq.ZMQ::Socket], socket)
65
+ # $i += 1
66
+ # break if $i > 100
67
+ # #puts ZMsg.recvMsg(socket).inspect
68
+ #end
69
+
70
+ #socket.close
71
+ #ctx.destroy
data/echo_server.rb ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'zmachine'
6
+
7
+ java_import org.zeromq.ZMQ
8
+ java_import org.zeromq.ZFrame
9
+
10
+ #set_trace_func proc { |event, file, line, id, binding, classname|
11
+ # printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
12
+ #}
13
+
14
+ class EchoServer < ZMachine::Connection
15
+ def receive_data(msg)
16
+ origin = msg.unwrap
17
+ puts "recv(#{msg.to_a.map {|f| String.from_java_bytes(f.data) }.inspect})"
18
+ msg = ZMsg.new_string_msg("ok")
19
+ msg.wrap(origin)
20
+ send_data(msg)
21
+ end
22
+ end
23
+
24
+ ZMachine.run do
25
+ ZMachine.start_server("tcp://*:10000", ZMQ::ROUTER, EchoServer) do |handler|
26
+ handler.channel.identity = "server"
27
+ end
28
+ #ZMachine.start_server("0.0.0.0", 10000, EchoServer)
29
+ puts "machine running"
30
+ end
31
+
32
+ #ctx = ZContext.new
33
+ #socket = ctx.create_socket(ZMQ::ROUTER)
34
+ #socket.bind("tcp://127.0.0.1:10000")
35
+ #socket.identity = "server".to_java_bytes
36
+
37
+ #loop do
38
+ # puts socket.events.inspect
39
+ # msg = ZMsg.recvMsg(socket)
40
+ # puts "recv(#{msg.to_a.map {|f| String.from_java_bytes(f.data) }.inspect})"
41
+ #end
@@ -0,0 +1,12 @@
1
+ module ZMachine
2
+ class Acceptor
3
+ attr_reader :klass
4
+ attr_reader :args
5
+ attr_reader :callback
6
+
7
+ def initialize(channel, klass, *args, &block)
8
+ @klass, @args, @callback = klass, args, block
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module ZMachine
2
+ class Channel
3
+
4
+ attr_reader :socket
5
+ attr_reader :selector
6
+ attr_accessor :handler
7
+
8
+ def initialize(selector)
9
+ @selector = selector
10
+ @outbound_queue = []
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,186 @@
1
+ module ZMachine
2
+ class Connection
3
+
4
+ attr_accessor :channel
5
+
6
+ extend Forwardable
7
+
8
+ alias original_method method
9
+
10
+ def self.new(channel, *args, &block)
11
+ allocate.instance_eval do
12
+ @channel = channel
13
+ initialize(*args, &block)
14
+ post_init
15
+ self
16
+ end
17
+ end
18
+
19
+ def initialize(*args, &block)
20
+ end
21
+
22
+ # callbacks
23
+
24
+ def post_init
25
+ end
26
+
27
+ def connection_completed
28
+ end
29
+
30
+ def receive_data(data)
31
+ end
32
+
33
+ def unbind
34
+ end
35
+
36
+ # public API
37
+
38
+ def_delegator :@channel, :close_connection
39
+
40
+ def close_connection_after_writing
41
+ close_connection(true)
42
+ end
43
+
44
+ def comm_inactivity_timeout
45
+ end
46
+
47
+ def comm_inactivity_timeout=(value)
48
+ end
49
+
50
+ alias :set_comm_inactivity_timeout :comm_inactivity_timeout=
51
+
52
+ def detach
53
+ _not_implemented
54
+ end
55
+
56
+ def error?
57
+ errno = ZMachine::report_connection_error_status(@signature)
58
+ case errno
59
+ when 0
60
+ false
61
+ when -1
62
+ true
63
+ else
64
+ Errno::constants.select do |name|
65
+ Errno.__send__(:const_get, name)::Errno == errno
66
+ end.first
67
+ end
68
+ end
69
+
70
+ def get_idle_time
71
+ _not_implemented
72
+ end
73
+
74
+ def get_peer_cert
75
+ _not_implemented
76
+ end
77
+
78
+ def get_peername
79
+ if peer = @channel.peer_name
80
+ ::Socket.pack_sockaddr_in(*peer)
81
+ end
82
+ end
83
+
84
+ def get_pid
85
+ _not_implemented
86
+ end
87
+
88
+ def get_proxied_bytes
89
+ _not_implemented
90
+ end
91
+
92
+ def_delegator :@channel, :get_sock_opt
93
+
94
+ def get_sockname
95
+ if sock_name = @channel.sock_name
96
+ ::Socket.pack_sockaddr_in(*sock_name)
97
+ end
98
+ end
99
+
100
+ def get_status
101
+ end
102
+
103
+ def notify_readable=(mode)
104
+ _not_implemented
105
+ end
106
+
107
+ def notify_readable?
108
+ _not_implemented
109
+ end
110
+
111
+ def notify_writable=(mode)
112
+ _not_implemented
113
+ end
114
+
115
+ def notify_writable?
116
+ _not_implemented
117
+ end
118
+
119
+ def pause
120
+ _not_implemented
121
+ end
122
+
123
+ def paused?
124
+ _not_implemented
125
+ end
126
+
127
+ def pending_connect_timeout=(value)
128
+ end
129
+
130
+ alias :set_pending_connect_timeout :pending_connect_timeout=
131
+
132
+ def proxy_completed
133
+ _not_implemented
134
+ end
135
+
136
+ def proxy_incoming_to(conn, bufsize = 0)
137
+ _not_implemented
138
+ end
139
+
140
+ def proxy_target_unbound
141
+ _not_implemented
142
+ end
143
+
144
+ def resume
145
+ _not_implemented
146
+ end
147
+
148
+ def_delegator :@channel, :send_data
149
+
150
+ def send_datagram(data, recipient_address, recipient_port)
151
+ _not_implemented
152
+ end
153
+
154
+ def send_file_data(filename)
155
+ _not_implemented
156
+ end
157
+
158
+ def_delegator :@channel, :set_sock_opt
159
+
160
+ def ssl_handshake_completed
161
+ _not_implemented
162
+ end
163
+
164
+ def ssl_verify_peer(cert)
165
+ _not_implemented
166
+ end
167
+
168
+ def start_tls(args = {})
169
+ _not_implemented
170
+ end
171
+
172
+ def stop_proxying
173
+ _not_implemented
174
+ end
175
+
176
+ def stream_file_data(filename, args = {})
177
+ _not_implemented
178
+ end
179
+
180
+ private
181
+
182
+ def _not_implemented
183
+ raise RuntimeError.new("API call not implemented!")
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,207 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 Jul 2006
6
+ #
7
+ # See ZMachine and ZMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ module ZMachine
27
+ module Deferrable
28
+ autoload :Pool, 'em/deferrable/pool'
29
+
30
+ # Specify a block to be executed if and when the Deferrable object receives
31
+ # a status of :succeeded. See #set_deferred_status for more information.
32
+ #
33
+ # Calling this method on a Deferrable object whose status is not yet known
34
+ # will cause the callback block to be stored on an internal list.
35
+ # If you call this method on a Deferrable whose status is :succeeded, the
36
+ # block will be executed immediately, receiving the parameters given to the
37
+ # prior #set_deferred_status call.
38
+ #
39
+ #--
40
+ # If there is no status, add a callback to an internal list.
41
+ # If status is succeeded, execute the callback immediately.
42
+ # If status is failed, do nothing.
43
+ #
44
+ def callback(&block)
45
+ return unless block
46
+ @deferred_status ||= :unknown
47
+ if @deferred_status == :succeeded
48
+ block.call(*@deferred_args)
49
+ elsif @deferred_status != :failed
50
+ @callbacks ||= []
51
+ @callbacks.unshift(block) # << block
52
+ end
53
+ self
54
+ end
55
+
56
+ # Cancels an outstanding callback to &block if any. Undoes the action of #callback.
57
+ #
58
+ def cancel_callback(block)
59
+ @callbacks ||= []
60
+ @callbacks.delete(block)
61
+ end
62
+
63
+ # Specify a block to be executed if and when the Deferrable object receives
64
+ # a status of :failed. See #set_deferred_status for more information.
65
+ #--
66
+ # If there is no status, add an errback to an internal list.
67
+ # If status is failed, execute the errback immediately.
68
+ # If status is succeeded, do nothing.
69
+ #
70
+ def errback(&block)
71
+ return unless block
72
+ @deferred_status ||= :unknown
73
+ if @deferred_status == :failed
74
+ block.call(*@deferred_args)
75
+ elsif @deferred_status != :succeeded
76
+ @errbacks ||= []
77
+ @errbacks.unshift(block) # << block
78
+ end
79
+ self
80
+ end
81
+
82
+ # Cancels an outstanding errback to &block if any. Undoes the action of #errback.
83
+ #
84
+ def cancel_errback(block)
85
+ @errbacks ||= []
86
+ @errbacks.delete(block)
87
+ end
88
+
89
+ # Sets the "disposition" (status) of the Deferrable object. See also the large set of
90
+ # sugarings for this method.
91
+ # Note that if you call this method without arguments,
92
+ # no arguments will be passed to the callback/errback.
93
+ # If the user has coded these with arguments, then the
94
+ # user code will throw an argument exception.
95
+ # Implementors of deferrable classes <b>must</b>
96
+ # document the arguments they will supply to user callbacks.
97
+ #
98
+ # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
99
+ # on the INSIDE of a callback. This is very useful when a previously-registered
100
+ # callback wants to change the parameters that will be passed to subsequently-registered
101
+ # ones.
102
+ #
103
+ # You may give either :succeeded or :failed as the status argument.
104
+ #
105
+ # If you pass :succeeded, then all of the blocks passed to the object using the #callback
106
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
107
+ # passed to the object using #errback will be discarded.
108
+ #
109
+ # If you pass :failed, then all of the blocks passed to the object using the #errback
110
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
111
+ # passed to the object using # callback will be discarded.
112
+ #
113
+ # If you pass any arguments to #set_deferred_status in addition to the status argument,
114
+ # they will be passed as arguments to any callbacks or errbacks that are executed.
115
+ # It's your responsibility to ensure that the argument lists specified in your callbacks and
116
+ # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
117
+ # an ArgumentError.
118
+ #
119
+ #--
120
+ # We're shifting callbacks off and discarding them as we execute them.
121
+ # This is valid because by definition callbacks are executed no more than
122
+ # once. It also has the magic effect of permitting recursive calls, which
123
+ # means that a callback can call #set_deferred_status and change the parameters
124
+ # that will be sent to subsequent callbacks down the chain.
125
+ #
126
+ # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
127
+ # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
128
+ # versions.
129
+ #
130
+ # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
131
+ # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
132
+ # which only allows status to be set once. Prior to making this change, it was possible
133
+ # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
134
+ # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
135
+ # to raise an exception is status is set more than once on a Deferrable. The latter
136
+ # behavior would invalidate the idiom of resetting arguments by setting status from
137
+ # within a callback or errback, but more seriously it would cause spurious errors
138
+ # if a Deferrable was timed out and then an attempt was made to succeed it. See the
139
+ # comments under the new method #timeout.
140
+ #
141
+ def set_deferred_status(status, *args)
142
+ cancel_timeout
143
+ @errbacks ||= nil
144
+ @callbacks ||= nil
145
+ @deferred_status = status
146
+ @deferred_args = args
147
+ case @deferred_status
148
+ when :succeeded
149
+ if @callbacks
150
+ while cb = @callbacks.pop
151
+ cb.call(*@deferred_args)
152
+ end
153
+ end
154
+ @errbacks.clear if @errbacks
155
+ when :failed
156
+ if @errbacks
157
+ while eb = @errbacks.pop
158
+ eb.call(*@deferred_args)
159
+ end
160
+ end
161
+ @callbacks.clear if @callbacks
162
+ end
163
+ end
164
+
165
+ # Setting a timeout on a Deferrable causes it to go into the failed state after
166
+ # the Timeout expires (passing no arguments to the object's errbacks).
167
+ # Setting the status at any time prior to a call to the expiration of the timeout
168
+ # will cause the timer to be cancelled.
169
+ def timeout(seconds, *args)
170
+ cancel_timeout
171
+ me = self
172
+ @deferred_timeout = ZMachine::Timer.new(seconds) { me.fail(*args) }
173
+ self
174
+ end
175
+
176
+ # Cancels an outstanding timeout if any. Undoes the action of #timeout.
177
+ #
178
+ def cancel_timeout
179
+ @deferred_timeout ||= nil
180
+ if @deferred_timeout
181
+ @deferred_timeout.cancel
182
+ @deferred_timeout = nil
183
+ end
184
+ end
185
+
186
+ # Sugar for set_deferred_status(:succeeded, ...)
187
+ #
188
+ def succeed(*args)
189
+ set_deferred_status(:succeeded, *args)
190
+ end
191
+ alias set_deferred_success succeed
192
+
193
+ # Sugar for set_deferred_status(:failed, ...)
194
+ #
195
+ def fail(*args)
196
+ set_deferred_status(:failed, *args)
197
+ end
198
+ alias set_deferred_failure fail
199
+ end
200
+
201
+ # DefaultDeferrable is an otherwise empty class that includes Deferrable.
202
+ # This is very useful when you just need to return a Deferrable object
203
+ # as a way of communicating deferred status to some other part of a program.
204
+ class DefaultDeferrable
205
+ include Deferrable
206
+ end
207
+ end