fluentd 0.12.43 → 0.14.0

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.

Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +6 -0
  3. data/.gitignore +2 -0
  4. data/.travis.yml +33 -21
  5. data/CONTRIBUTING.md +1 -0
  6. data/ChangeLog +1239 -0
  7. data/README.md +0 -25
  8. data/Rakefile +2 -1
  9. data/Vagrantfile +17 -0
  10. data/appveyor.yml +35 -0
  11. data/example/filter_stdout.conf +5 -5
  12. data/example/in_forward.conf +2 -2
  13. data/example/in_http.conf +2 -2
  14. data/example/in_out_forward.conf +17 -0
  15. data/example/in_syslog.conf +2 -2
  16. data/example/in_tail.conf +2 -2
  17. data/example/in_tcp.conf +2 -2
  18. data/example/in_udp.conf +2 -2
  19. data/example/out_copy.conf +4 -4
  20. data/example/out_file.conf +2 -2
  21. data/example/out_forward.conf +2 -2
  22. data/example/out_forward_buf_file.conf +23 -0
  23. data/example/v0_12_filter.conf +8 -8
  24. data/fluent.conf +29 -0
  25. data/fluentd.gemspec +18 -11
  26. data/lib/fluent/agent.rb +60 -58
  27. data/lib/fluent/command/cat.rb +1 -1
  28. data/lib/fluent/command/debug.rb +7 -5
  29. data/lib/fluent/command/fluentd.rb +97 -2
  30. data/lib/fluent/compat/call_super_mixin.rb +67 -0
  31. data/lib/fluent/compat/filter.rb +50 -0
  32. data/lib/fluent/compat/formatter.rb +109 -0
  33. data/lib/fluent/compat/input.rb +50 -0
  34. data/lib/fluent/compat/output.rb +617 -0
  35. data/lib/fluent/compat/output_chain.rb +60 -0
  36. data/lib/fluent/compat/parser.rb +163 -0
  37. data/lib/fluent/compat/propagate_default.rb +62 -0
  38. data/lib/fluent/config.rb +23 -20
  39. data/lib/fluent/config/configure_proxy.rb +119 -70
  40. data/lib/fluent/config/dsl.rb +5 -18
  41. data/lib/fluent/config/element.rb +72 -8
  42. data/lib/fluent/config/error.rb +0 -3
  43. data/lib/fluent/config/literal_parser.rb +0 -2
  44. data/lib/fluent/config/parser.rb +4 -4
  45. data/lib/fluent/config/section.rb +39 -28
  46. data/lib/fluent/config/types.rb +2 -13
  47. data/lib/fluent/config/v1_parser.rb +1 -3
  48. data/lib/fluent/configurable.rb +48 -16
  49. data/lib/fluent/daemon.rb +15 -0
  50. data/lib/fluent/engine.rb +26 -52
  51. data/lib/fluent/env.rb +6 -4
  52. data/lib/fluent/event.rb +58 -11
  53. data/lib/fluent/event_router.rb +5 -5
  54. data/lib/fluent/filter.rb +2 -50
  55. data/lib/fluent/formatter.rb +4 -293
  56. data/lib/fluent/input.rb +2 -32
  57. data/lib/fluent/label.rb +2 -2
  58. data/lib/fluent/load.rb +3 -2
  59. data/lib/fluent/log.rb +107 -38
  60. data/lib/fluent/match.rb +0 -36
  61. data/lib/fluent/mixin.rb +117 -7
  62. data/lib/fluent/msgpack_factory.rb +62 -0
  63. data/lib/fluent/output.rb +7 -612
  64. data/lib/fluent/output_chain.rb +23 -0
  65. data/lib/fluent/parser.rb +4 -800
  66. data/lib/fluent/plugin.rb +100 -121
  67. data/lib/fluent/plugin/bare_output.rb +63 -0
  68. data/lib/fluent/plugin/base.rb +121 -0
  69. data/lib/fluent/plugin/buf_file.rb +101 -182
  70. data/lib/fluent/plugin/buf_memory.rb +9 -92
  71. data/lib/fluent/plugin/buffer.rb +473 -0
  72. data/lib/fluent/plugin/buffer/chunk.rb +135 -0
  73. data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
  74. data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
  75. data/lib/fluent/plugin/exec_util.rb +80 -75
  76. data/lib/fluent/plugin/file_util.rb +33 -28
  77. data/lib/fluent/plugin/file_wrapper.rb +120 -0
  78. data/lib/fluent/plugin/filter.rb +51 -0
  79. data/lib/fluent/plugin/filter_grep.rb +13 -40
  80. data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
  81. data/lib/fluent/plugin/formatter.rb +93 -0
  82. data/lib/fluent/plugin/formatter_csv.rb +48 -0
  83. data/lib/fluent/plugin/formatter_hash.rb +32 -0
  84. data/lib/fluent/plugin/formatter_json.rb +47 -0
  85. data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
  86. data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
  87. data/lib/fluent/plugin/formatter_out_file.rb +45 -0
  88. data/lib/fluent/plugin/formatter_single_value.rb +34 -0
  89. data/lib/fluent/plugin/formatter_stdout.rb +39 -0
  90. data/lib/fluent/plugin/in_debug_agent.rb +4 -0
  91. data/lib/fluent/plugin/in_dummy.rb +22 -18
  92. data/lib/fluent/plugin/in_exec.rb +18 -8
  93. data/lib/fluent/plugin/in_forward.rb +36 -79
  94. data/lib/fluent/plugin/in_gc_stat.rb +4 -0
  95. data/lib/fluent/plugin/in_http.rb +21 -18
  96. data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
  97. data/lib/fluent/plugin/in_object_space.rb +6 -1
  98. data/lib/fluent/plugin/in_stream.rb +7 -3
  99. data/lib/fluent/plugin/in_syslog.rb +46 -95
  100. data/lib/fluent/plugin/in_tail.rb +58 -640
  101. data/lib/fluent/plugin/in_tcp.rb +8 -1
  102. data/lib/fluent/plugin/in_udp.rb +8 -18
  103. data/lib/fluent/plugin/input.rb +33 -0
  104. data/lib/fluent/plugin/multi_output.rb +95 -0
  105. data/lib/fluent/plugin/out_buffered_null.rb +59 -0
  106. data/lib/fluent/plugin/out_copy.rb +11 -7
  107. data/lib/fluent/plugin/out_exec.rb +15 -11
  108. data/lib/fluent/plugin/out_exec_filter.rb +18 -10
  109. data/lib/fluent/plugin/out_file.rb +34 -5
  110. data/lib/fluent/plugin/out_forward.rb +25 -19
  111. data/lib/fluent/plugin/out_null.rb +0 -14
  112. data/lib/fluent/plugin/out_roundrobin.rb +11 -7
  113. data/lib/fluent/plugin/out_stdout.rb +5 -7
  114. data/lib/fluent/plugin/out_stream.rb +3 -1
  115. data/lib/fluent/plugin/output.rb +979 -0
  116. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  117. data/lib/fluent/plugin/parser.rb +244 -0
  118. data/lib/fluent/plugin/parser_apache.rb +24 -0
  119. data/lib/fluent/plugin/parser_apache2.rb +84 -0
  120. data/lib/fluent/plugin/parser_apache_error.rb +21 -0
  121. data/lib/fluent/plugin/parser_csv.rb +31 -0
  122. data/lib/fluent/plugin/parser_json.rb +79 -0
  123. data/lib/fluent/plugin/parser_ltsv.rb +50 -0
  124. data/lib/fluent/plugin/parser_multiline.rb +102 -0
  125. data/lib/fluent/plugin/parser_nginx.rb +24 -0
  126. data/lib/fluent/plugin/parser_none.rb +36 -0
  127. data/lib/fluent/plugin/parser_syslog.rb +82 -0
  128. data/lib/fluent/plugin/parser_tsv.rb +37 -0
  129. data/lib/fluent/plugin/socket_util.rb +119 -117
  130. data/lib/fluent/plugin/storage.rb +84 -0
  131. data/lib/fluent/plugin/storage_local.rb +116 -0
  132. data/lib/fluent/plugin/string_util.rb +16 -13
  133. data/lib/fluent/plugin_helper.rb +39 -0
  134. data/lib/fluent/plugin_helper/child_process.rb +298 -0
  135. data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
  136. data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
  137. data/lib/fluent/plugin_helper/event_loop.rb +118 -0
  138. data/lib/fluent/plugin_helper/retry_state.rb +177 -0
  139. data/lib/fluent/plugin_helper/storage.rb +308 -0
  140. data/lib/fluent/plugin_helper/thread.rb +147 -0
  141. data/lib/fluent/plugin_helper/timer.rb +85 -0
  142. data/lib/fluent/plugin_id.rb +63 -0
  143. data/lib/fluent/process.rb +21 -30
  144. data/lib/fluent/registry.rb +21 -9
  145. data/lib/fluent/root_agent.rb +115 -40
  146. data/lib/fluent/supervisor.rb +330 -320
  147. data/lib/fluent/system_config.rb +42 -18
  148. data/lib/fluent/test.rb +6 -1
  149. data/lib/fluent/test/base.rb +23 -3
  150. data/lib/fluent/test/driver/base.rb +247 -0
  151. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  152. data/lib/fluent/test/driver/filter.rb +35 -0
  153. data/lib/fluent/test/driver/input.rb +31 -0
  154. data/lib/fluent/test/driver/output.rb +78 -0
  155. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  156. data/lib/fluent/test/filter_test.rb +0 -1
  157. data/lib/fluent/test/formatter_test.rb +2 -1
  158. data/lib/fluent/test/input_test.rb +23 -17
  159. data/lib/fluent/test/output_test.rb +28 -39
  160. data/lib/fluent/test/parser_test.rb +1 -1
  161. data/lib/fluent/time.rb +104 -1
  162. data/lib/fluent/{status.rb → unique_id.rb} +15 -24
  163. data/lib/fluent/version.rb +1 -1
  164. data/lib/fluent/winsvc.rb +72 -0
  165. data/test/compat/test_calls_super.rb +164 -0
  166. data/test/config/test_config_parser.rb +83 -0
  167. data/test/config/test_configurable.rb +547 -274
  168. data/test/config/test_configure_proxy.rb +146 -29
  169. data/test/config/test_dsl.rb +3 -181
  170. data/test/config/test_element.rb +274 -0
  171. data/test/config/test_literal_parser.rb +1 -1
  172. data/test/config/test_section.rb +79 -7
  173. data/test/config/test_system_config.rb +21 -0
  174. data/test/config/test_types.rb +3 -26
  175. data/test/helper.rb +78 -8
  176. data/test/plugin/test_bare_output.rb +118 -0
  177. data/test/plugin/test_base.rb +75 -0
  178. data/test/plugin/test_buf_file.rb +420 -521
  179. data/test/plugin/test_buf_memory.rb +32 -194
  180. data/test/plugin/test_buffer.rb +981 -0
  181. data/test/plugin/test_buffer_chunk.rb +110 -0
  182. data/test/plugin/test_buffer_file_chunk.rb +770 -0
  183. data/test/plugin/test_buffer_memory_chunk.rb +265 -0
  184. data/test/plugin/test_filter.rb +255 -0
  185. data/test/plugin/test_filter_grep.rb +2 -73
  186. data/test/plugin/test_filter_record_transformer.rb +24 -68
  187. data/test/plugin/test_filter_stdout.rb +6 -6
  188. data/test/plugin/test_in_debug_agent.rb +2 -0
  189. data/test/plugin/test_in_dummy.rb +11 -17
  190. data/test/plugin/test_in_exec.rb +6 -25
  191. data/test/plugin/test_in_forward.rb +112 -151
  192. data/test/plugin/test_in_gc_stat.rb +2 -0
  193. data/test/plugin/test_in_http.rb +106 -157
  194. data/test/plugin/test_in_object_space.rb +21 -5
  195. data/test/plugin/test_in_stream.rb +14 -13
  196. data/test/plugin/test_in_syslog.rb +30 -275
  197. data/test/plugin/test_in_tail.rb +95 -282
  198. data/test/plugin/test_in_tcp.rb +14 -0
  199. data/test/plugin/test_in_udp.rb +21 -67
  200. data/test/plugin/test_input.rb +122 -0
  201. data/test/plugin/test_multi_output.rb +180 -0
  202. data/test/plugin/test_out_buffered_null.rb +79 -0
  203. data/test/plugin/test_out_copy.rb +15 -2
  204. data/test/plugin/test_out_exec.rb +75 -25
  205. data/test/plugin/test_out_exec_filter.rb +74 -8
  206. data/test/plugin/test_out_file.rb +61 -7
  207. data/test/plugin/test_out_forward.rb +92 -15
  208. data/test/plugin/test_out_roundrobin.rb +1 -0
  209. data/test/plugin/test_out_stdout.rb +22 -13
  210. data/test/plugin/test_out_stream.rb +18 -0
  211. data/test/plugin/test_output.rb +515 -0
  212. data/test/plugin/test_output_as_buffered.rb +1540 -0
  213. data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
  214. data/test/plugin/test_output_as_buffered_retries.rb +808 -0
  215. data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
  216. data/test/plugin/test_output_as_standard.rb +362 -0
  217. data/test/plugin/test_owned_by.rb +35 -0
  218. data/test/plugin/test_storage.rb +167 -0
  219. data/test/plugin/test_storage_local.rb +8 -0
  220. data/test/plugin_helper/test_child_process.rb +599 -0
  221. data/test/plugin_helper/test_compat_parameters.rb +175 -0
  222. data/test/plugin_helper/test_event_emitter.rb +51 -0
  223. data/test/plugin_helper/test_event_loop.rb +52 -0
  224. data/test/plugin_helper/test_retry_state.rb +399 -0
  225. data/test/plugin_helper/test_storage.rb +411 -0
  226. data/test/plugin_helper/test_thread.rb +164 -0
  227. data/test/plugin_helper/test_timer.rb +100 -0
  228. data/test/scripts/exec_script.rb +0 -6
  229. data/test/scripts/fluent/plugin/out_test.rb +3 -0
  230. data/test/test_config.rb +13 -4
  231. data/test/test_event.rb +24 -13
  232. data/test/test_event_router.rb +8 -7
  233. data/test/test_event_time.rb +187 -0
  234. data/test/test_formatter.rb +13 -51
  235. data/test/test_input.rb +1 -1
  236. data/test/test_log.rb +239 -16
  237. data/test/test_mixin.rb +1 -1
  238. data/test/test_output.rb +53 -66
  239. data/test/test_parser.rb +105 -323
  240. data/test/test_plugin_helper.rb +81 -0
  241. data/test/test_root_agent.rb +4 -52
  242. data/test/test_supervisor.rb +272 -0
  243. data/test/test_unique_id.rb +47 -0
  244. metadata +181 -55
  245. data/CHANGELOG.md +0 -710
  246. data/lib/fluent/buffer.rb +0 -365
  247. data/lib/fluent/plugin/filter_parser.rb +0 -107
  248. data/lib/fluent/plugin/in_status.rb +0 -76
  249. data/lib/fluent/test/helpers.rb +0 -86
  250. data/test/plugin/data/log/foo/bar2 +0 -0
  251. data/test/plugin/test_filter_parser.rb +0 -744
  252. data/test/plugin/test_in_status.rb +0 -38
  253. data/test/test_buffer.rb +0 -624
@@ -0,0 +1,308 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'monitor'
18
+ require 'forwardable'
19
+
20
+ require 'fluent/plugin'
21
+ require 'fluent/plugin/storage'
22
+ require 'fluent/plugin_helper/thread'
23
+ require 'fluent/plugin_helper/timer'
24
+ require 'fluent/config/element'
25
+
26
+ module Fluent
27
+ module PluginHelper
28
+ module Storage
29
+ include Fluent::PluginHelper::Thread
30
+ include Fluent::PluginHelper::Timer
31
+
32
+ StorageState = Struct.new(:storage, :running)
33
+
34
+ def storage_create(usage: '', type: nil, conf: nil)
35
+ s = @_storages[usage]
36
+ if s && s.running
37
+ return s.storage
38
+ elsif !s
39
+ unless type
40
+ raise ArgumentError, "BUG: type not specified without configuration"
41
+ end
42
+ storage = Plugin.new_storage(type, parent: self)
43
+ config = case conf
44
+ when Fluent::Config::Element
45
+ conf
46
+ when Hash
47
+ conf = Hash[conf.map{|k,v| [k.to_s, v]}]
48
+ Fluent::Config::Element.new('storage', '', conf, [])
49
+ when nil
50
+ Fluent::Config::Element.new('storage', '', {}, [])
51
+ else
52
+ raise ArgumentError, "BUG: conf must be a Element, Hash (or unspecified), but '#{conf.class}'"
53
+ end
54
+ storage.configure(config)
55
+ s = @_storages[usage] = StorageState.new(wrap_instance(storage), false)
56
+ end
57
+
58
+ s.storage.load
59
+
60
+ if s.storage.autosave && !s.storage.persistent
61
+ timer_execute(:storage_autosave, s.storage.autosave_interval, repeat: true) do
62
+ begin
63
+ s.storage.save
64
+ rescue => e
65
+ log.error "plugin storage failed to save its data", usage: usage, type: type, error: e
66
+ end
67
+ end
68
+ end
69
+ s.running = true
70
+ s.storage
71
+ end
72
+
73
+ def self.included(mod)
74
+ mod.instance_eval do
75
+ # minimum section definition to instantiate storage plugin instances
76
+ config_section :storage, required: false, multi: true, param_name: :storage_configs do
77
+ config_argument :usage, :string, default: ''
78
+ config_param :@type, :string, default: Fluent::Plugin::Storage::DEFAULT_TYPE
79
+ end
80
+ end
81
+ end
82
+
83
+ attr_reader :_storages # for tests
84
+
85
+ def initialize
86
+ super
87
+ @_storages = {} # usage => storage_state
88
+ @_storages_mutex = Mutex.new
89
+ end
90
+
91
+ def configure(conf)
92
+ super
93
+
94
+ @storage_configs.each do |section|
95
+ if @_storages[section.usage]
96
+ raise Fluent::ConfigError, "duplicated storages configured: #{section.usage}"
97
+ end
98
+ config = conf.elements(name: 'storage', arg: section.usage).first
99
+ raise "storage section with argument '#{section.usage}' not found. it may be a bug." unless config
100
+
101
+ storage = Plugin.new_storage(section[:@type])
102
+ storage.owner = self
103
+ storage.configure(config)
104
+ @_storages[section.usage] = StorageState.new(wrap_instance(storage), false)
105
+ end
106
+ end
107
+
108
+ def stop
109
+ super
110
+ # timer stops automatically
111
+ end
112
+
113
+ def shutdown
114
+ @_storages.each_pair do |usage, s|
115
+ begin
116
+ s.storage.save if s.storage.save_at_shutdown
117
+ rescue => e
118
+ log.error "unexpected error while saving data of plugin storages", usage: usage, storage: s.storage, error: e
119
+ end
120
+ end
121
+
122
+ super
123
+ end
124
+
125
+ def close
126
+ @_storages.each_pair do |usage, s|
127
+ begin
128
+ s.storage.close
129
+ rescue => e
130
+ log.error "unexpected error while closing plugin storages", usage: usage, storage: s.storage, error: e
131
+ end
132
+ s.running = false
133
+ end
134
+
135
+ super
136
+ end
137
+
138
+ def terminate
139
+ @_storages.each_pair do |usage, s|
140
+ begin
141
+ s.storage.terminate
142
+ rescue => e
143
+ log.error "unexpected error while terminating plugin storages", usage: usage, storage: s.storage, error: e
144
+ end
145
+ end
146
+ @_storages = {}
147
+
148
+ super
149
+ end
150
+
151
+ def wrap_instance(storage)
152
+ if storage.persistent && storage.persistent_always?
153
+ storage
154
+ elsif storage.persistent
155
+ PersistentWrapper.new(storage)
156
+ elsif !storage.synchronized?
157
+ SynchronizeWrapper.new(storage)
158
+ else
159
+ storage
160
+ end
161
+ end
162
+
163
+ class PersistentWrapper
164
+ # PersistentWrapper always provides synchronized operations
165
+ extend Forwardable
166
+
167
+ def initialize(storage)
168
+ @storage = storage
169
+ @monitor = Monitor.new
170
+ end
171
+
172
+ def_delegators :@storage, :autosave_interval, :save_at_shutdown
173
+ def_delegators :@storage, :close, :terminate
174
+
175
+ def persistent_always?
176
+ true
177
+ end
178
+
179
+ def persistent
180
+ true
181
+ end
182
+
183
+ def autosave
184
+ false
185
+ end
186
+
187
+ def synchronized?
188
+ true
189
+ end
190
+
191
+ def implementation
192
+ @storage
193
+ end
194
+
195
+ def load
196
+ @monitor.synchronize do
197
+ @storage.load
198
+ end
199
+ end
200
+
201
+ def save
202
+ @monitor.synchronize do
203
+ @storage.save
204
+ end
205
+ end
206
+
207
+ def get(key)
208
+ @monitor.synchronize do
209
+ @storage.load
210
+ @storage.get(key)
211
+ end
212
+ end
213
+
214
+ def fetch(key, defval)
215
+ @monitor.synchronize do
216
+ @storage.load
217
+ @storage.fetch(key, defval)
218
+ end
219
+ end
220
+
221
+ def put(key, value)
222
+ @monitor.synchronize do
223
+ @storage.load
224
+ @storage.put(key, value)
225
+ @storage.save
226
+ value
227
+ end
228
+ end
229
+
230
+ def delete(key)
231
+ @monitor.synchronize do
232
+ @storage.load
233
+ val = @storage.delete(key)
234
+ @storage.save
235
+ val
236
+ end
237
+ end
238
+
239
+ def update(key, &block)
240
+ @monitor.synchronize do
241
+ @storage.load
242
+ v = block.call(@storage.get(key))
243
+ @storage.put(key, v)
244
+ @storage.save
245
+ v
246
+ end
247
+ end
248
+ end
249
+
250
+ class SynchronizeWrapper
251
+ extend Forwardable
252
+
253
+ def initialize(storage)
254
+ @storage = storage
255
+ @mutex = Mutex.new
256
+ end
257
+
258
+ def_delegators :@storage, :persistent, :autosave, :autosave_interval, :save_at_shutdown
259
+ def_delegators :@storage, :persistent_always?
260
+ def_delegators :@storage, :close, :terminate
261
+
262
+ def synchronized?
263
+ true
264
+ end
265
+
266
+ def implementation
267
+ @storage
268
+ end
269
+
270
+ def load
271
+ @mutex.synchronize do
272
+ @storage.load
273
+ end
274
+ end
275
+
276
+ def save
277
+ @mutex.synchronize do
278
+ @storage.save
279
+ end
280
+ end
281
+
282
+ def get(key)
283
+ @mutex.synchronize{ @storage.get(key) }
284
+ end
285
+
286
+ def fetch(key, defval)
287
+ @mutex.synchronize{ @storage.fetch(key, defval) }
288
+ end
289
+
290
+ def put(key, value)
291
+ @mutex.synchronize{ @storage.put(key, value) }
292
+ end
293
+
294
+ def delete(key)
295
+ @mutex.synchronize{ @storage.delete(key) }
296
+ end
297
+
298
+ def update(key, &block)
299
+ @mutex.synchronize do
300
+ v = block.call(@storage.get(key))
301
+ @storage.put(key, v)
302
+ v
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,147 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Fluent
18
+ module PluginHelper
19
+ module Thread
20
+ THREAD_DEFAULT_WAIT_SECONDS = 1
21
+
22
+ # stop : mark callback thread as stopped
23
+ # shutdown : [-]
24
+ # close : correct stopped threads
25
+ # terminate: kill all threads
26
+
27
+ attr_reader :_threads # for test driver
28
+
29
+ def thread_current_running?
30
+ # checker for code in callback of thread_create
31
+ ::Thread.current[:_fluentd_plugin_helper_thread_running] || false
32
+ end
33
+
34
+ def thread_wait_until_start
35
+ until @_threads_mutex.synchronize{ @_threads.values.reduce(true){|r,t| r && t[:_fluentd_plugin_helper_thread_started] } }
36
+ sleep 0.1
37
+ end
38
+ end
39
+
40
+ def thread_wait_until_stop
41
+ until @_threads_mutex.synchronize{ @_threads.values.reduce(true){|r,t| r && ![:_fluentd_plugin_helper_thread_running] } }
42
+ sleep 0.1
43
+ end
44
+ end
45
+
46
+ # Ruby 2.2.3 or earlier (and all 2.1.x) cause bug about Threading ("Stack consistency error")
47
+ # by passing splatted argument to `yield`
48
+ # https://bugs.ruby-lang.org/issues/11027
49
+ # We can enable to pass arguments after expire of Ruby 2.1 (& older 2.2.x)
50
+ # def thread_create(title, *args)
51
+ # Thread.new(*args) do |*t_args|
52
+ # yield *t_args
53
+ def thread_create(title)
54
+ raise ArgumentError, "BUG: title must be a symbol" unless title.is_a? Symbol
55
+ raise ArgumentError, "BUG: callback not specified" unless block_given?
56
+ m = Mutex.new
57
+ m.lock
58
+ thread = ::Thread.new do
59
+ m.lock # run thread after that thread is successfully set into @_threads
60
+ m.unlock
61
+ thread_exit = false
62
+ ::Thread.current[:_fluentd_plugin_helper_thread_title] = title
63
+ ::Thread.current[:_fluentd_plugin_helper_thread_started] = true
64
+ ::Thread.current[:_fluentd_plugin_helper_thread_running] = true
65
+ begin
66
+ yield
67
+ thread_exit = true
68
+ rescue Exception => e
69
+ log.warn "thread exited by unexpected error", plugin: self.class, title: title, error: e
70
+ thread_exit = true
71
+ raise
72
+ ensure
73
+ unless thread_exit
74
+ log.warn "thread doesn't exit correctly (killed or other reason)", plugin: self.class, title: title, thread: ::Thread.current, error: $!
75
+ end
76
+ @_threads_mutex.synchronize do
77
+ @_threads.delete(::Thread.current.object_id)
78
+ end
79
+ ::Thread.current[:_fluentd_plugin_helper_thread_running] = false
80
+ end
81
+ end
82
+ thread.abort_on_exception = true
83
+ @_threads_mutex.synchronize do
84
+ @_threads[thread.object_id] = thread
85
+ end
86
+ m.unlock
87
+ thread
88
+ end
89
+
90
+ def thread_exist?(title)
91
+ @_threads.values.select{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }.size > 0
92
+ end
93
+
94
+ def thread_started?(title)
95
+ t = @_threads.values.select{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }.first
96
+ t && t[:_fluentd_plugin_helper_thread_started]
97
+ end
98
+
99
+ def thread_running?(title)
100
+ t = @_threads.values.select{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }.first
101
+ t && t[:_fluentd_plugin_helper_thread_running]
102
+ end
103
+
104
+ def initialize
105
+ super
106
+ @_threads_mutex = Mutex.new
107
+ @_threads = {}
108
+ @_thread_wait_seconds = THREAD_DEFAULT_WAIT_SECONDS
109
+ end
110
+
111
+ def stop
112
+ super
113
+ @_threads_mutex.synchronize do
114
+ @_threads.each_pair do |obj_id, thread|
115
+ thread[:_fluentd_plugin_helper_thread_running] = false
116
+ end
117
+ end
118
+ end
119
+
120
+ def close
121
+ @_threads_mutex.synchronize{ @_threads.keys }.each do |obj_id|
122
+ thread = @_threads[obj_id]
123
+ if !thread || thread.join(@_thread_wait_seconds)
124
+ @_threads_mutex.synchronize{ @_threads.delete(obj_id) }
125
+ end
126
+ end
127
+
128
+ super
129
+ end
130
+
131
+ def terminate
132
+ super
133
+ @_threads_mutex.synchronize{ @_threads.keys }.each do |obj_id|
134
+ thread = @_threads[obj_id]
135
+ log.warn "killing existing thead", thread: thread
136
+ thread.kill if thread
137
+ end
138
+ @_threads_mutex.synchronize{ @_threads.keys }.each do |obj_id|
139
+ thread = @_threads[obj_id]
140
+ thread.join
141
+ @_threads_mutex.synchronize{ @_threads.delete(obj_id) }
142
+ end
143
+ @_thread_wait_seconds = nil
144
+ end
145
+ end
146
+ end
147
+ end