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,121 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RBSim::Tokens::DataQueue do
|
4
|
+
|
5
|
+
let(:apache1_first) { RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1') }
|
6
|
+
let(:apache1_second) { RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1') }
|
7
|
+
let(:apache1_third) { RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1') }
|
8
|
+
let(:apache5_first) { RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache5') }
|
9
|
+
let(:apache3_first) { RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache3') }
|
10
|
+
|
11
|
+
describe "enqueues data for each process separatelly" do
|
12
|
+
subject do
|
13
|
+
queue = RBSim::Tokens::DataQueueToken.new
|
14
|
+
queue.put apache1_first
|
15
|
+
queue.put apache5_first
|
16
|
+
queue.put apache1_second
|
17
|
+
queue.put apache3_first
|
18
|
+
queue.put apache1_third
|
19
|
+
queue
|
20
|
+
end
|
21
|
+
|
22
|
+
it "has 3 data packages for apache1" do
|
23
|
+
expect(subject.get 'apache1').to eq apache1_first
|
24
|
+
expect(subject.get 'apache1').to eq apache1_second
|
25
|
+
expect(subject.get 'apache1').to eq apache1_third
|
26
|
+
expect(subject.get 'apache1').to be nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "has 1 data package for apache5" do
|
30
|
+
expect(subject.get 'apache5').to eq apache5_first
|
31
|
+
expect(subject.get 'apache5').to be nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has 1 data package for apache3" do
|
35
|
+
expect(subject.get 'apache3').to eq apache3_first
|
36
|
+
expect(subject.get 'apache3').to be nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it "has no data packages for apache0" do
|
40
|
+
expect(subject.get 'apache0').to be nil
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "collects queue lengths for processes" do
|
46
|
+
context "when putting something to the queue" do
|
47
|
+
subject do
|
48
|
+
queue = RBSim::Tokens::DataQueueToken.new
|
49
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1')
|
50
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache5')
|
51
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1')
|
52
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache3')
|
53
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1')
|
54
|
+
queue
|
55
|
+
end
|
56
|
+
it "has 3 packages for apache1" do
|
57
|
+
expect(subject.length_for('apache1')).to eq 3
|
58
|
+
end
|
59
|
+
|
60
|
+
it "has 1 package for apache5" do
|
61
|
+
expect(subject.length_for('apache5')).to eq 1
|
62
|
+
end
|
63
|
+
|
64
|
+
it "has 1 package for apache3" do
|
65
|
+
expect(subject.length_for('apache3')).to eq 1
|
66
|
+
end
|
67
|
+
|
68
|
+
it "has no packages for apache333" do
|
69
|
+
expect(subject.length_for('apache333')).to eq 0
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when putting and getting from the queue" do
|
75
|
+
subject do
|
76
|
+
queue = RBSim::Tokens::DataQueueToken.new
|
77
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache0')
|
78
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache2')
|
79
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache2')
|
80
|
+
queue.get 'apache0'
|
81
|
+
queue.get 'apache2'
|
82
|
+
queue
|
83
|
+
end
|
84
|
+
|
85
|
+
it "has 1 package for apache2" do
|
86
|
+
expect(subject.length_for('apache2')).to eq 1
|
87
|
+
end
|
88
|
+
|
89
|
+
it "has no packages for apache0" do
|
90
|
+
expect(subject.length_for('apache0')).to eq 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "remembers last involved process" do
|
97
|
+
context "when putting" do
|
98
|
+
subject do
|
99
|
+
queue = RBSim::Tokens::DataQueueToken.new
|
100
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache0')
|
101
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache2')
|
102
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1')
|
103
|
+
queue
|
104
|
+
end
|
105
|
+
its(:last_involved_queue) { should eq 'apache1' }
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when getting" do
|
109
|
+
subject do
|
110
|
+
queue = RBSim::Tokens::DataQueueToken.new
|
111
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache0')
|
112
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache2')
|
113
|
+
queue.put RBSim::Tokens::DataToken.new(:node01, 'wget', size: 1024, to: 'apache1')
|
114
|
+
queue.get 'apache0'
|
115
|
+
queue
|
116
|
+
end
|
117
|
+
its(:last_involved_queue) { should eq 'apache0' }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RBSim::Tokens::DataQueue do
|
4
|
+
subject { RBSim::Tokens::DataQueue.new(:apache) }
|
5
|
+
|
6
|
+
let(:data_id) { 12332432 }
|
7
|
+
let(:other_data_id) { 23634657 }
|
8
|
+
|
9
|
+
let(:data1) do
|
10
|
+
data = RBSim::Tokens::Data.new(data_id, :node01, :apache1, to: :apache, size: 1024)
|
11
|
+
data.fragments = 3
|
12
|
+
data
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:data2) do
|
16
|
+
data = RBSim::Tokens::Data.new(data_id, :node01, :apache1, to: :apache, size: 1024)
|
17
|
+
data.fragments = 3
|
18
|
+
data
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:data3) do
|
22
|
+
data = RBSim::Tokens::Data.new(data_id, :node01, :apache1, to: :apache, size: 1024)
|
23
|
+
data.fragments = 3
|
24
|
+
data
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:other_data1) do
|
28
|
+
data = RBSim::Tokens::Data.new(other_data_id, :node01, :apache1, to: :apache, size: 1024)
|
29
|
+
data.fragments = 2
|
30
|
+
data
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:other_data2) do
|
34
|
+
data = RBSim::Tokens::Data.new(other_data_id, :node01, :apache1, to: :apache, size: 1024)
|
35
|
+
data.fragments = 2
|
36
|
+
data
|
37
|
+
end
|
38
|
+
|
39
|
+
shared_examples_for "empty queue" do
|
40
|
+
it "is empty" do
|
41
|
+
expect(subject.empty?).to be true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "has length 0" do
|
45
|
+
expect(subject.length).to eq 0
|
46
|
+
end
|
47
|
+
|
48
|
+
it "dequeues nil" do
|
49
|
+
expect(subject.get).to be_nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "raises error when fragment count is not set" do
|
54
|
+
data = RBSim::Tokens::Data.new(other_data_id, :node01, :apache1, to: :apache, size: 1024)
|
55
|
+
expect { subject.put data }.to raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "until all fragments arrive" do
|
59
|
+
before :each do
|
60
|
+
subject.put data1
|
61
|
+
subject.put data2
|
62
|
+
subject.put other_data1
|
63
|
+
end
|
64
|
+
|
65
|
+
it_behaves_like "empty queue"
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "when all fragments arrive" do
|
70
|
+
before :each do
|
71
|
+
subject.put data1
|
72
|
+
subject.put data2
|
73
|
+
subject.put other_data1
|
74
|
+
subject.put data3
|
75
|
+
end
|
76
|
+
|
77
|
+
it "is not empty" do
|
78
|
+
expect(subject.empty?).to be false
|
79
|
+
end
|
80
|
+
|
81
|
+
it "has length 1" do
|
82
|
+
expect(subject.length).to eq 1
|
83
|
+
end
|
84
|
+
|
85
|
+
it "dequeues data" do
|
86
|
+
expect(subject.get.data_id).to eq data_id
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "when data is dequeued" do
|
90
|
+
before :each do
|
91
|
+
subject.get
|
92
|
+
end
|
93
|
+
|
94
|
+
it_behaves_like "empty queue"
|
95
|
+
|
96
|
+
|
97
|
+
describe "when another data arrives" do
|
98
|
+
before :each do
|
99
|
+
subject.put other_data2
|
100
|
+
end
|
101
|
+
|
102
|
+
it "dequeues data" do
|
103
|
+
expect(subject.get.data_id).to eq other_data_id
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/spec/units_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Numeric units" do
|
4
|
+
|
5
|
+
let(:jiffies) { Numeric::RBSIM_JIFFIES_PER_SECOND }
|
6
|
+
|
7
|
+
shared_examples "has correct units" do
|
8
|
+
# volume units
|
9
|
+
its(:bits) { should eq subject }
|
10
|
+
its(:bytes) { should eq subject * 8 }
|
11
|
+
its(:in_bits) { should eq subject }
|
12
|
+
its(:in_bytes) { should eq subject / 8 }
|
13
|
+
|
14
|
+
# network units
|
15
|
+
its(:bps) { should eq subject.to_f / jiffies}
|
16
|
+
its(:Bps) { should eq subject.to_f * 8 / jiffies }
|
17
|
+
its(:in_bps) { should eq subject * jiffies }
|
18
|
+
its(:in_Bps) { should eq subject / 8 * jiffies }
|
19
|
+
|
20
|
+
# time units
|
21
|
+
its(:seconds) { should eq subject * jiffies }
|
22
|
+
its(:miliseconds) { should eq subject * jiffies / 1000 }
|
23
|
+
its(:microseconds) { should eq subject * jiffies / 1000000 }
|
24
|
+
its(:minutes) { should eq subject * jiffies * 60 }
|
25
|
+
its(:hours) { should eq subject * jiffies * 60 * 60 }
|
26
|
+
its(:days) { should eq subject * jiffies * 60 * 60 * 24 }
|
27
|
+
|
28
|
+
its(:in_seconds) { should eq subject / jiffies }
|
29
|
+
its(:in_miliseconds) { should eq subject * 1000 / jiffies }
|
30
|
+
its(:in_microseconds) { should eq subject * 1000 * 1000 / jiffies }
|
31
|
+
its(:in_minutes) { should be_within(1.0/jiffies).of( subject / (jiffies * 60) ) }
|
32
|
+
its(:in_hours) { should be_within(1.0/jiffies).of( subject / (jiffies * 60 * 60) ) }
|
33
|
+
its(:in_days) { should be_within(1.0/jiffies).of( subject / (jiffies * 60 * 60 * 24) ) }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 128 do
|
37
|
+
include_examples 'has correct units'
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 1.5 do
|
41
|
+
include_examples 'has correct units'
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 50000 do
|
45
|
+
include_examples 'has correct units'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/tcpn/model.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# add route to data
|
2
|
+
# before network transmission
|
3
|
+
page 'add route' do
|
4
|
+
RouteNotFound = Class.new RuntimeError
|
5
|
+
|
6
|
+
data_for_network = place 'data for network'
|
7
|
+
routes = place 'routes'
|
8
|
+
data_with_route = place 'data with route'
|
9
|
+
data_to_receive = place 'data to receive', process_name: :process_name
|
10
|
+
|
11
|
+
class TCPNAddRouteToData
|
12
|
+
def initialize(binding)
|
13
|
+
@data = binding['data for network'].value
|
14
|
+
@queue = binding['data to receive'].value
|
15
|
+
@routes = binding['routes'].value
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_route_token(clock)
|
19
|
+
if to_self?
|
20
|
+
nil
|
21
|
+
else
|
22
|
+
@data.route = route
|
23
|
+
{ ts: clock, val: @data }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_self_token(clock)
|
28
|
+
if to_self?
|
29
|
+
@queue.put @data
|
30
|
+
end
|
31
|
+
{ ts: clock, val: @queue }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def to_self?
|
37
|
+
@data.src_node == @data.dst_node
|
38
|
+
end
|
39
|
+
|
40
|
+
def route
|
41
|
+
r = @routes.find @data.src_node, @data.dst_node
|
42
|
+
if r.nil?
|
43
|
+
raise RouteNotFound.new("from #{@data.src_node} to #{@data.dst_node}")
|
44
|
+
end
|
45
|
+
r
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
transition 'add_route' do
|
50
|
+
input data_for_network
|
51
|
+
input routes
|
52
|
+
input data_to_receive
|
53
|
+
|
54
|
+
output routes do |binding, clock|
|
55
|
+
binding['routes']
|
56
|
+
end
|
57
|
+
|
58
|
+
output data_with_route do |binding, clock|
|
59
|
+
TCPNAddRouteToData.new(binding).with_route_token(clock)
|
60
|
+
end
|
61
|
+
|
62
|
+
output data_to_receive do |binding, clock|
|
63
|
+
TCPNAddRouteToData.new(binding).to_self_token(clock)
|
64
|
+
end
|
65
|
+
|
66
|
+
sentry do |marking_for, clock, result|
|
67
|
+
marking_for['data for network'].each do |data|
|
68
|
+
marking_for['data to receive'].each(:process_name, data.value.dst) do |queue|
|
69
|
+
routes = marking_for['routes'].first
|
70
|
+
result << { 'data for network' => data,
|
71
|
+
'data to receive' => queue,
|
72
|
+
'routes' => routes }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
@@ -0,0 +1,250 @@
|
|
1
|
+
page 'application' do
|
2
|
+
process = timed_place 'process', { first_event: :first_event, user_event: :has_user_event?, name: :name }
|
3
|
+
data_to_send = place 'data to send'
|
4
|
+
mapping = place 'mapping'
|
5
|
+
data_to_receive = place 'data to receive', empty: :empty?
|
6
|
+
|
7
|
+
# model of CPU load by application logic
|
8
|
+
sub_page "cpu.rb"
|
9
|
+
|
10
|
+
# statistics
|
11
|
+
sub_page "stats.rb"
|
12
|
+
|
13
|
+
# new event from user (register_event statement)
|
14
|
+
sub_page "register_event.rb"
|
15
|
+
|
16
|
+
# Delay process execution for specified time.
|
17
|
+
# args: { time: time for which we should wait }
|
18
|
+
class EventDelayFor
|
19
|
+
def initialize(binding)
|
20
|
+
@process = binding['process'].value
|
21
|
+
@event = @process.serve_system_event :delay_for
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_token(clock)
|
25
|
+
ts = clock + @event[:args][:time].to_i
|
26
|
+
{ val: @process, ts: ts }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
transition 'event::delay_for' do
|
31
|
+
input process
|
32
|
+
output process do |binding, clock|
|
33
|
+
EventDelayFor.new(binding).process_token(clock)
|
34
|
+
end
|
35
|
+
|
36
|
+
sentry do |marking_for, clock, result|
|
37
|
+
marking_for['process'].each(:first_event, :delay_for) do |p|
|
38
|
+
result << { 'process' => p }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
=begin
|
42
|
+
guard do |binding, clock|
|
43
|
+
binding[:process][:val].has_event? :delay_for
|
44
|
+
end
|
45
|
+
=end
|
46
|
+
end
|
47
|
+
|
48
|
+
transition 'event::serve_user' do
|
49
|
+
input process
|
50
|
+
|
51
|
+
output process do |binding, clock|
|
52
|
+
process = binding['process'].value
|
53
|
+
process.serve_user_event
|
54
|
+
process
|
55
|
+
end
|
56
|
+
|
57
|
+
sentry do |marking_for, clock, result|
|
58
|
+
marking_for['process'].each(:user_event, true) do |p|
|
59
|
+
result << { 'process' => p }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
=begin
|
64
|
+
guard do |binding, clock|
|
65
|
+
binding[:process][:val].has_user_event?
|
66
|
+
end
|
67
|
+
=end
|
68
|
+
end
|
69
|
+
|
70
|
+
transition 'event::send_data' do
|
71
|
+
input process
|
72
|
+
|
73
|
+
# Sending data to anothe node.
|
74
|
+
# args: { to: destination process name,
|
75
|
+
# size: volume of send data,
|
76
|
+
# type: type of send data (to use in HLModel),
|
77
|
+
# content: content of send data (to use in HLModel) }
|
78
|
+
class EventSendData
|
79
|
+
def initialize(bndng)
|
80
|
+
@process = bndng['process'].value
|
81
|
+
@event = @process.serve_system_event :send_data
|
82
|
+
fragments = [
|
83
|
+
@process.data_fragmentation,
|
84
|
+
@event[:args][:size].to_i / 1500.bytes
|
85
|
+
].min
|
86
|
+
fragments = 1 if fragments == 0
|
87
|
+
@data = fragments.times.map do
|
88
|
+
d = RBSim::Tokens::DataToken.new(self.object_id, @process.node, @process.name, @event[:args])
|
89
|
+
d.fragments = fragments
|
90
|
+
d
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def data_token(clock)
|
95
|
+
@data.map { |d| { val: d, ts: clock } }
|
96
|
+
end
|
97
|
+
|
98
|
+
def process_token(clock)
|
99
|
+
{ val: @process, ts: clock }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
output process do |binding, clock|
|
104
|
+
EventSendData.new(binding).process_token clock
|
105
|
+
end
|
106
|
+
|
107
|
+
output data_to_send do |binding, clock|
|
108
|
+
EventSendData.new(binding).data_token clock
|
109
|
+
end
|
110
|
+
|
111
|
+
sentry do |marking_for, clock, result|
|
112
|
+
marking_for['process'].each(:first_event, :send_data) do |p|
|
113
|
+
result << { 'process' => p }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
=begin
|
118
|
+
guard do |binding, clock|
|
119
|
+
binding[:process][:val].has_event? :send_data
|
120
|
+
end
|
121
|
+
=end
|
122
|
+
end
|
123
|
+
|
124
|
+
transition 'event::new_process' do
|
125
|
+
input process
|
126
|
+
input mapping
|
127
|
+
|
128
|
+
# Creating new process on the same node
|
129
|
+
# args: { program: program name for new process (optional),
|
130
|
+
# constructor: block called as constructor of new process (adds initial events),
|
131
|
+
# constructor_args: args passed to the constructor }
|
132
|
+
class EventNewProcess
|
133
|
+
def initialize(binding)
|
134
|
+
@process = binding['process'].value
|
135
|
+
@event = @process.serve_system_event :new_process
|
136
|
+
@new_process = @event[:args][:constructor].call @event[:args][:constructor_args]
|
137
|
+
@mapping = binding['mapping'].value
|
138
|
+
@mapping[@new_process.name] = @new_process.node
|
139
|
+
end
|
140
|
+
|
141
|
+
def process_tokens(clock)
|
142
|
+
[ { ts: clock, val: @process }, { ts: clock, val: @new_process } ]
|
143
|
+
end
|
144
|
+
|
145
|
+
def mapping_token(clock)
|
146
|
+
{ ts: clock, val: @mapping }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
output process do |binding, clock|
|
151
|
+
EventNewProcess.new(binding).process_tokens(clock)
|
152
|
+
end
|
153
|
+
|
154
|
+
output mapping do |binding, clock|
|
155
|
+
EventNewProcess.new(binding).mapping_token(clock)
|
156
|
+
end
|
157
|
+
|
158
|
+
sentry do |marking_for, clock, result|
|
159
|
+
marking_for['process'].each(:first_event, :new_process) do |p|
|
160
|
+
mapping = marking_for['mapping'].first
|
161
|
+
result << { 'process' => p , 'mapping' => mapping}
|
162
|
+
end
|
163
|
+
end
|
164
|
+
=begin
|
165
|
+
guard do |binding, clock|
|
166
|
+
binding[:process][:val].has_event? :new_process
|
167
|
+
end
|
168
|
+
=end
|
169
|
+
end
|
170
|
+
|
171
|
+
transition 'event::data_received' do
|
172
|
+
input process
|
173
|
+
input data_to_receive
|
174
|
+
|
175
|
+
class EventDataReceived
|
176
|
+
def initialize(binding)
|
177
|
+
@process = binding['process'].value
|
178
|
+
@queue = binding['data to receive'].value
|
179
|
+
@data = @queue.get
|
180
|
+
@process.enqueue_event :data_received, @data
|
181
|
+
end
|
182
|
+
|
183
|
+
def process_token(clock)
|
184
|
+
{ ts: clock, val: @process }
|
185
|
+
end
|
186
|
+
|
187
|
+
def queue_token(clock)
|
188
|
+
{ ts: clock, val: @queue }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
output process do |binding, clock|
|
193
|
+
EventDataReceived.new(binding).process_token(clock)
|
194
|
+
end
|
195
|
+
|
196
|
+
output data_to_receive do |binding, clock|
|
197
|
+
EventDataReceived.new(binding).queue_token(clock)
|
198
|
+
end
|
199
|
+
|
200
|
+
sentry do |marking_for, clock, result|
|
201
|
+
marking_for['data to receive'].each(:empty, false) do |queue|
|
202
|
+
marking_for['process'].each(:name, queue.value.process_name) do |process|
|
203
|
+
result << { 'process' => process, 'data to receive' => queue }
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
=begin
|
209
|
+
guard do |binding, clock|
|
210
|
+
process = binding[:process][:val]
|
211
|
+
data = binding[:queue][:val].get process.name
|
212
|
+
!data.nil?
|
213
|
+
end
|
214
|
+
=end
|
215
|
+
end
|
216
|
+
|
217
|
+
transition 'event::log' do
|
218
|
+
input process
|
219
|
+
|
220
|
+
# Log message from process
|
221
|
+
# args: log message
|
222
|
+
class EventLog
|
223
|
+
def initialize(binding)
|
224
|
+
@process = binding['process'].value
|
225
|
+
@event = @process.serve_system_event :log
|
226
|
+
end
|
227
|
+
|
228
|
+
def process_token(clock)
|
229
|
+
{ val: @process, ts: clock }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
output process do |binding, clock|
|
234
|
+
EventLog.new(binding).process_token(clock)
|
235
|
+
end
|
236
|
+
|
237
|
+
sentry do |marking_for, clock, result|
|
238
|
+
marking_for['process'].each(:first_event, :log) do |p|
|
239
|
+
result << { 'process' => p }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
=begin
|
244
|
+
guard do |binding, clock|
|
245
|
+
binding[:process][:val].has_event? :log
|
246
|
+
end
|
247
|
+
=end
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|