packet 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ module Packet
2
+ class CPUWorker < Packet::Worker
3
+ @@worker_type = 'cpu'
4
+ cattr_accessor :worker_type
5
+ # this is the place where all the worker specific inititlization has to be done
6
+ def worker_init
7
+ @worker_started = true
8
+ end
9
+
10
+ def receive_data p_data
11
+ p p_data
12
+ end
13
+
14
+ def receive_internal_data p_data
15
+ p p_data
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,210 @@
1
+ # $Id: deferrable.rb 534 2007-09-15 23:06:15Z blackhedd $
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 Jul 2006
6
+ #
7
+ # See EventMachine and EventMachine::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
+ # FIXME: Packet doesn't support timers on Deferables yet
27
+
28
+ require 'forwardable'
29
+
30
+ module Packet
31
+
32
+ module Deferrable
33
+
34
+ # Specify a block to be executed if and when the Deferrable object receives
35
+ # a status of :succeeded. See #set_deferred_status for more information.
36
+ #
37
+ # Calling this method on a Deferrable object whose status is not yet known
38
+ # will cause the callback block to be stored on an internal list.
39
+ # If you call this method on a Deferrable whose status is :succeeded, the
40
+ # block will be executed immediately, receiving the parameters given to the
41
+ # prior #set_deferred_status call.
42
+ #
43
+ #--
44
+ # If there is no status, add a callback to an internal list.
45
+ # If status is succeeded, execute the callback immediately.
46
+ # If status is failed, do nothing.
47
+ #
48
+ def callback &block
49
+ return unless block
50
+ if @deferred_status == :succeeded
51
+ block.call(*@deferred_args)
52
+ elsif @deferred_status != :failed
53
+ @callbacks ||= []
54
+ @callbacks.unshift block # << block
55
+ end
56
+ end
57
+
58
+ # Specify a block to be executed if and when the Deferrable object receives
59
+ # a status of :failed. See #set_deferred_status for more information.
60
+ #--
61
+ # If there is no status, add an errback to an internal list.
62
+ # If status is failed, execute the errback immediately.
63
+ # If status is succeeded, do nothing.
64
+ #
65
+ def errback &block
66
+ return unless block
67
+ if @deferred_status == :failed
68
+ block.call(*@deferred_args)
69
+ elsif @deferred_status != :succeeded
70
+ @errbacks ||= []
71
+ @errbacks.unshift block # << block
72
+ end
73
+ end
74
+
75
+ # Sets the "disposition" (status) of the Deferrable object. See also the large set of
76
+ # sugarings for this method.
77
+ # Note that if you call this method without arguments,
78
+ # no arguments will be passed to the callback/errback.
79
+ # If the user has coded these with arguments, then the
80
+ # user code will throw an argument exception.
81
+ # Implementors of deferrable classes <b>must</b>
82
+ # document the arguments they will supply to user callbacks.
83
+ #
84
+ # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
85
+ # on the INSIDE of a callback. This is very useful when a previously-registered
86
+ # callback wants to change the parameters that will be passed to subsequently-registered
87
+ # ones.
88
+ #
89
+ # You may give either :succeeded or :failed as the status argument.
90
+ #
91
+ # If you pass :succeeded, then all of the blocks passed to the object using the #callback
92
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
93
+ # passed to the object using #errback will be discarded.
94
+ #
95
+ # If you pass :failed, then all of the blocks passed to the object using the #errback
96
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
97
+ # passed to the object using # callback will be discarded.
98
+ #
99
+ # If you pass any arguments to #set_deferred_status in addition to the status argument,
100
+ # they will be passed as arguments to any callbacks or errbacks that are executed.
101
+ # It's your responsibility to ensure that the argument lists specified in your callbacks and
102
+ # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
103
+ # an ArgumentError.
104
+ #
105
+ # --
106
+ # We're shifting callbacks off and discarding them as we execute them.
107
+ # This is valid because by definition callbacks are executed no more than
108
+ # once. It also has the magic effect of permitting recursive calls, which
109
+ # means that a callback can call #set_deferred_status and change the parameters
110
+ # that will be sent to subsequent callbacks down the chain.
111
+ #
112
+ # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
113
+ # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
114
+ # versions.
115
+ #
116
+ # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
117
+ # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
118
+ # which only allows status to be set once. Prior to making this change, it was possible
119
+ # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
120
+ # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
121
+ # to raise an exception is status is set more than once on a Deferrable. The latter
122
+ # behavior would invalidate the idiom of resetting arguments by setting status from
123
+ # within a callback or errback, but more seriously it would cause spurious errors
124
+ # if a Deferrable was timed out and then an attempt was made to succeed it. See the
125
+ # comments under the new method #timeout.
126
+ #
127
+ def set_deferred_status status, *args
128
+ #cancel_timeout
129
+ @deferred_status = status
130
+ @deferred_args = args
131
+ case @deferred_status
132
+ when :succeeded
133
+ if @callbacks
134
+ while cb = @callbacks.pop
135
+ cb.call(*@deferred_args)
136
+ end
137
+ end
138
+ @errbacks.clear if @errbacks
139
+ when :failed
140
+ if @errbacks
141
+ while eb = @errbacks.pop
142
+ eb.call(*@deferred_args)
143
+ end
144
+ end
145
+ @callbacks.clear if @callbacks
146
+ end
147
+ end
148
+
149
+
150
+ # Setting a timeout on a Deferrable causes it to go into the failed state after
151
+ # the Timeout expires (passing no arguments to the object's errbacks).
152
+ # Setting the status at any time prior to a call to the expiration of the timeout
153
+ # will cause the timer to be cancelled.
154
+ #--
155
+ #
156
+ #
157
+ def timeout seconds
158
+ cancel_timeout
159
+ me = self
160
+ @deferred_timeout = EventMachine::Timer.new(seconds) {me.fail}
161
+ end
162
+
163
+
164
+ # Cancels an outstanding timeout if any. Undoes the action of #timeout.
165
+ #
166
+ #
167
+ def cancel_timeout
168
+ if @deferred_timeout
169
+ @deferred_timeout.cancel
170
+ @deferred_timeout = nil
171
+ end
172
+ end
173
+
174
+
175
+ # Equivalent to set_deferred_status(:succeeded, ...)
176
+ #
177
+ def set_deferred_success *args
178
+ set_deferred_status :succeeded, *args
179
+ end
180
+
181
+ # Equivalent to set_deferred_status(:failed, ...)
182
+ #
183
+ def set_deferred_failure *args
184
+ set_deferred_status :failed, *args
185
+ end
186
+
187
+ # And still more sugar
188
+ #
189
+ def succeed *args
190
+ set_deferred_success(*args)
191
+ end
192
+
193
+ # Can't get enough sugar
194
+ #
195
+ def fail *args
196
+ set_deferred_failure(*args)
197
+ end
198
+ end
199
+
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
+ #
205
+ class DefaultDeferrable
206
+ include Deferrable
207
+ end
208
+
209
+ end
210
+
@@ -0,0 +1,8 @@
1
+ module Packet
2
+ class DisconnectError < RuntimeError
3
+ attr_accessor :disconnected_socket
4
+ def initialize(t_sock)
5
+ @disconnected_socket = t_sock
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ class DoubleKeyedHash
2
+ def initialize
3
+ @keys1 = {}
4
+ @internal_hash = {}
5
+ end
6
+
7
+ def []=(key1,key2,value)
8
+ @keys1[key2] = key1
9
+ @internal_hash[key1] = value
10
+ end
11
+
12
+ def [] key
13
+ @internal_hash[key] || @internal_hash[@keys1[key]]
14
+ end
15
+
16
+ def each
17
+ @internal_hash.each { |key,value| yield(key,value)}
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module Packet
2
+ class Event
3
+ attr_accessor :timer_signature, :block, :cancel_flag
4
+ def initialize(elapsed_time,&block)
5
+ @cancel_flag = false
6
+ @timer_signature = Guid.hexdigest
7
+ @block = block
8
+ @scheduled_time = Time.now + elapsed_time
9
+ end
10
+
11
+ def run_now?
12
+ return true if @scheduled_time <= Time.now
13
+ return false
14
+ end
15
+
16
+ def cancel
17
+ @cancel_flag = true
18
+ end
19
+
20
+ def run
21
+ @block.call
22
+ end
23
+ end
24
+ end
25
+ # WOW
@@ -0,0 +1,6 @@
1
+ module Packet
2
+ class IOWorker < Packet::Worker
3
+ @@worker_type = :io
4
+ cattr_accessor :worker_type
5
+ end
6
+ end
@@ -0,0 +1,66 @@
1
+ # Class acts as a pimp for workers, which doesn't have a manually created pimp
2
+ # The idea behind a manually added pimp is to let client handle low level messaging
3
+ # beween workers. A meta pimp, does it for you.
4
+ class Packet::MetaPimp < Packet::Pimp
5
+ # initializer of pimp
6
+ attr_accessor :callback_hash
7
+ attr_accessor :worker_status
8
+ def pimp_init
9
+ @callback_hash ||= {}
10
+ @worker_status = nil
11
+ @tokenizer = BinParser.new
12
+ end
13
+
14
+ # will be invoked whenever there is a response from the worker
15
+ # Possible bug with reading large responses.
16
+ # response would be binary but base64 encoded and must be decoded and then loaded
17
+ def receive_data p_data
18
+ @tokenizer.extract(p_data) do |b_data|
19
+ t_data = Marshal.load(b_data)
20
+ handle_object(t_data)
21
+ end
22
+ end
23
+
24
+ def handle_object data_options = {}
25
+ case data_options[:type]
26
+ when :request
27
+ process_request(data_options)
28
+ when :response
29
+ process_response(data_options)
30
+ when :status
31
+ save_worker_status(data_options)
32
+ end
33
+ end
34
+
35
+ def save_worker_status(data_options = { })
36
+ @worker_status = data_options[:data]
37
+ end
38
+
39
+ def process_request(data_options = {})
40
+ if requested_worker = data_options[:requested_worker]
41
+ reactor.live_workers[requested_worker].send_request(data_options)
42
+ end
43
+ end
44
+
45
+ def process_response(data_options = {})
46
+ if callback_signature = data_options[:callback_signature]
47
+ callback = callback_hash[callback_signature]
48
+ callback.call(data_options)
49
+ elsif client_signature = data_options[:client_signature]
50
+ reactor.connections[client_signature].instance.worker_receive(data_options)
51
+ end
52
+ end
53
+
54
+ # can be used to send request to correspoding worker
55
+ def send_request(data_options = { })
56
+ if callback = data_options[:callback]
57
+ callback_hash[callback.signature] = callback
58
+ data_options.delete(:callback)
59
+ data_options[:callback_signature] = callback.signature
60
+ send_data(data_options)
61
+ else
62
+ send_data(data_options)
63
+ end
64
+ end
65
+ end
66
+
@@ -0,0 +1,81 @@
1
+ module Packet
2
+ module NbioHelper
3
+ # nonblocking method of reading data
4
+ # when method returns nil it probably means that client diconnected
5
+ def read_data(t_sock)
6
+ sock_data = ""
7
+ begin
8
+ while(sock_data << t_sock.read_nonblock(1023)); end
9
+ rescue Errno::EAGAIN
10
+ return sock_data
11
+ rescue
12
+ raise DisconnectError.new(t_sock)
13
+ end
14
+ end
15
+
16
+ def write_data(p_data,p_sock)
17
+ return unless p_data
18
+ if p_data.is_a? Fixnum
19
+ t_data = p_data.to_s
20
+ else
21
+ t_data = p_data.dup.to_s
22
+ end
23
+ t_length = t_data.length
24
+ begin
25
+ p_sock.write_nonblock(t_data)
26
+ rescue Errno::EAGAIN
27
+ return
28
+ end
29
+
30
+ # loop do
31
+ # begin
32
+ # written_length = p_sock.write_nonblock(t_data)
33
+ # rescue Errno::EAGAIN
34
+ # break
35
+ # end
36
+ # break if written_length >= t_length
37
+ # t_data = t_data[written_length..-1]
38
+ # break if t_data.empty?
39
+ # t_length = t_data.length
40
+ # end
41
+ end
42
+
43
+ # method writes data to socket in a non blocking manner, but doesn't care if there is a error writing data
44
+ def write_once(p_data,p_sock)
45
+ t_data = p_data.dup.to_s
46
+ begin
47
+ p_sock.write_nonblock(t_data)
48
+ rescue Errno::EAGAIN
49
+ return
50
+ end
51
+ end
52
+
53
+ # method dumps the object in a protocol format which can be easily picked by a recursive descent parser
54
+ def dump_object(p_data,p_sock)
55
+ object_dump = Marshal.dump(p_data)
56
+ dump_length = object_dump.length.to_s
57
+ length_str = dump_length.rjust(9,'0')
58
+ final_data = length_str + object_dump
59
+
60
+ # total_length = final_data.length
61
+ # loop do
62
+ # begin
63
+ # written_length = p_sock.write_nonblock(final_data)
64
+ # rescue Errno::EAGAIN
65
+ # break
66
+ # end
67
+ # break if written_length >= total_length
68
+ # final_data = final_data[written_length..-1]
69
+ # break if final_data.empty?
70
+ # total_length = final_data.length
71
+ # end
72
+
73
+ begin
74
+ p_sock.write_nonblock(final_data)
75
+ rescue Errno::EAGAIN
76
+ return
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,37 @@
1
+ require "socket"
2
+ require "yaml"
3
+ require "forwardable"
4
+ require "attribute_accessors"
5
+ require "buftok"
6
+ require "bin_parser"
7
+
8
+ require "ostruct"
9
+ require "socket"
10
+
11
+ require "packet_guid"
12
+ require "ruby_hacks"
13
+ require "double_keyed_hash"
14
+ require "event"
15
+
16
+ require "periodic_event"
17
+ require "disconnect_error"
18
+ require "callback"
19
+
20
+ require "nbio"
21
+ require "pimp"
22
+ require "meta_pimp"
23
+ require "core"
24
+
25
+ require "packet_master"
26
+ require "connection"
27
+ require "worker"
28
+
29
+ # This file is just a runner of things and hence does basic initialization of thingies required for running
30
+ # the application.
31
+
32
+
33
+ PACKET_APP = File.expand_path'../' unless defined?(PACKET_APP)
34
+
35
+ module Packet
36
+ VERSION='0.1.0'
37
+ end