rbsim 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.hgignore +6 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +12 -0
  5. data/Gemfile.lock +66 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +960 -0
  8. data/TODO +28 -0
  9. data/basic_sim.rb +62 -0
  10. data/fast-tcpn.rb +3 -0
  11. data/lib/rbsim.rb +14 -0
  12. data/lib/rbsim/dsl.rb +30 -0
  13. data/lib/rbsim/dsl/infrastructure.rb +48 -0
  14. data/lib/rbsim/dsl/mapping.rb +32 -0
  15. data/lib/rbsim/dsl/process.rb +129 -0
  16. data/lib/rbsim/dsl/program.rb +10 -0
  17. data/lib/rbsim/experiment.rb +110 -0
  18. data/lib/rbsim/hlmodel.rb +25 -0
  19. data/lib/rbsim/hlmodel/infrastructure.rb +116 -0
  20. data/lib/rbsim/hlmodel/mapping.rb +5 -0
  21. data/lib/rbsim/hlmodel/process.rb +152 -0
  22. data/lib/rbsim/numeric_units.rb +107 -0
  23. data/lib/rbsim/simulator.rb +184 -0
  24. data/lib/rbsim/statistics.rb +77 -0
  25. data/lib/rbsim/tokens.rb +146 -0
  26. data/lib/rbsim/version.rb +3 -0
  27. data/new_process.rb +49 -0
  28. data/rbsim.gemspec +42 -0
  29. data/show_readme.rb +15 -0
  30. data/sim.rb +142 -0
  31. data/sim_bamboo.rb +251 -0
  32. data/sim_process.rb +83 -0
  33. data/sim_process_dsl.rb +58 -0
  34. data/spec/dsl/infrastructure_nets_spec.rb +39 -0
  35. data/spec/dsl/infrastructure_nodes_spec.rb +72 -0
  36. data/spec/dsl/infrastructure_routes_spec.rb +44 -0
  37. data/spec/dsl/mapping_spec.rb +70 -0
  38. data/spec/dsl/process_spec.rb +56 -0
  39. data/spec/dsl/program_spec.rb +36 -0
  40. data/spec/dsl_and_hlmodel/new_process_spec.rb +235 -0
  41. data/spec/hlmodel/net_spec.rb +112 -0
  42. data/spec/hlmodel/process_spec.rb +242 -0
  43. data/spec/hlmodel/route_spec.rb +47 -0
  44. data/spec/hlmodel/routes_spec.rb +44 -0
  45. data/spec/integration/basic_simulation_spec.rb +104 -0
  46. data/spec/integration/net_spec.rb +44 -0
  47. data/spec/integration/process_spec.rb +117 -0
  48. data/spec/integration/rbsim_spec.rb +40 -0
  49. data/spec/simulator/logger_spec.rb +35 -0
  50. data/spec/simulator/stats_spec.rb +93 -0
  51. data/spec/spec_helper.rb +26 -0
  52. data/spec/statistics_spec.rb +300 -0
  53. data/spec/tcpn/add_route_spec.rb +55 -0
  54. data/spec/tcpn/cpu_spec.rb +53 -0
  55. data/spec/tcpn/map_data_spec.rb +37 -0
  56. data/spec/tcpn/network_spec.rb +163 -0
  57. data/spec/tcpn/register_event_spec.rb +48 -0
  58. data/spec/tcpn/route_to_self_spec.rb +53 -0
  59. data/spec/tcpn/stats_spec.rb +77 -0
  60. data/spec/tokens/data_queue_obsolete.rb +121 -0
  61. data/spec/tokens/data_queue_spec.rb +111 -0
  62. data/spec/units_spec.rb +48 -0
  63. data/tcpn/model.rb +6 -0
  64. data/tcpn/model/add_route.rb +78 -0
  65. data/tcpn/model/application.rb +250 -0
  66. data/tcpn/model/cpu.rb +75 -0
  67. data/tcpn/model/map_data.rb +42 -0
  68. data/tcpn/model/network.rb +108 -0
  69. data/tcpn/model/register_event.rb +89 -0
  70. data/tcpn/model/stats.rb +46 -0
  71. 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
@@ -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,6 @@
1
+ page "rbsim model" do
2
+ sub_page "model/application.rb"
3
+ sub_page "model/map_data.rb"
4
+ sub_page "model/add_route.rb"
5
+ sub_page "model/network.rb"
6
+ end
@@ -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