packet 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README +4 -0
- data/Rakefile +16 -8
- data/TODO +8 -0
- data/examples/asteroid.c +296 -0
- data/examples/asteroid.h +5 -0
- data/examples/concurrent_thread.c +53 -0
- data/examples/extconf.h +4 -0
- data/examples/extconf.rb +10 -0
- data/examples/persistent_print.rb +24 -0
- data/examples/sample_server.rb +19 -0
- data/examples/use_stuff.rb +3 -0
- data/lib/bin_parser.rb +16 -8
- data/lib/class_helpers.rb +74 -0
- data/lib/connection.rb +18 -18
- data/lib/core.rb +38 -13
- data/lib/double_keyed_hash.rb +6 -0
- data/lib/meta_pimp.rb +20 -6
- data/lib/nbio.rb +27 -30
- data/lib/packet.rb +6 -6
- data/lib/packet_master.rb +55 -58
- data/lib/pimp.rb +1 -0
- data/lib/thread_pool.rb +54 -0
- data/lib/timer_store.rb +63 -0
- data/lib/worker.rb +4 -28
- data/lib/worker_pool.rb +10 -0
- metadata +66 -55
- data/LICENSE +0 -4
- data/bin/packet_mongrel.rb +0 -215
- data/bin/runner.rb +0 -35
- data/lib/attribute_accessors.rb +0 -48
- data/lib/buftok.rb +0 -127
- data/lib/cpu_worker.rb +0 -19
- data/lib/deferrable.rb +0 -210
- data/lib/io_worker.rb +0 -6
- data/lib/ruby_hacks.rb +0 -125
data/lib/buftok.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
# BufferedTokenizer - Statefully split input data by a specifiable token
|
2
|
-
#
|
3
|
-
# Authors:: Tony Arcieri, Martin Emde
|
4
|
-
#
|
5
|
-
#----------------------------------------------------------------------------
|
6
|
-
#
|
7
|
-
# Copyright (C) 2006-07 by Tony Arcieri and Martin Emde
|
8
|
-
#
|
9
|
-
# Distributed under the Ruby license (http://www.ruby-lang.org/en/LICENSE.txt)
|
10
|
-
#
|
11
|
-
#---------------------------------------------------------------------------
|
12
|
-
#
|
13
|
-
|
14
|
-
# (C)2006 Tony Arcieri, Martin Emde
|
15
|
-
# Distributed under the Ruby license (http://www.ruby-lang.org/en/LICENSE.txt)
|
16
|
-
|
17
|
-
# BufferedTokenizer takes a delimiter upon instantiation, or acts line-based
|
18
|
-
# by default. It allows input to be spoon-fed from some outside source which
|
19
|
-
# receives arbitrary length datagrams which may-or-may-not contain the token
|
20
|
-
# by which entities are delimited.
|
21
|
-
|
22
|
-
class BufferedTokenizer
|
23
|
-
# New BufferedTokenizers will operate on lines delimited by "\n" by default
|
24
|
-
# or allow you to specify any delimiter token you so choose, which will then
|
25
|
-
# be used by String#split to tokenize the input data
|
26
|
-
def initialize(delimiter = "\n", size_limit = nil)
|
27
|
-
# Store the specified delimiter
|
28
|
-
@delimiter = delimiter
|
29
|
-
|
30
|
-
# Store the specified size limitation
|
31
|
-
@size_limit = size_limit
|
32
|
-
|
33
|
-
# The input buffer is stored as an array. This is by far the most efficient
|
34
|
-
# approach given language constraints (in C a linked list would be a more
|
35
|
-
# appropriate data structure). Segments of input data are stored in a list
|
36
|
-
# which is only joined when a token is reached, substantially reducing the
|
37
|
-
# number of objects required for the operation.
|
38
|
-
@input = []
|
39
|
-
|
40
|
-
# Size of the input buffer
|
41
|
-
@input_size = 0
|
42
|
-
end
|
43
|
-
|
44
|
-
# Extract takes an arbitrary string of input data and returns an array of
|
45
|
-
# tokenized entities, provided there were any available to extract. This
|
46
|
-
# makes for easy processing of datagrams using a pattern like:
|
47
|
-
#
|
48
|
-
# tokenizer.extract(data).map { |entity| Decode(entity) }.each do ...
|
49
|
-
def extract(data)
|
50
|
-
# Extract token-delimited entities from the input string with the split command.
|
51
|
-
# There's a bit of craftiness here with the -1 parameter. Normally split would
|
52
|
-
# behave no differently regardless of if the token lies at the very end of the
|
53
|
-
# input buffer or not (i.e. a literal edge case) Specifying -1 forces split to
|
54
|
-
# return "" in this case, meaning that the last entry in the list represents a
|
55
|
-
# new segment of data where the token has not been encountered
|
56
|
-
entities = data.split @delimiter, -1
|
57
|
-
|
58
|
-
# Check to see if the buffer has exceeded capacity, if we're imposing a limit
|
59
|
-
if @size_limit
|
60
|
-
raise 'input buffer full' if @input_size + entities.first.size > @size_limit
|
61
|
-
@input_size += entities.first.size
|
62
|
-
end
|
63
|
-
|
64
|
-
# Move the first entry in the resulting array into the input buffer. It represents
|
65
|
-
# the last segment of a token-delimited entity unless it's the only entry in the list.
|
66
|
-
@input << entities.shift
|
67
|
-
|
68
|
-
# If the resulting array from the split is empty, the token was not encountered
|
69
|
-
# (not even at the end of the buffer). Since we've encountered no token-delimited
|
70
|
-
# entities this go-around, return an empty array.
|
71
|
-
return [] if entities.empty?
|
72
|
-
|
73
|
-
# At this point, we've hit a token, or potentially multiple tokens. Now we can bring
|
74
|
-
# together all the data we've buffered from earlier calls without hitting a token,
|
75
|
-
# and add it to our list of discovered entities.
|
76
|
-
entities.unshift @input.join
|
77
|
-
|
78
|
-
=begin
|
79
|
-
# Note added by FC, 10Jul07. This paragraph contains a regression. It breaks
|
80
|
-
# empty tokens. Think of the empty line that delimits an HTTP header. It will have
|
81
|
-
# two "\n" delimiters in a row, and this code mishandles the resulting empty token.
|
82
|
-
# It someone figures out how to fix the problem, we can re-enable this code branch.
|
83
|
-
# Multi-character token support.
|
84
|
-
# Split any tokens that were incomplete on the last iteration buf complete now.
|
85
|
-
entities.map! do |e|
|
86
|
-
e.split @delimiter, -1
|
87
|
-
end
|
88
|
-
# Flatten the resulting array. This has the side effect of removing the empty
|
89
|
-
# entry at the end that was produced by passing -1 to split. Add it again if
|
90
|
-
# necessary.
|
91
|
-
if (entities[-1] == [])
|
92
|
-
entities.flatten! << []
|
93
|
-
else
|
94
|
-
entities.flatten!
|
95
|
-
end
|
96
|
-
=end
|
97
|
-
|
98
|
-
# Now that we've hit a token, joined the input buffer and added it to the entities
|
99
|
-
# list, we can go ahead and clear the input buffer. All of the segments that were
|
100
|
-
# stored before the join can now be garbage collected.
|
101
|
-
@input.clear
|
102
|
-
|
103
|
-
# The last entity in the list is not token delimited, however, thanks to the -1
|
104
|
-
# passed to split. It represents the beginning of a new list of as-yet-untokenized
|
105
|
-
# data, so we add it to the start of the list.
|
106
|
-
@input << entities.pop
|
107
|
-
|
108
|
-
# Set the new input buffer size, provided we're keeping track
|
109
|
-
@input_size = @input.first.size if @size_limit
|
110
|
-
|
111
|
-
# Now we're left with the list of extracted token-delimited entities we wanted
|
112
|
-
# in the first place. Hooray!
|
113
|
-
entities
|
114
|
-
end
|
115
|
-
|
116
|
-
# Flush the contents of the input buffer, i.e. return the input buffer even though
|
117
|
-
# a token has not yet been encountered
|
118
|
-
def flush
|
119
|
-
buffer = @input.join
|
120
|
-
@input.clear
|
121
|
-
buffer
|
122
|
-
end
|
123
|
-
|
124
|
-
def empty?
|
125
|
-
@input.empty?
|
126
|
-
end
|
127
|
-
end
|
data/lib/cpu_worker.rb
DELETED
@@ -1,19 +0,0 @@
|
|
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
|
data/lib/deferrable.rb
DELETED
@@ -1,210 +0,0 @@
|
|
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
|
-
|
data/lib/io_worker.rb
DELETED
data/lib/ruby_hacks.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
# FIXME: ultimate goal should be remove dependence from activesupport gem altogether.
|
2
|
-
|
3
|
-
class Object
|
4
|
-
def deep_copy
|
5
|
-
Marshal.load(Marshal.dump(self))
|
6
|
-
end
|
7
|
-
|
8
|
-
def nothing?
|
9
|
-
if respond_to?(:empty?) && respond_to?(:strip)
|
10
|
-
empty? or strip.empty?
|
11
|
-
elsif respond_to?(:empty?)
|
12
|
-
empty?
|
13
|
-
elsif respond_to?(:zero?)
|
14
|
-
zero?
|
15
|
-
else
|
16
|
-
!self
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def clean!
|
21
|
-
if respond_to?(:empty?) && respond_to?(:strip)
|
22
|
-
return nil if empty?
|
23
|
-
(strip.empty?) ? nil : (self.strip)
|
24
|
-
elsif respond_to?(:empty?)
|
25
|
-
empty? ? nil : self
|
26
|
-
else
|
27
|
-
self
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def blank?
|
32
|
-
if respond_to?(:empty?) && respond_to?(:strip)
|
33
|
-
empty? or strip.empty?
|
34
|
-
elsif respond_to?(:empty?)
|
35
|
-
empty?
|
36
|
-
else
|
37
|
-
!self
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.metaclass; class << self; self; end; end
|
42
|
-
|
43
|
-
def self.iattr_accessor *args
|
44
|
-
|
45
|
-
metaclass.instance_eval do
|
46
|
-
attr_accessor *args
|
47
|
-
args.each do |attr|
|
48
|
-
define_method("set_#{attr}") do |b_value|
|
49
|
-
self.send("#{attr}=",b_value)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
args.each do |attr|
|
55
|
-
class_eval do
|
56
|
-
define_method(attr) do
|
57
|
-
self.class.send(attr)
|
58
|
-
end
|
59
|
-
define_method("#{attr}=") do |b_value|
|
60
|
-
self.class.send("#{attr}=",b_value)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
class NilClass #:nodoc:
|
69
|
-
def blank?
|
70
|
-
true
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class FalseClass #:nodoc:
|
75
|
-
def blank?
|
76
|
-
true
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class TrueClass #:nodoc:
|
81
|
-
def blank?
|
82
|
-
false
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class Array #:nodoc:
|
87
|
-
alias_method :blank?, :empty?
|
88
|
-
def clean!
|
89
|
-
(empty?) ? nil : self
|
90
|
-
end
|
91
|
-
|
92
|
-
def extract_options!
|
93
|
-
last.is_a?(Hash) ? pop : {}
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
class Hash #:nodoc:
|
98
|
-
alias_method :blank?, :empty?
|
99
|
-
def clean!
|
100
|
-
(empty?) ? nil : self
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
class String #:nodoc:
|
105
|
-
def blank?
|
106
|
-
empty? || strip.empty?
|
107
|
-
end
|
108
|
-
|
109
|
-
def clean!
|
110
|
-
return nil if empty?
|
111
|
-
t_val = self.strip
|
112
|
-
(t_val.empty?) ? nil : t_val
|
113
|
-
end
|
114
|
-
|
115
|
-
def classify
|
116
|
-
word_parts = split('_')
|
117
|
-
return word_parts.map { |x| x.capitalize}.join
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
class Numeric #:nodoc:
|
122
|
-
def blank?
|
123
|
-
false
|
124
|
-
end
|
125
|
-
end
|