rbsim 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.hgignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +66 -0
- data/LICENSE.txt +674 -0
- data/README.md +960 -0
- data/TODO +28 -0
- data/basic_sim.rb +62 -0
- data/fast-tcpn.rb +3 -0
- data/lib/rbsim.rb +14 -0
- data/lib/rbsim/dsl.rb +30 -0
- data/lib/rbsim/dsl/infrastructure.rb +48 -0
- data/lib/rbsim/dsl/mapping.rb +32 -0
- data/lib/rbsim/dsl/process.rb +129 -0
- data/lib/rbsim/dsl/program.rb +10 -0
- data/lib/rbsim/experiment.rb +110 -0
- data/lib/rbsim/hlmodel.rb +25 -0
- data/lib/rbsim/hlmodel/infrastructure.rb +116 -0
- data/lib/rbsim/hlmodel/mapping.rb +5 -0
- data/lib/rbsim/hlmodel/process.rb +152 -0
- data/lib/rbsim/numeric_units.rb +107 -0
- data/lib/rbsim/simulator.rb +184 -0
- data/lib/rbsim/statistics.rb +77 -0
- data/lib/rbsim/tokens.rb +146 -0
- data/lib/rbsim/version.rb +3 -0
- data/new_process.rb +49 -0
- data/rbsim.gemspec +42 -0
- data/show_readme.rb +15 -0
- data/sim.rb +142 -0
- data/sim_bamboo.rb +251 -0
- data/sim_process.rb +83 -0
- data/sim_process_dsl.rb +58 -0
- data/spec/dsl/infrastructure_nets_spec.rb +39 -0
- data/spec/dsl/infrastructure_nodes_spec.rb +72 -0
- data/spec/dsl/infrastructure_routes_spec.rb +44 -0
- data/spec/dsl/mapping_spec.rb +70 -0
- data/spec/dsl/process_spec.rb +56 -0
- data/spec/dsl/program_spec.rb +36 -0
- data/spec/dsl_and_hlmodel/new_process_spec.rb +235 -0
- data/spec/hlmodel/net_spec.rb +112 -0
- data/spec/hlmodel/process_spec.rb +242 -0
- data/spec/hlmodel/route_spec.rb +47 -0
- data/spec/hlmodel/routes_spec.rb +44 -0
- data/spec/integration/basic_simulation_spec.rb +104 -0
- data/spec/integration/net_spec.rb +44 -0
- data/spec/integration/process_spec.rb +117 -0
- data/spec/integration/rbsim_spec.rb +40 -0
- data/spec/simulator/logger_spec.rb +35 -0
- data/spec/simulator/stats_spec.rb +93 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/statistics_spec.rb +300 -0
- data/spec/tcpn/add_route_spec.rb +55 -0
- data/spec/tcpn/cpu_spec.rb +53 -0
- data/spec/tcpn/map_data_spec.rb +37 -0
- data/spec/tcpn/network_spec.rb +163 -0
- data/spec/tcpn/register_event_spec.rb +48 -0
- data/spec/tcpn/route_to_self_spec.rb +53 -0
- data/spec/tcpn/stats_spec.rb +77 -0
- data/spec/tokens/data_queue_obsolete.rb +121 -0
- data/spec/tokens/data_queue_spec.rb +111 -0
- data/spec/units_spec.rb +48 -0
- data/tcpn/model.rb +6 -0
- data/tcpn/model/add_route.rb +78 -0
- data/tcpn/model/application.rb +250 -0
- data/tcpn/model/cpu.rb +75 -0
- data/tcpn/model/map_data.rb +42 -0
- data/tcpn/model/network.rb +108 -0
- data/tcpn/model/register_event.rb +89 -0
- data/tcpn/model/stats.rb +46 -0
- metadata +221 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rbsim/hlmodel/infrastructure.rb'
|
2
|
+
require 'rbsim/hlmodel/process.rb'
|
3
|
+
require 'rbsim/hlmodel/mapping.rb'
|
4
|
+
|
5
|
+
module RBSim
|
6
|
+
module HLModel
|
7
|
+
|
8
|
+
Model = Struct.new :nodes, :nets, :routes, :programs, :processes, :mapping, :simulator do
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
self.programs = {}
|
12
|
+
self.processes = {}
|
13
|
+
self.mapping = Mapping.new
|
14
|
+
self.routes = Tokens::RoutesToken.new
|
15
|
+
self.each_pair do |attr, val|
|
16
|
+
if val.nil?
|
17
|
+
self.send "#{attr}=".to_sym, []
|
18
|
+
end
|
19
|
+
end
|
20
|
+
self.simulator = nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module RBSim
|
2
|
+
module HLModel
|
3
|
+
|
4
|
+
Node = Struct.new :name, :cpus
|
5
|
+
class Node
|
6
|
+
CPU = Struct.new :performance, :node, :tags
|
7
|
+
end
|
8
|
+
|
9
|
+
class Net
|
10
|
+
attr_reader :name, :bw, :delay, :drop, :tags
|
11
|
+
|
12
|
+
InvalidTypeOfDropParameter = Class.new RuntimeError
|
13
|
+
InvalidValueOfDropProbability = Class.new RuntimeError
|
14
|
+
|
15
|
+
def initialize(name, bw, delay = 0, drop = 0, tags = {})
|
16
|
+
@name, @bw, @delay = name, bw, delay
|
17
|
+
@drop = drop
|
18
|
+
@tags = tags
|
19
|
+
unless @drop.kind_of?(Proc) || @drop.kind_of?(Numeric)
|
20
|
+
raise InvalidTypeOfDropParameter.new(@drop.class)
|
21
|
+
end
|
22
|
+
if @drop.kind_of? Numeric
|
23
|
+
if @drop > 1 || @drop < 0
|
24
|
+
raise InvalidValueOfDropProbability.new(@drop)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@drop_next = drop_next?
|
28
|
+
end
|
29
|
+
|
30
|
+
def drop?
|
31
|
+
drop_this = @drop_next
|
32
|
+
@drop_next = drop_next?
|
33
|
+
drop_this
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def drop_next?
|
39
|
+
return @drop.call if @drop.kind_of? Proc
|
40
|
+
|
41
|
+
# a little optimization ;-)
|
42
|
+
return true if @drop == 1
|
43
|
+
return false if @drop == 0
|
44
|
+
|
45
|
+
return rand <= @drop
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Routes
|
50
|
+
def initialize
|
51
|
+
@routes = {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def add(route)
|
55
|
+
key = [route.src, route.dst]
|
56
|
+
@routes[key] ||= []
|
57
|
+
@routes[key] << route
|
58
|
+
if route.twoway?
|
59
|
+
@routes[key.reverse] ||= []
|
60
|
+
@routes[key.reverse] << route
|
61
|
+
end
|
62
|
+
end
|
63
|
+
alias << add
|
64
|
+
|
65
|
+
def find(src, dst)
|
66
|
+
routes = @routes[[src, dst]]
|
67
|
+
return nil if routes.nil?
|
68
|
+
route = if routes.size == 1
|
69
|
+
routes.first
|
70
|
+
else
|
71
|
+
routes[rand(routes.size)]
|
72
|
+
end
|
73
|
+
if route.src == src
|
74
|
+
route
|
75
|
+
else
|
76
|
+
route.reverse!
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
Route = Struct.new :src, :dst, :via, :twoway do
|
83
|
+
|
84
|
+
CannotReverseOnewayRoute = Class.new RuntimeError
|
85
|
+
|
86
|
+
def initialize(*)
|
87
|
+
super
|
88
|
+
self.twoway = false unless self.twoway
|
89
|
+
@net_number = 0
|
90
|
+
end
|
91
|
+
|
92
|
+
def next_net
|
93
|
+
raise StopIteration if @net_number >= via.length
|
94
|
+
net = via[@net_number]
|
95
|
+
@net_number += 1
|
96
|
+
net
|
97
|
+
end
|
98
|
+
|
99
|
+
def has_next_net?
|
100
|
+
@net_number < via.length
|
101
|
+
end
|
102
|
+
|
103
|
+
def reverse!
|
104
|
+
raise CannotReverseOnewayRoute unless self.twoway
|
105
|
+
self.via = self.via.reverse
|
106
|
+
self.src, self.dst = self.dst, self.src
|
107
|
+
@net_enum = nil
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def twoway?
|
112
|
+
twoway
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module RBSim
|
2
|
+
module HLModel
|
3
|
+
|
4
|
+
class Process
|
5
|
+
NoHandlerForUserEvent = Class.new RuntimeError
|
6
|
+
InvalidEventType = Class.new RuntimeError
|
7
|
+
InvalidSystemEventPassed = Class.new RuntimeError
|
8
|
+
NoEventToServe = Class.new RuntimeError
|
9
|
+
NotAssignedToNode = Class.new RuntimeError
|
10
|
+
|
11
|
+
attr_reader :name, :program, :functions, :tags
|
12
|
+
attr_accessor :node
|
13
|
+
# to how many fragments should be
|
14
|
+
# divided data sent by this process?
|
15
|
+
attr_accessor :data_fragmentation
|
16
|
+
|
17
|
+
alias id name
|
18
|
+
|
19
|
+
# +name+: name of this process used to assign it to a node
|
20
|
+
# +program+: name of program running in this process (if any name was given); this is just for information
|
21
|
+
def initialize(name, program = nil, tags = {})
|
22
|
+
@event_handlers = { data_received: generic_data_received_handler }
|
23
|
+
@event_queue = []
|
24
|
+
@name = name
|
25
|
+
@program = program
|
26
|
+
@tags = tags || {}
|
27
|
+
@functions = {}
|
28
|
+
@data_fragmentation = 1
|
29
|
+
end
|
30
|
+
|
31
|
+
# define a new reusable function for this program
|
32
|
+
def function(name, &block)
|
33
|
+
@functions[name] = block
|
34
|
+
end
|
35
|
+
|
36
|
+
# define event handler
|
37
|
+
def on_event(event, &block)
|
38
|
+
@event_handlers[event] = block
|
39
|
+
end
|
40
|
+
|
41
|
+
# event just happened
|
42
|
+
def enqueue_event(event, args = nil)
|
43
|
+
handler = nil # system event has no handling code defined here
|
44
|
+
# it must be handled by somethig external, like
|
45
|
+
# TCPN transition!
|
46
|
+
unless system_event_names.include? event
|
47
|
+
handler = @event_handlers[event]
|
48
|
+
if handler.nil?
|
49
|
+
raise NoHandlerForUserEvent.new(event)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@event_queue << { name: event, block: handler, args: args }
|
53
|
+
end
|
54
|
+
|
55
|
+
# serve first event if it is a user event
|
56
|
+
def serve_user_event
|
57
|
+
check_if_assigned!
|
58
|
+
if has_system_event?
|
59
|
+
raise InvalidEventType.new("#{@event_queue.first[:name]} is not a user event!")
|
60
|
+
end
|
61
|
+
event = @event_queue.shift
|
62
|
+
event[:block].call self, event[:args]
|
63
|
+
end
|
64
|
+
|
65
|
+
# serve first event if it is a system event
|
66
|
+
def serve_system_event(name)
|
67
|
+
check_if_assigned!
|
68
|
+
unless has_event?
|
69
|
+
raise NoEventToServe.new
|
70
|
+
end
|
71
|
+
unless has_event? name
|
72
|
+
raise InvalidSystemEventPassed.new("You tried to serve: #{name}, but first in queue is: #{@event_queue.first[:name]}")
|
73
|
+
end
|
74
|
+
if has_user_event?
|
75
|
+
raise InvalidEventType.new("#{@event_queue.first[:name]} is not a system event!")
|
76
|
+
end
|
77
|
+
event = @event_queue.shift
|
78
|
+
{ name: event[:name], args: event[:args] }
|
79
|
+
end
|
80
|
+
|
81
|
+
# is there a user event to serve?
|
82
|
+
def has_user_event?
|
83
|
+
return false unless has_event?
|
84
|
+
return false if system_event_names.include? @event_queue.first[:name]
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
# is there a system event to serve?
|
89
|
+
def has_system_event?
|
90
|
+
return false unless has_event?
|
91
|
+
return true if system_event_names.include? @event_queue.first[:name]
|
92
|
+
false
|
93
|
+
end
|
94
|
+
|
95
|
+
# is there any event to serve?
|
96
|
+
def has_event?(name = nil)
|
97
|
+
return false if @event_queue.empty?
|
98
|
+
return true if name == nil
|
99
|
+
return true if @event_queue.first[:name] == name
|
100
|
+
false
|
101
|
+
end
|
102
|
+
|
103
|
+
# returns name of the first event in queue
|
104
|
+
def first_event
|
105
|
+
event = @event_queue.first
|
106
|
+
if event.nil?
|
107
|
+
nil
|
108
|
+
else
|
109
|
+
event[:name]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def handlers_size
|
114
|
+
@event_handlers.size
|
115
|
+
end
|
116
|
+
|
117
|
+
def event_queue_size
|
118
|
+
@event_queue.size
|
119
|
+
end
|
120
|
+
|
121
|
+
# system events need special handling, by special
|
122
|
+
# transitions, e.g. :cpu event requires a cpu token
|
123
|
+
# :delay_for requires change in timestamp, etc.
|
124
|
+
# handlers for system events must be implemented
|
125
|
+
# in simulator!
|
126
|
+
def system_event_names
|
127
|
+
[ :cpu, :delay_for, :send_data, :new_process, :register_event, :log, :stats_start, :stats_stop, :stats, :stats_save ]
|
128
|
+
end
|
129
|
+
|
130
|
+
# Start new process on the same node
|
131
|
+
# used when creating new process during simulation
|
132
|
+
def new(program = nil)
|
133
|
+
self.class.new @node, program
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def check_if_assigned!
|
138
|
+
if @node.nil?
|
139
|
+
raise NotAssignedToNode.new("process #{@name} will not serve events until assigned to a node!")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def generic_data_received_handler
|
144
|
+
proc do |process, data|
|
145
|
+
STDERR.puts "WARNING! Process #{process.name} on node #{process.node} received data, but has no handler defined! Define handler for event :data_received! Data packege will be dropped! Received data: #{data}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#
|
2
|
+
# This file extends Ruby Numeric class by methods
|
3
|
+
# used in RBSim to desciribe units of time,
|
4
|
+
# data volume and network speed.
|
5
|
+
#
|
6
|
+
# Native data volume unit is one bit
|
7
|
+
# Native network speed unit is one bit per second
|
8
|
+
# Time unit is one jiffie, defined by Numric::RBSIM_JIFFIES_PER_SECOND
|
9
|
+
class Numeric
|
10
|
+
|
11
|
+
#
|
12
|
+
# Time units
|
13
|
+
#
|
14
|
+
|
15
|
+
|
16
|
+
# Defines unit of time -- jiffie is the smallest
|
17
|
+
# time unit that can be accounted by simulator
|
18
|
+
RBSIM_JIFFIES_PER_SECOND = 1000000
|
19
|
+
|
20
|
+
def seconds
|
21
|
+
self * RBSIM_JIFFIES_PER_SECOND
|
22
|
+
end
|
23
|
+
|
24
|
+
def miliseconds
|
25
|
+
self.seconds / 1000
|
26
|
+
end
|
27
|
+
|
28
|
+
def microseconds
|
29
|
+
self.miliseconds / 1000
|
30
|
+
end
|
31
|
+
|
32
|
+
def minutes
|
33
|
+
self.seconds * 60
|
34
|
+
end
|
35
|
+
|
36
|
+
def hours
|
37
|
+
self.minutes * 60
|
38
|
+
end
|
39
|
+
|
40
|
+
def days
|
41
|
+
self.hours * 24
|
42
|
+
end
|
43
|
+
|
44
|
+
def in_seconds
|
45
|
+
self / RBSIM_JIFFIES_PER_SECOND
|
46
|
+
end
|
47
|
+
|
48
|
+
def in_miliseconds
|
49
|
+
self * 1000 / RBSIM_JIFFIES_PER_SECOND
|
50
|
+
end
|
51
|
+
|
52
|
+
def in_microseconds
|
53
|
+
self * 1000 * 1000 / RBSIM_JIFFIES_PER_SECOND
|
54
|
+
end
|
55
|
+
|
56
|
+
def in_minutes
|
57
|
+
self.in_seconds / 60
|
58
|
+
end
|
59
|
+
|
60
|
+
def in_hours
|
61
|
+
self.in_minutes / 60
|
62
|
+
end
|
63
|
+
|
64
|
+
def in_days
|
65
|
+
self.in_hours / 24
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Data volume units
|
70
|
+
#
|
71
|
+
|
72
|
+
def bytes
|
73
|
+
self * 8
|
74
|
+
end
|
75
|
+
|
76
|
+
def in_bytes
|
77
|
+
self / 8
|
78
|
+
end
|
79
|
+
|
80
|
+
def in_bits
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
def bits
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Network throuput units
|
90
|
+
#
|
91
|
+
|
92
|
+
def bps
|
93
|
+
self.to_f.in_seconds
|
94
|
+
end
|
95
|
+
|
96
|
+
def Bps
|
97
|
+
(self * 8).to_f.in_seconds
|
98
|
+
end
|
99
|
+
|
100
|
+
def in_bps
|
101
|
+
self.seconds
|
102
|
+
end
|
103
|
+
|
104
|
+
def in_Bps
|
105
|
+
(self / 8).seconds
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
module RBSim
|
2
|
+
|
3
|
+
class Simulator
|
4
|
+
attr_reader :clock
|
5
|
+
# To how many fragments should be divided data
|
6
|
+
# sent over the network?
|
7
|
+
attr_accessor :data_fragmentation
|
8
|
+
|
9
|
+
# Create new simulator
|
10
|
+
# +block+ defines new model
|
11
|
+
# +params+ will be passed as block parameter to the model
|
12
|
+
def initialize(params = {}, &block)
|
13
|
+
@block = block
|
14
|
+
@params = params
|
15
|
+
@logger = default_logger
|
16
|
+
@stats_collector = Statistics.new
|
17
|
+
@resource_stats_collector = Statistics.new
|
18
|
+
@clock = 0
|
19
|
+
@data_fragmentation = 1
|
20
|
+
end
|
21
|
+
|
22
|
+
def data_fragmentation=(d)
|
23
|
+
raise "TCPN already initialized. Too late to set data fragmentation" unless @tcpn.nil?
|
24
|
+
@data_fragmentation = d
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
simulator.run
|
29
|
+
end
|
30
|
+
|
31
|
+
def stop
|
32
|
+
simulator.stop
|
33
|
+
end
|
34
|
+
|
35
|
+
def hlmodel
|
36
|
+
if @hlmodel.nil?
|
37
|
+
@hlmodel = RBSim::HLModel::Model.new
|
38
|
+
@hlmodel.simulator = self
|
39
|
+
Docile.dsl_eval(RBSim::DSL.new(@hlmodel), @params, &@block)
|
40
|
+
end
|
41
|
+
@hlmodel
|
42
|
+
end
|
43
|
+
|
44
|
+
def tcpn
|
45
|
+
if @tcpn.nil?
|
46
|
+
@tcpn = FastTCPN.read File.expand_path '../../../tcpn/model.rb', __FILE__
|
47
|
+
hlmodel.nets.each do |net|
|
48
|
+
@tcpn.add_marking_for 'net', net
|
49
|
+
end
|
50
|
+
|
51
|
+
hlmodel.nodes.each do |node|
|
52
|
+
node.cpus.each do |cpu|
|
53
|
+
cpu.node = node.name
|
54
|
+
@tcpn.add_marking_for 'CPU', cpu
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
hlmodel.processes.each do |name, process|
|
59
|
+
process.node = hlmodel.mapping[name]
|
60
|
+
process.data_fragmentation = data_fragmentation
|
61
|
+
@tcpn.add_marking_for 'process', process
|
62
|
+
@tcpn.add_marking_for 'data to receive', Tokens::DataQueueToken.new(process.name, process.tags)
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
@tcpn.add_marking_for 'routes', hlmodel.routes
|
67
|
+
@tcpn.add_marking_for 'mapping', hlmodel.mapping
|
68
|
+
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
@tcpn
|
73
|
+
end
|
74
|
+
|
75
|
+
def simulator
|
76
|
+
if @simulator.nil?
|
77
|
+
@simulator = tcpn
|
78
|
+
|
79
|
+
set_logger_callbacks
|
80
|
+
set_stats_collector_callbacks
|
81
|
+
set_clock_callbacks
|
82
|
+
|
83
|
+
end
|
84
|
+
@simulator
|
85
|
+
end
|
86
|
+
|
87
|
+
def logger(&block)
|
88
|
+
@logger = block
|
89
|
+
end
|
90
|
+
|
91
|
+
def stats
|
92
|
+
{ application: @stats_collector, resources: @resource_stats_collector }
|
93
|
+
end
|
94
|
+
|
95
|
+
# FIXME: not tested!
|
96
|
+
def stats_save(file)
|
97
|
+
File.open file, 'w' do |f|
|
98
|
+
f.puts Marshal.dump(stats_data)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def default_logger
|
105
|
+
proc do |clock, message|
|
106
|
+
puts "%.3f: #{message}" % (clock.to_f.in_seconds)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_logger_callbacks
|
111
|
+
@simulator.cb_for :transition, :after do |t, e|
|
112
|
+
if e.transition == 'event::log'
|
113
|
+
message = e.binding['process'].value.serve_system_event(:log)[:args]
|
114
|
+
@logger.call e.clock, message
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def set_stats_collector_callbacks
|
120
|
+
@simulator.cb_for :transition, :after do |t, e|
|
121
|
+
if e.transition == "event::stats"
|
122
|
+
process = e.binding['process'].value
|
123
|
+
event = process.first_event
|
124
|
+
params = process.serve_system_event(event)[:args]
|
125
|
+
@stats_collector.event event.to_s.sub(/^stats_/,'').to_sym, params, e.clock
|
126
|
+
elsif e.transition == "event::cpu"
|
127
|
+
cpu = e.binding['CPU'].value
|
128
|
+
@resource_stats_collector.event :start, cpu.tags.merge({ resource: 'CPU', node: cpu.node }), e.clock
|
129
|
+
elsif e.transition == "event::cpu_finished"
|
130
|
+
cpu = e.binding['working CPU'].value[:cpu]
|
131
|
+
@resource_stats_collector.event :stop, cpu.tags.merge({ resource: 'CPU', node: cpu.node }), e.clock
|
132
|
+
elsif e.transition == "transmitted"
|
133
|
+
process = e.binding['data after net'].value.dst
|
134
|
+
queue = e.binding['data to receive'].value
|
135
|
+
@resource_stats_collector.event :start, queue.process_tags.merge({ resource: 'DATAQ WAIT', process: process }), e.clock
|
136
|
+
elsif e.transition == "event::data_received"
|
137
|
+
process = e.binding['process'].value
|
138
|
+
@resource_stats_collector.event :stop, process.tags.merge({ resource: 'DATAQ WAIT', process: process.name }), e.clock
|
139
|
+
elsif e.transition == "net"
|
140
|
+
net = e.binding['net'].value
|
141
|
+
dropped = e.binding['net'].value.drop?
|
142
|
+
if dropped
|
143
|
+
@resource_stats_collector.event :stats, net.tags.merge({ event: 'NET DROP', net: net.name }), e.clock
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
@simulator.cb_for :place, :remove do |t, e|
|
149
|
+
if e.place == 'net'
|
150
|
+
net = e.tokens.first.value
|
151
|
+
@resource_stats_collector.event :start, net.tags.merge({ resource: 'NET', name: net.name }), e.clock
|
152
|
+
end
|
153
|
+
end
|
154
|
+
@simulator.cb_for :place, :add do |t, e|
|
155
|
+
if e.place == 'net'
|
156
|
+
net = e.tokens.first[:val]
|
157
|
+
ts = e.tokens.first[:ts]
|
158
|
+
@resource_stats_collector.event :stop, net.tags.merge({ resource: 'NET', name: net.name }), ts
|
159
|
+
elsif e.place == 'data to receive'
|
160
|
+
queue = e.tokens.first[:val]
|
161
|
+
process_name = queue.process_name
|
162
|
+
process_tags = queue.process_tags
|
163
|
+
@resource_stats_collector.event :save,
|
164
|
+
{ value: queue.length, tags: process_tags.merge({ resource: 'DATAQ LEN', process: process_name }) },
|
165
|
+
e.tcpn.clock
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def set_clock_callbacks
|
171
|
+
@simulator.cb_for :clock, :after do |t, e|
|
172
|
+
self.clock = e.clock
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def clock=(clock)
|
177
|
+
@clock = clock
|
178
|
+
@stats_collector.clock = clock
|
179
|
+
@resource_stats_collector.clock = clock
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|