rbsim 0.0.3
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.
- 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
|