packet 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|