fluentd 0.10.35 → 0.10.36
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- data/.travis.yml +13 -0
- data/ChangeLog +9 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/buffer.rb +210 -214
- data/lib/fluent/command/fluentd.rb +4 -0
- data/lib/fluent/config.rb +1 -0
- data/lib/fluent/engine.rb +10 -10
- data/lib/fluent/output.rb +404 -406
- data/lib/fluent/plugin/buf_file.rb +146 -151
- data/lib/fluent/plugin/buf_memory.rb +62 -67
- data/lib/fluent/plugin/in_debug_agent.rb +27 -31
- data/lib/fluent/plugin/in_exec.rb +86 -90
- data/lib/fluent/plugin/in_forward.rb +171 -171
- data/lib/fluent/plugin/in_gc_stat.rb +43 -47
- data/lib/fluent/plugin/in_http.rb +214 -216
- data/lib/fluent/plugin/in_monitor_agent.rb +212 -214
- data/lib/fluent/plugin/in_object_space.rb +75 -79
- data/lib/fluent/plugin/in_status.rb +44 -50
- data/lib/fluent/plugin/in_stream.rb +159 -160
- data/lib/fluent/plugin/in_syslog.rb +149 -153
- data/lib/fluent/plugin/in_tail.rb +382 -387
- data/lib/fluent/plugin/out_copy.rb +40 -45
- data/lib/fluent/plugin/out_exec.rb +52 -57
- data/lib/fluent/plugin/out_exec_filter.rb +327 -331
- data/lib/fluent/plugin/out_file.rb +78 -74
- data/lib/fluent/plugin/out_forward.rb +410 -414
- data/lib/fluent/plugin/out_null.rb +15 -19
- data/lib/fluent/plugin/out_roundrobin.rb +63 -68
- data/lib/fluent/plugin/out_stdout.rb +9 -14
- data/lib/fluent/plugin/out_stream.rb +83 -90
- data/lib/fluent/plugin/out_test.rb +42 -46
- data/lib/fluent/supervisor.rb +15 -0
- data/lib/fluent/version.rb +1 -1
- data/test/plugin/in_stream.rb +2 -0
- data/test/plugin/out_file.rb +19 -1
- metadata +6 -5
@@ -16,103 +16,99 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
module Fluent
|
19
|
+
class ObjectSpaceInput < Input
|
20
|
+
Plugin.register_input('object_space', self)
|
19
21
|
|
22
|
+
def initialize
|
23
|
+
super
|
24
|
+
end
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def initialize
|
25
|
-
super
|
26
|
-
end
|
26
|
+
config_param :emit_interval, :time, :default => 60
|
27
|
+
config_param :tag, :string
|
28
|
+
config_param :top, :integer, :default => 15
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
class TimerWatcher < Coolio::TimerWatcher
|
31
|
+
def initialize(interval, repeat, &callback)
|
32
|
+
@callback = callback
|
33
|
+
super(interval, repeat)
|
34
|
+
end
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def on_timer
|
37
|
+
@callback.call
|
38
|
+
rescue
|
39
|
+
# TODO log?
|
40
|
+
$log.error $!.to_s
|
41
|
+
$log.error_backtrace
|
42
|
+
end
|
36
43
|
end
|
37
44
|
|
38
|
-
def
|
39
|
-
|
40
|
-
rescue
|
41
|
-
# TODO log?
|
42
|
-
$log.error $!.to_s
|
43
|
-
$log.error_backtrace
|
45
|
+
def configure(conf)
|
46
|
+
super
|
44
47
|
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def configure(conf)
|
48
|
-
super
|
49
|
-
end
|
50
|
-
|
51
|
-
def start
|
52
|
-
@loop = Coolio::Loop.new
|
53
|
-
@timer = TimerWatcher.new(@emit_interval, true, &method(:on_timer))
|
54
|
-
@loop.attach(@timer)
|
55
|
-
@thread = Thread.new(&method(:run))
|
56
|
-
end
|
57
|
-
|
58
|
-
def shutdown
|
59
|
-
@loop.watchers.each {|w| w.detach }
|
60
|
-
@loop.stop
|
61
|
-
@thread.join
|
62
|
-
end
|
63
48
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
class Counter
|
72
|
-
def initialize(klass, init_count)
|
73
|
-
@klass = klass
|
74
|
-
@count = init_count
|
49
|
+
def start
|
50
|
+
@loop = Coolio::Loop.new
|
51
|
+
@timer = TimerWatcher.new(@emit_interval, true, &method(:on_timer))
|
52
|
+
@loop.attach(@timer)
|
53
|
+
@thread = Thread.new(&method(:run))
|
75
54
|
end
|
76
55
|
|
77
|
-
def
|
78
|
-
@
|
56
|
+
def shutdown
|
57
|
+
@loop.watchers.each {|w| w.detach }
|
58
|
+
@loop.stop
|
59
|
+
@thread.join
|
79
60
|
end
|
80
61
|
|
81
|
-
def
|
82
|
-
@
|
62
|
+
def run
|
63
|
+
@loop.run
|
64
|
+
rescue
|
65
|
+
$log.error "unexpected error", :error=>$!.to_s
|
66
|
+
$log.error_backtrace
|
83
67
|
end
|
84
68
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
array = []
|
92
|
-
map = {}
|
69
|
+
class Counter
|
70
|
+
def initialize(klass, init_count)
|
71
|
+
@klass = klass
|
72
|
+
@count = init_count
|
73
|
+
end
|
93
74
|
|
94
|
-
|
95
|
-
|
96
|
-
if c = map[klass]
|
97
|
-
c.incr!
|
98
|
-
else
|
99
|
-
c = Counter.new(klass, 1)
|
100
|
-
array << c
|
101
|
-
map[klass] = c
|
75
|
+
def incr!
|
76
|
+
@count += 1
|
102
77
|
end
|
103
|
-
}
|
104
78
|
|
105
|
-
|
79
|
+
def name
|
80
|
+
@klass.name
|
81
|
+
end
|
106
82
|
|
107
|
-
|
108
|
-
|
109
|
-
break if i >= @top
|
110
|
-
record[c.name] = c.count
|
111
|
-
}
|
83
|
+
attr_reader :count
|
84
|
+
end
|
112
85
|
|
113
|
-
|
86
|
+
def on_timer
|
87
|
+
now = Engine.now
|
88
|
+
|
89
|
+
array = []
|
90
|
+
map = {}
|
91
|
+
|
92
|
+
ObjectSpace.each_object {|obj|
|
93
|
+
klass = obj.class rescue Object
|
94
|
+
if c = map[klass]
|
95
|
+
c.incr!
|
96
|
+
else
|
97
|
+
c = Counter.new(klass, 1)
|
98
|
+
array << c
|
99
|
+
map[klass] = c
|
100
|
+
end
|
101
|
+
}
|
102
|
+
|
103
|
+
array.sort_by! {|c| -c.count }
|
104
|
+
|
105
|
+
record = {}
|
106
|
+
array.each_with_index {|c,i|
|
107
|
+
break if i >= @top
|
108
|
+
record[c.name] = c.count
|
109
|
+
}
|
110
|
+
|
111
|
+
Engine.emit(@tag, now, record)
|
112
|
+
end
|
114
113
|
end
|
115
114
|
end
|
116
|
-
|
117
|
-
|
118
|
-
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
#
|
3
2
|
# Fluent
|
4
3
|
#
|
@@ -17,65 +16,60 @@
|
|
17
16
|
# limitations under the License.
|
18
17
|
#
|
19
18
|
module Fluent
|
19
|
+
class StatusInput < Input
|
20
|
+
Plugin.register_input('status', self)
|
20
21
|
|
22
|
+
def initialize
|
23
|
+
super
|
24
|
+
end
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def initialize
|
26
|
-
super
|
27
|
-
end
|
26
|
+
config_param :emit_interval, :time, :default => 60
|
27
|
+
config_param :tag, :string
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
class TimerWatcher < Coolio::TimerWatcher
|
30
|
+
def initialize(interval, repeat, &callback)
|
31
|
+
@callback = callback
|
32
|
+
super(interval, repeat)
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
def on_timer
|
36
|
+
@callback.call
|
37
|
+
rescue
|
38
|
+
# TODO log?
|
39
|
+
$log.error $!.to_s
|
40
|
+
$log.error_backtrace
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
|
-
def
|
39
|
-
|
40
|
-
rescue
|
41
|
-
# TODO log?
|
42
|
-
$log.error $!.to_s
|
43
|
-
$log.error_backtrace
|
44
|
+
def configure(conf)
|
45
|
+
super
|
44
46
|
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def configure(conf)
|
48
|
-
super
|
49
|
-
end
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
def start
|
49
|
+
@loop = Coolio::Loop.new
|
50
|
+
@timer = TimerWatcher.new(@emit_interval, true, &method(:on_timer))
|
51
|
+
@loop.attach(@timer)
|
52
|
+
@thread = Thread.new(&method(:run))
|
53
|
+
end
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
def shutdown
|
56
|
+
@loop.watchers.each {|w| w.detach }
|
57
|
+
@loop.stop
|
58
|
+
@thread.join
|
59
|
+
end
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
61
|
+
def run
|
62
|
+
@loop.run
|
63
|
+
rescue
|
64
|
+
$log.error "unexpected error", :error=>$!.to_s
|
65
|
+
$log.error_backtrace
|
66
|
+
end
|
70
67
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
68
|
+
def on_timer
|
69
|
+
now = Engine.now
|
70
|
+
Status.each {|record|
|
71
|
+
Engine.emit(@tag, now, record)
|
72
|
+
}
|
73
|
+
end
|
76
74
|
end
|
77
75
|
end
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
|
@@ -16,193 +16,192 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
module Fluent
|
19
|
+
# obsolete
|
20
|
+
class StreamInput < Input
|
21
|
+
def initialize
|
22
|
+
require 'socket'
|
23
|
+
require 'yajl'
|
24
|
+
super
|
25
|
+
end
|
19
26
|
|
27
|
+
def start
|
28
|
+
@loop = Coolio::Loop.new
|
29
|
+
@lsock = listen
|
30
|
+
@loop.attach(@lsock)
|
31
|
+
@thread = Thread.new(&method(:run))
|
32
|
+
@cached_unpacker = $use_msgpack_5 ? nil : MessagePack::Unpacker.new
|
33
|
+
end
|
20
34
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def start
|
30
|
-
@loop = Coolio::Loop.new
|
31
|
-
@lsock = listen
|
32
|
-
@loop.attach(@lsock)
|
33
|
-
@thread = Thread.new(&method(:run))
|
34
|
-
@cached_unpacker = $use_msgpack_5 ? nil : MessagePack::Unpacker.new
|
35
|
-
end
|
36
|
-
|
37
|
-
def shutdown
|
38
|
-
@loop.watchers.each {|w| w.detach }
|
39
|
-
@loop.stop
|
40
|
-
@lsock.close
|
41
|
-
@thread.join
|
42
|
-
end
|
43
|
-
|
44
|
-
#def listen
|
45
|
-
#end
|
35
|
+
def shutdown
|
36
|
+
@loop.watchers.each {|w| w.detach }
|
37
|
+
@loop.stop
|
38
|
+
@lsock.close
|
39
|
+
@thread.join
|
40
|
+
end
|
46
41
|
|
47
|
-
|
48
|
-
|
49
|
-
rescue
|
50
|
-
$log.error "unexpected error", :error=>$!.to_s
|
51
|
-
$log.error_backtrace
|
52
|
-
end
|
42
|
+
#def listen
|
43
|
+
#end
|
53
44
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
# message Forward {
|
61
|
-
# 1: string tag
|
62
|
-
# 2: list<Entry> entries
|
63
|
-
# }
|
64
|
-
#
|
65
|
-
# message PackedForward {
|
66
|
-
# 1: string tag
|
67
|
-
# 2: raw entries # msgpack stream of Entry
|
68
|
-
# }
|
69
|
-
#
|
70
|
-
# message Message {
|
71
|
-
# 1: string tag
|
72
|
-
# 2: long? time
|
73
|
-
# 3: object record
|
74
|
-
# }
|
75
|
-
def on_message(msg)
|
76
|
-
# TODO format error
|
77
|
-
tag = msg[0].to_s
|
78
|
-
entries = msg[1]
|
79
|
-
|
80
|
-
if entries.class == String
|
81
|
-
# PackedForward
|
82
|
-
es = MessagePackEventStream.new(entries, @cached_unpacker)
|
83
|
-
Engine.emit_stream(tag, es)
|
84
|
-
|
85
|
-
elsif entries.class == Array
|
86
|
-
# Forward
|
87
|
-
es = MultiEventStream.new
|
88
|
-
entries.each {|e|
|
89
|
-
time = e[0].to_i
|
90
|
-
time = (now ||= Engine.now) if time == 0
|
91
|
-
record = e[1]
|
92
|
-
es.add(time, record)
|
93
|
-
}
|
94
|
-
Engine.emit_stream(tag, es)
|
95
|
-
|
96
|
-
else
|
97
|
-
# Message
|
98
|
-
time = msg[1]
|
99
|
-
time = Engine.now if time == 0
|
100
|
-
record = msg[2]
|
101
|
-
Engine.emit(tag, time, record)
|
45
|
+
def run
|
46
|
+
@loop.run
|
47
|
+
rescue
|
48
|
+
$log.error "unexpected error", :error=>$!.to_s
|
49
|
+
$log.error_backtrace
|
102
50
|
end
|
103
|
-
end
|
104
51
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
52
|
+
protected
|
53
|
+
# message Entry {
|
54
|
+
# 1: long time
|
55
|
+
# 2: object record
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
# message Forward {
|
59
|
+
# 1: string tag
|
60
|
+
# 2: list<Entry> entries
|
61
|
+
# }
|
62
|
+
#
|
63
|
+
# message PackedForward {
|
64
|
+
# 1: string tag
|
65
|
+
# 2: raw entries # msgpack stream of Entry
|
66
|
+
# }
|
67
|
+
#
|
68
|
+
# message Message {
|
69
|
+
# 1: string tag
|
70
|
+
# 2: long? time
|
71
|
+
# 3: object record
|
72
|
+
# }
|
73
|
+
def on_message(msg)
|
74
|
+
# TODO format error
|
75
|
+
tag = msg[0].to_s
|
76
|
+
entries = msg[1]
|
77
|
+
|
78
|
+
if entries.class == String
|
79
|
+
# PackedForward
|
80
|
+
es = MessagePackEventStream.new(entries, @cached_unpacker)
|
81
|
+
Engine.emit_stream(tag, es)
|
82
|
+
|
83
|
+
elsif entries.class == Array
|
84
|
+
# Forward
|
85
|
+
es = MultiEventStream.new
|
86
|
+
entries.each {|e|
|
87
|
+
time = e[0].to_i
|
88
|
+
time = (now ||= Engine.now) if time == 0
|
89
|
+
record = e[1]
|
90
|
+
es.add(time, record)
|
91
|
+
}
|
92
|
+
Engine.emit_stream(tag, es)
|
93
|
+
|
94
|
+
else
|
95
|
+
# Message
|
96
|
+
time = msg[1]
|
97
|
+
time = Engine.now if time == 0
|
98
|
+
record = msg[2]
|
99
|
+
Engine.emit(tag, time, record)
|
111
100
|
end
|
112
|
-
$log.trace { "accepted fluent socket object_id=#{self.object_id}" }
|
113
|
-
@on_message = on_message
|
114
101
|
end
|
115
102
|
|
116
|
-
|
117
|
-
|
103
|
+
class Handler < Coolio::Socket
|
104
|
+
def initialize(io, on_message)
|
105
|
+
super(io)
|
106
|
+
if io.is_a?(TCPSocket)
|
107
|
+
opt = [1, @timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
|
108
|
+
io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
|
109
|
+
end
|
110
|
+
$log.trace { "accepted fluent socket object_id=#{self.object_id}" }
|
111
|
+
@on_message = on_message
|
112
|
+
end
|
118
113
|
|
119
|
-
|
120
|
-
first = data[0]
|
121
|
-
if first == '{' || first == '['
|
122
|
-
m = method(:on_read_json)
|
123
|
-
@y = Yajl::Parser.new
|
124
|
-
@y.on_parse_complete = @on_message
|
125
|
-
else
|
126
|
-
m = method(:on_read_msgpack)
|
127
|
-
@u = MessagePack::Unpacker.new
|
114
|
+
def on_connect
|
128
115
|
end
|
129
116
|
|
130
|
-
(
|
131
|
-
|
117
|
+
def on_read(data)
|
118
|
+
first = data[0]
|
119
|
+
if first == '{' || first == '['
|
120
|
+
m = method(:on_read_json)
|
121
|
+
@y = Yajl::Parser.new
|
122
|
+
@y.on_parse_complete = @on_message
|
123
|
+
else
|
124
|
+
m = method(:on_read_msgpack)
|
125
|
+
@u = MessagePack::Unpacker.new
|
126
|
+
end
|
127
|
+
|
128
|
+
(class << self; self; end).module_eval do
|
129
|
+
define_method(:on_read, m)
|
130
|
+
end
|
131
|
+
m.call(data)
|
132
132
|
end
|
133
|
-
m.call(data)
|
134
|
-
end
|
135
133
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
134
|
+
def on_read_json(data)
|
135
|
+
@y << data
|
136
|
+
rescue
|
137
|
+
$log.error "unexpected error", :error=>$!.to_s
|
138
|
+
$log.error_backtrace
|
139
|
+
close
|
140
|
+
end
|
143
141
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
142
|
+
def on_read_msgpack(data)
|
143
|
+
@u.feed_each(data, &@on_message)
|
144
|
+
rescue
|
145
|
+
$log.error "unexpected error", :error=>$!.to_s
|
146
|
+
$log.error_backtrace
|
147
|
+
close
|
148
|
+
end
|
151
149
|
|
152
|
-
|
153
|
-
|
150
|
+
def on_close
|
151
|
+
$log.trace { "closed fluent socket object_id=#{self.object_id}" }
|
152
|
+
end
|
154
153
|
end
|
155
154
|
end
|
156
|
-
end
|
157
155
|
|
158
156
|
|
159
|
-
# obsolete
|
160
|
-
# ForwardInput is backward compatible with TcpInput
|
161
|
-
#class TcpInput < StreamInput
|
162
|
-
# Plugin.register_input('tcp', self)
|
163
|
-
#
|
164
|
-
# config_param :port, :integer, :default => DEFAULT_LISTEN_PORT
|
165
|
-
# config_param :bind, :string, :default => '0.0.0.0'
|
166
|
-
#
|
167
|
-
# def configure(conf)
|
168
|
-
# super
|
169
|
-
# end
|
170
|
-
#
|
171
|
-
# def listen
|
172
|
-
# $log.debug "listening fluent socket on #{@bind}:#{@port}"
|
173
|
-
# Coolio::TCPServer.new(@bind, @port, Handler, method(:on_message))
|
174
|
-
# end
|
175
|
-
#end
|
176
|
-
class TcpInput < ForwardInput
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
157
|
+
# obsolete
|
158
|
+
# ForwardInput is backward compatible with TcpInput
|
159
|
+
#class TcpInput < StreamInput
|
160
|
+
# Plugin.register_input('tcp', self)
|
161
|
+
#
|
162
|
+
# config_param :port, :integer, :default => DEFAULT_LISTEN_PORT
|
163
|
+
# config_param :bind, :string, :default => '0.0.0.0'
|
164
|
+
#
|
165
|
+
# def configure(conf)
|
166
|
+
# super
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# def listen
|
170
|
+
# $log.debug "listening fluent socket on #{@bind}:#{@port}"
|
171
|
+
# Coolio::TCPServer.new(@bind, @port, Handler, method(:on_message))
|
172
|
+
# end
|
173
|
+
#end
|
174
|
+
class TcpInput < ForwardInput
|
175
|
+
Plugin.register_input('tcp', self)
|
176
|
+
|
177
|
+
def initialize
|
178
|
+
super
|
179
|
+
$log.warn "'tcp' input is obsoleted and will be removed soon. Use 'forward' instead."
|
180
|
+
end
|
182
181
|
end
|
183
|
-
end
|
184
182
|
|
185
183
|
|
186
|
-
class UnixInput < StreamInput
|
187
|
-
|
184
|
+
class UnixInput < StreamInput
|
185
|
+
Plugin.register_input('unix', self)
|
188
186
|
|
189
|
-
|
187
|
+
config_param :path, :string, :default => DEFAULT_SOCKET_PATH
|
188
|
+
config_param :backlog, :integer, :default => nil
|
190
189
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
190
|
+
def configure(conf)
|
191
|
+
super
|
192
|
+
#$log.warn "'unix' input is obsoleted and will be removed. Use 'forward' instead."
|
193
|
+
end
|
195
194
|
|
196
|
-
|
197
|
-
|
198
|
-
|
195
|
+
def listen
|
196
|
+
if File.exist?(@path)
|
197
|
+
File.unlink(@path)
|
198
|
+
end
|
199
|
+
FileUtils.mkdir_p File.dirname(@path)
|
200
|
+
$log.debug "listening fluent socket on #{@path}"
|
201
|
+
s = Coolio::UNIXServer.new(@path, Handler, method(:on_message))
|
202
|
+
s.listen(@backlog) unless @backlog.nil?
|
203
|
+
s
|
199
204
|
end
|
200
|
-
FileUtils.mkdir_p File.dirname(@path)
|
201
|
-
$log.debug "listening fluent socket on #{@path}"
|
202
|
-
Coolio::UNIXServer.new(@path, Handler, method(:on_message))
|
203
205
|
end
|
204
206
|
end
|
205
207
|
|
206
|
-
|
207
|
-
end
|
208
|
-
|