drbdump 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.autotest +8 -0
- data/.gemtest +0 -0
- data/History.rdoc +4 -0
- data/Manifest.txt +30 -0
- data/README.rdoc +71 -0
- data/Rakefile +30 -0
- data/bin/drbdump +6 -0
- data/example/ping.rb +241 -0
- data/example/service_primes.rb +212 -0
- data/example/tuplespace_primes.rb +196 -0
- data/lib/drbdump.rb +714 -0
- data/lib/drbdump/loader.rb +75 -0
- data/lib/drbdump/message.rb +72 -0
- data/lib/drbdump/message_result.rb +84 -0
- data/lib/drbdump/message_send.rb +146 -0
- data/lib/drbdump/statistic.rb +90 -0
- data/lib/drbdump/statistics.rb +318 -0
- data/lib/drbdump/test_case.rb +91 -0
- data/test/arg.dump +0 -0
- data/test/drb_fin.dump +0 -0
- data/test/http.dump +0 -0
- data/test/ping.dump +0 -0
- data/test/ring.dump +0 -0
- data/test/test_drbdump.rb +283 -0
- data/test/test_drbdump_loader.rb +88 -0
- data/test/test_drbdump_message.rb +31 -0
- data/test/test_drbdump_message_result.rb +73 -0
- data/test/test_drbdump_message_send.rb +105 -0
- data/test/test_drbdump_statistic.rb +98 -0
- data/test/test_drbdump_statistics.rb +264 -0
- data/test/too_large_packet.pcap +0 -0
- metadata +183 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'marshal/structure'
|
2
|
+
|
3
|
+
##
|
4
|
+
# A DRb protocol message chunk loader.
|
5
|
+
#
|
6
|
+
# Based on DRb::DRbMessage
|
7
|
+
|
8
|
+
class DRbDump::Loader
|
9
|
+
|
10
|
+
##
|
11
|
+
# Base Loader error class
|
12
|
+
|
13
|
+
class Error < DRbDump::Error; end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Raised when the message content is missing or too short
|
17
|
+
|
18
|
+
class DataError < Error; end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Raised when the packet is too large
|
22
|
+
|
23
|
+
class TooLarge < Error; end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Raised when the packet is not large enough to complete a message
|
27
|
+
|
28
|
+
class Premature < Error; end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Raised when the message size is incorrect or missing
|
32
|
+
|
33
|
+
class SizeError < Error; end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Creates a new loader with the given +config+ Hash. The loader uses only
|
37
|
+
# the :load_limit key to limit the maximum message size.
|
38
|
+
|
39
|
+
def initialize config
|
40
|
+
@load_limit = config[:load_limit]
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Returns the next component from a DRb message +stream+ as a
|
45
|
+
# Marshal::Structure object.
|
46
|
+
|
47
|
+
def load stream
|
48
|
+
begin
|
49
|
+
size = stream.read 4
|
50
|
+
rescue => e
|
51
|
+
raise SizeError, e.message, e.backtrace
|
52
|
+
end
|
53
|
+
|
54
|
+
raise SizeError, 'connection closed' unless size
|
55
|
+
raise Premature, 'header' if size.size < 4
|
56
|
+
|
57
|
+
size, = size.unpack 'N'
|
58
|
+
|
59
|
+
raise TooLarge, "#{size} bytes (#{@load_limit} allowed)" if
|
60
|
+
size >= @load_limit
|
61
|
+
|
62
|
+
begin
|
63
|
+
data = stream.read size
|
64
|
+
rescue => e
|
65
|
+
raise DataError, e.message, e.backtrace
|
66
|
+
end
|
67
|
+
|
68
|
+
raise DataError, 'connection closed' unless data
|
69
|
+
raise Premature, 'Marshal' if data.bytesize < size
|
70
|
+
|
71
|
+
Marshal::Structure.new data
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
##
|
2
|
+
# Contains common parts of MessageSend and MessageResult
|
3
|
+
|
4
|
+
class DRbDump::Message
|
5
|
+
|
6
|
+
##
|
7
|
+
# Creates the appropriate message instance from the next +packet+ which was
|
8
|
+
# captured by +drbdump+ on the given +stream+.
|
9
|
+
|
10
|
+
def self.from_stream drbdump, packet, stream
|
11
|
+
loader = drbdump.loader
|
12
|
+
|
13
|
+
first_chunk = loader.load stream
|
14
|
+
|
15
|
+
case first_chunk.load
|
16
|
+
when nil, Integer then
|
17
|
+
DRbDump::MessageSend.new drbdump, packet, first_chunk, stream
|
18
|
+
when true, false then
|
19
|
+
DRbDump::MessageResult.new drbdump, packet, first_chunk, stream
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Initializes a message from +packet+ captured by a +drbdump+
|
25
|
+
|
26
|
+
def initialize drbdump, packet
|
27
|
+
@drbdump = drbdump
|
28
|
+
@loader = drbdump.loader
|
29
|
+
@packet = packet
|
30
|
+
@statistics = drbdump.statistics
|
31
|
+
|
32
|
+
@source = nil
|
33
|
+
@destination = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# The resolved destination for the message.
|
38
|
+
|
39
|
+
def destination
|
40
|
+
return @destination if @destination
|
41
|
+
|
42
|
+
resolve_addresses
|
43
|
+
|
44
|
+
@destination
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Resolves source and destination addresses
|
49
|
+
|
50
|
+
def resolve_addresses # :nodoc:
|
51
|
+
resolver = @drbdump.resolver
|
52
|
+
|
53
|
+
source = @packet.source resolver
|
54
|
+
@source = "\"druby://#{source.sub(/\.(\d+)$/, ':\1')}\""
|
55
|
+
|
56
|
+
destination = @packet.destination resolver
|
57
|
+
@destination = "\"druby://#{destination.sub(/\.(\d+)$/, ':\1')}\""
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# The resolved source of the message
|
62
|
+
|
63
|
+
def source
|
64
|
+
return @source if @source
|
65
|
+
|
66
|
+
resolve_addresses
|
67
|
+
|
68
|
+
@source
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
##
|
2
|
+
# Wraps a DRb message-result after consuming it from a stream.
|
3
|
+
|
4
|
+
class DRbDump::MessageResult < DRbDump::Message
|
5
|
+
|
6
|
+
##
|
7
|
+
# Creates a new MessageResult for the creating +drbdump+ instance. The last
|
8
|
+
# packet in the message is +packet+ and the Marshal::Structure for the
|
9
|
+
# result type is +status+. The rest of the message will be loaded from
|
10
|
+
# +stream+.
|
11
|
+
|
12
|
+
def initialize drbdump, packet, status, stream
|
13
|
+
super drbdump, packet
|
14
|
+
|
15
|
+
@result = nil
|
16
|
+
@status = nil
|
17
|
+
@stream = stream
|
18
|
+
|
19
|
+
@raw_result = @loader.load stream
|
20
|
+
@raw_status = status
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# The number of allocations required to load the result.
|
25
|
+
|
26
|
+
def allocations
|
27
|
+
@raw_status.count_allocations + @raw_result.count_allocations
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Prints the message information to standard output
|
32
|
+
|
33
|
+
def display
|
34
|
+
update_statistics
|
35
|
+
|
36
|
+
return if @drbdump.quiet
|
37
|
+
|
38
|
+
message = status ? 'success' : 'exception'
|
39
|
+
arrow = status ? "\u21d0" : "\u2902"
|
40
|
+
timestamp = self.timestamp.strftime DRbDump::TIMESTAMP_FORMAT
|
41
|
+
|
42
|
+
puts "%s %s %s %s %s: %s" % [
|
43
|
+
timestamp, destination, arrow, source, message, result
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# The loaded result object
|
49
|
+
|
50
|
+
def result
|
51
|
+
return @result if @result
|
52
|
+
|
53
|
+
result = @drbdump.load_marshal_data @raw_result
|
54
|
+
|
55
|
+
@result = if DRb::DRbObject === result then
|
56
|
+
"(\"druby://#{result.__drburi}\", #{result.__drbref})"
|
57
|
+
else
|
58
|
+
result.inspect
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# The loaded status object
|
64
|
+
|
65
|
+
def status
|
66
|
+
@status ||= @raw_status.load
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# The timestamp of the last packet in the result
|
71
|
+
|
72
|
+
def timestamp
|
73
|
+
@packet.timestamp
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Updates the drbdump's statistics with information from this result.
|
78
|
+
|
79
|
+
def update_statistics # :nodoc:
|
80
|
+
@statistics.add_result self
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
##
|
2
|
+
# Wraps a DRb message-send after consuming it from a stream.
|
3
|
+
|
4
|
+
class DRbDump::MessageSend < DRbDump::Message
|
5
|
+
|
6
|
+
##
|
7
|
+
# The number of arguments, not including the block
|
8
|
+
|
9
|
+
attr_reader :argc
|
10
|
+
|
11
|
+
##
|
12
|
+
# The arguments, each as a Marshal::Structure
|
13
|
+
|
14
|
+
attr_reader :raw_argv
|
15
|
+
|
16
|
+
##
|
17
|
+
# The block as a Marshal::Structure
|
18
|
+
|
19
|
+
attr_reader :raw_block
|
20
|
+
|
21
|
+
##
|
22
|
+
# The message sent as a Marshal::Structure
|
23
|
+
|
24
|
+
attr_reader :raw_message
|
25
|
+
|
26
|
+
##
|
27
|
+
# Creates a new MessageSend for the creating +drbdump+ instance. The last
|
28
|
+
# packet in the message is +packet+ and the Marshal::Structure for the first
|
29
|
+
# argument is +receiver+. The rest of the message will be loaded from
|
30
|
+
# +stream+.
|
31
|
+
|
32
|
+
def initialize drbdump, packet, receiver, stream
|
33
|
+
super drbdump, packet
|
34
|
+
|
35
|
+
@argc = nil
|
36
|
+
@argv = nil
|
37
|
+
@block = nil
|
38
|
+
@message = nil
|
39
|
+
@raw_receiver = receiver
|
40
|
+
@stream = stream
|
41
|
+
|
42
|
+
load_message if stream
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# The number of allocations required to load the message.
|
47
|
+
|
48
|
+
def allocations
|
49
|
+
allocations = 0
|
50
|
+
|
51
|
+
allocations += @raw_receiver.count_allocations
|
52
|
+
allocations += @raw_message.count_allocations
|
53
|
+
@raw_argv.each { |arg| allocations += arg.count_allocations }
|
54
|
+
allocations += @raw_block.count_allocations
|
55
|
+
|
56
|
+
allocations
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# A string containing all loaded arguments including the block.
|
61
|
+
|
62
|
+
def arguments
|
63
|
+
arguments = argv.map { |obj| obj.inspect }
|
64
|
+
(arguments << '&block') if block
|
65
|
+
arguments.join ', '
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Number of arguments including the block
|
70
|
+
|
71
|
+
def argument_count
|
72
|
+
@argc + (block ? 1 : 0)
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# The loaded arguments
|
77
|
+
|
78
|
+
def argv
|
79
|
+
@argv ||= @raw_argv.map { |obj| @drbdump.load_marshal_data obj }
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# The loaded block
|
84
|
+
|
85
|
+
def block
|
86
|
+
@block ||= @raw_block.load
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Prints the message information to standard output
|
91
|
+
|
92
|
+
def display
|
93
|
+
update_statistics
|
94
|
+
|
95
|
+
return if @drbdump.quiet
|
96
|
+
|
97
|
+
timestamp = self.timestamp.strftime DRbDump::TIMESTAMP_FORMAT
|
98
|
+
|
99
|
+
puts "%s %s \u21d2 (%s, %p).%s(%s)" % [
|
100
|
+
timestamp, source, destination, receiver, message, arguments
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Returns the message, arguments and block for the DRb message-send in
|
106
|
+
# +stream+.
|
107
|
+
|
108
|
+
def load_message # :nodoc:
|
109
|
+
@raw_message = @loader.load @stream
|
110
|
+
@argc = @loader.load(@stream).load
|
111
|
+
@raw_argv = @argc.times.map { @loader.load @stream }
|
112
|
+
@raw_block = @loader.load @stream
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# The loaded message
|
117
|
+
|
118
|
+
def message
|
119
|
+
@message ||= @raw_message.load
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# The loaded receiver for the message
|
124
|
+
|
125
|
+
def receiver
|
126
|
+
@receiver ||= @raw_receiver.load
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Returns the timestamp for the first packet in the incomplete stream for
|
131
|
+
# +packet+ or the packet's timestamp if this is the only packet in the
|
132
|
+
# stream.
|
133
|
+
|
134
|
+
def timestamp
|
135
|
+
@drbdump.incomplete_timestamps.delete(@packet.source) || @packet.timestamp
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# Updates the drbdump's statistics with information from this message.
|
140
|
+
|
141
|
+
def update_statistics # :nodoc:
|
142
|
+
@statistics.add_message_send self
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
##
|
2
|
+
# Stores the minimum, maximum, mean, count and standard deviation for a set of
|
3
|
+
# values but not the values themselves.
|
4
|
+
|
5
|
+
class DRbDump::Statistic
|
6
|
+
|
7
|
+
##
|
8
|
+
# The number of items in the set
|
9
|
+
|
10
|
+
attr_reader :count
|
11
|
+
|
12
|
+
##
|
13
|
+
# The maximum value added
|
14
|
+
|
15
|
+
attr_reader :max
|
16
|
+
|
17
|
+
##
|
18
|
+
# The mean of all values
|
19
|
+
|
20
|
+
attr_reader :mean
|
21
|
+
|
22
|
+
##
|
23
|
+
# The minimum value added
|
24
|
+
|
25
|
+
attr_reader :min
|
26
|
+
|
27
|
+
def initialize # :nodoc:
|
28
|
+
@M_2 = 0.0
|
29
|
+
@count = 0
|
30
|
+
@max = -Float::INFINITY
|
31
|
+
@mean = 0.0
|
32
|
+
@min = Float::INFINITY
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Adds +value+ to the set of values. Returns the number of values.
|
37
|
+
|
38
|
+
def add value
|
39
|
+
@min = value if value < @min
|
40
|
+
@max = value if value > @max
|
41
|
+
@count += 1
|
42
|
+
|
43
|
+
delta = value - @mean
|
44
|
+
@mean += delta / @count
|
45
|
+
@M_2 += delta * (value - @mean)
|
46
|
+
|
47
|
+
@count
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# The average of all values
|
52
|
+
|
53
|
+
alias average mean
|
54
|
+
|
55
|
+
##
|
56
|
+
# The maximum value added
|
57
|
+
|
58
|
+
alias maximum max
|
59
|
+
|
60
|
+
##
|
61
|
+
# The minimum value added
|
62
|
+
|
63
|
+
alias minimum min
|
64
|
+
|
65
|
+
##
|
66
|
+
# The sample variance for all values
|
67
|
+
|
68
|
+
def sample_variance
|
69
|
+
sv = @M_2 / (@count - 1)
|
70
|
+
return 0.0 if sv.nan?
|
71
|
+
sv
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# The standard deviation of all values
|
76
|
+
|
77
|
+
def standard_deviation
|
78
|
+
Math.sqrt sample_variance
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# An array containing the number of values in the set, the mean and the
|
83
|
+
# standard deviation
|
84
|
+
|
85
|
+
def to_a
|
86
|
+
[@count, @min, @mean, @max, standard_deviation]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|