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,135 @@
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 'fluent/plugin/buffer'
18
+ require 'fluent/unique_id'
19
+ require 'fluent/event'
20
+
21
+ require 'monitor'
22
+
23
+ module Fluent
24
+ module Plugin
25
+ class Buffer # fluent/plugin/buffer is alread loaded
26
+ class Chunk
27
+ include MonitorMixin
28
+ include UniqueId::Mixin
29
+ include ChunkMessagePackEventStreamer
30
+
31
+ # Chunks has 2 part:
32
+ # * metadata: contains metadata which should be restored after resume (if possible)
33
+ # v: {key=>value,key=>value,...} (optional)
34
+ # t: tag as string (optional)
35
+ # k: time slice key (optional)
36
+ #
37
+ # id: unique_id of chunk (*)
38
+ # s: size (number of events in chunk) (*)
39
+ # c: created_at as unix time (*)
40
+ # m: modified_at as unix time (*)
41
+ # (*): fields automatically injected by chunk itself
42
+ # * data: binary data, combined records represented as String, maybe compressed
43
+
44
+ # NOTE: keys of metadata are named with a single letter
45
+ # to decread bytesize of metadata I/O
46
+
47
+ # TODO: CompressedPackedMessage of forward protocol?
48
+
49
+ def initialize(metadata)
50
+ super()
51
+ @unique_id = generate_unique_id
52
+ @metadata = metadata
53
+
54
+ # state: staged/queued/closed
55
+ @state = :staged
56
+
57
+ @size = 0
58
+ @created_at = Time.now
59
+ @modified_at = Time.now
60
+ end
61
+
62
+ attr_reader :unique_id, :metadata, :created_at, :modified_at, :state
63
+
64
+ # data is array of formatted record string
65
+ def append(data)
66
+ raise NotImplementedError, "Implement this method in child class"
67
+ end
68
+
69
+ # for event streams which is packed or zipped (and we want not to unpack/uncompress)
70
+ def concat(bulk, records)
71
+ raise NotImplementedError, "Implement this method in child class"
72
+ end
73
+
74
+ def commit
75
+ raise NotImplementedError, "Implement this method in child class"
76
+ end
77
+
78
+ def rollback
79
+ raise NotImplementedError, "Implement this method in child class"
80
+ end
81
+
82
+ def bytesize
83
+ raise NotImplementedError, "Implement this method in child class"
84
+ end
85
+
86
+ def size
87
+ raise NotImplementedError, "Implement this method in child class"
88
+ end
89
+ alias :length :size
90
+
91
+ def empty?
92
+ size == 0
93
+ end
94
+
95
+ def staged?
96
+ @state == :staged
97
+ end
98
+
99
+ def queued?
100
+ @state == :queued
101
+ end
102
+
103
+ def closed?
104
+ @state == :closed
105
+ end
106
+
107
+ def enqueued!
108
+ @state = :queued
109
+ end
110
+
111
+ def close
112
+ @state = :closed
113
+ end
114
+
115
+ def purge
116
+ @state = :closed
117
+ end
118
+
119
+ def read
120
+ raise NotImplementedError, "Implement this method in child class"
121
+ end
122
+
123
+ def open(&block)
124
+ raise NotImplementedError, "Implement this method in child class"
125
+ end
126
+
127
+ def write_to(io)
128
+ open do |i|
129
+ IO.copy_stream(i, io)
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,339 @@
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 'fluent/plugin/buffer/chunk'
18
+ require 'fluent/unique_id'
19
+ require 'fluent/msgpack_factory'
20
+
21
+ module Fluent
22
+ module Plugin
23
+ class Buffer
24
+ class FileChunk < Chunk
25
+ ### buffer path user specified : /path/to/directory/user_specified_prefix.*.log
26
+ ### buffer chunk path : /path/to/directory/user_specified_prefix.b513b61c9791029c2513b61c9791029c2.log
27
+ ### buffer chunk metadata path : /path/to/directory/user_specified_prefix.b513b61c9791029c2513b61c9791029c2.log.meta
28
+
29
+ # NOTE: Old style buffer path of time sliced output plugins had a part of key: prefix.20150414.b513b61...suffix
30
+ # But this part is not used now for any purpose. (Now metadata is used instead.)
31
+
32
+ # state: b/q - 'b'(on stage, compatible with v0.12), 'q'(enqueued)
33
+ # path_prefix: path prefix string, ended with '.'
34
+ # path_suffix: path suffix string, like '.log' (or any other user specified)
35
+
36
+ include SystemConfig::Mixin
37
+ include MessagePackFactory::Mixin
38
+
39
+ FILE_PERMISSION = 0644
40
+
41
+ attr_reader :path, :permission
42
+
43
+ def initialize(metadata, path, mode, perm: system_config.file_permission || FILE_PERMISSION)
44
+ super(metadata)
45
+ @permission = perm
46
+ @bytesize = @size = @adding_bytes = @adding_size = 0
47
+ @meta = nil
48
+
49
+ case mode
50
+ when :create then create_new_chunk(path, perm)
51
+ when :staged then load_existing_staged_chunk(path)
52
+ when :queued then load_existing_enqueued_chunk(path)
53
+ else
54
+ raise ArgumentError, "Invalid file chunk mode: #{mode}"
55
+ end
56
+ end
57
+
58
+ def append(data)
59
+ raise "BUG: appending to non-staged chunk, now '#{self.state}'" unless self.staged?
60
+
61
+ bytes = 0
62
+ adding = ''.force_encoding(Encoding::ASCII_8BIT)
63
+ data.each do |d|
64
+ x = d.force_encoding(Encoding::ASCII_8BIT)
65
+ bytes += x.bytesize
66
+ adding << x
67
+ end
68
+ @chunk.write adding
69
+
70
+ @adding_bytes += bytes
71
+ @adding_size += data.size
72
+
73
+ true
74
+ end
75
+
76
+ def concat(bulk, bulk_size)
77
+ raise "BUG: appending to non-staged chunk, now '#{self.state}'" unless self.staged?
78
+
79
+ bulk.force_encoding(Encoding::ASCII_8BIT)
80
+ @chunk.write bulk
81
+ @adding_bytes += bulk.bytesize
82
+ @adding_size += bulk_size
83
+ true
84
+ end
85
+
86
+ def commit
87
+ write_metadata # this should be at first: of course, this operation may fail
88
+
89
+ @commit_position = @chunk.pos
90
+ @size += @adding_size
91
+ @bytesize += @adding_bytes
92
+ @adding_bytes = @adding_size = 0
93
+ @modified_at = Time.now
94
+
95
+ true
96
+ end
97
+
98
+ def rollback
99
+ if @chunk.pos != @commit_position
100
+ @chunk.seek(@commit_position, IO::SEEK_SET)
101
+ @chunk.truncate(@commit_position)
102
+ end
103
+ @adding_bytes = @adding_size = 0
104
+ true
105
+ end
106
+
107
+ def bytesize
108
+ @bytesize + @adding_bytes
109
+ end
110
+
111
+ def size
112
+ @size + @adding_size
113
+ end
114
+
115
+ def empty?
116
+ @bytesize == 0
117
+ end
118
+
119
+ def enqueued!
120
+ return unless self.staged?
121
+
122
+ new_chunk_path = self.class.generate_queued_chunk_path(@path, @unique_id)
123
+ new_meta_path = new_chunk_path + '.meta'
124
+
125
+ write_metadata(update: false) # re-write metadata w/ finalized records
126
+
127
+ file_rename(@chunk, @path, new_chunk_path, ->(new_io){ @chunk = new_io })
128
+ @path = new_chunk_path
129
+
130
+ file_rename(@meta, @meta_path, new_meta_path, ->(new_io){ @meta = new_io })
131
+ @meta_path = new_meta_path
132
+
133
+ super
134
+ end
135
+
136
+ def close
137
+ super
138
+ size = @chunk.size
139
+ @chunk.close
140
+ @meta.close if @meta # meta may be missing if chunk is queued at first
141
+ if size == 0
142
+ File.unlink(@path, @meta_path)
143
+ end
144
+ end
145
+
146
+ def purge
147
+ super
148
+ @chunk.close
149
+ @meta.close if @meta
150
+ @bytesize = @size = @adding_bytes = @adding_size = 0
151
+ File.unlink(@path, @meta_path)
152
+ end
153
+
154
+ def read
155
+ @chunk.seek(0, IO::SEEK_SET)
156
+ @chunk.read
157
+ end
158
+
159
+ def open(&block)
160
+ @chunk.seek(0, IO::SEEK_SET)
161
+ val = yield @chunk
162
+ @chunk.seek(0, IO::SEEK_END) if self.staged?
163
+ val
164
+ end
165
+
166
+ def self.assume_chunk_state(path)
167
+ if /\.(b|q)([0-9a-f]+)\.[^\/]*\Z/n =~ path # //n switch means explicit 'ASCII-8BIT' pattern
168
+ $1 == 'b' ? :staged : :queued
169
+ else
170
+ :queued
171
+ end
172
+ end
173
+
174
+ def self.generate_stage_chunk_path(path, unique_id)
175
+ pos = path.index('.*.')
176
+ raise "BUG: buffer chunk path on stage MUST have '.*.'" unless pos
177
+
178
+ prefix = path[0...pos]
179
+ suffix = path[(pos+3)..-1]
180
+
181
+ chunk_id = Fluent::UniqueId.hex(unique_id)
182
+ state = 'b'
183
+ "#{prefix}.#{state}#{chunk_id}.#{suffix}"
184
+ end
185
+
186
+ def self.generate_queued_chunk_path(path, unique_id)
187
+ chunk_id = Fluent::UniqueId.hex(unique_id)
188
+ if path.index(".b#{chunk_id}.")
189
+ path.sub(".b#{chunk_id}.", ".q#{chunk_id}.")
190
+ else # for unexpected cases (ex: users rename files while opened by fluentd)
191
+ path + ".q#{chunk_id}.chunk"
192
+ end
193
+ end
194
+
195
+ # used only for queued v0.12 buffer path
196
+ def self.unique_id_from_path(path)
197
+ if /\.(b|q)([0-9a-f]+)\.[^\/]*\Z/n =~ path # //n switch means explicit 'ASCII-8BIT' pattern
198
+ return $2.scan(/../).map{|x| x.to_i(16) }.pack('C*')
199
+ end
200
+ nil
201
+ end
202
+
203
+ def restore_metadata(bindata)
204
+ data = msgpack_unpacker(symbolize_keys: true).feed(bindata).read rescue {}
205
+
206
+ now = Time.now
207
+
208
+ @unique_id = data[:id] || self.class.unique_id_from_path(@path) || @unique_id
209
+ @size = data[:s] || 0
210
+ @created_at = Time.at(data.fetch(:c, now.to_i))
211
+ @modified_at = Time.at(data.fetch(:m, now.to_i))
212
+
213
+ @metadata.timekey = data[:timekey]
214
+ @metadata.tag = data[:tag]
215
+ @metadata.variables = data[:variables]
216
+ end
217
+
218
+ def restore_metadata_partially(chunk)
219
+ @unique_id = self.class.unique_id_from_path(chunk.path) || @unique_id
220
+ @size = 0
221
+ @created_at = chunk.ctime # birthtime isn't supported on Windows (and Travis?)
222
+ @modified_at = chunk.mtime
223
+
224
+ @metadata.timekey = nil
225
+ @metadata.tag = nil
226
+ @metadata.variables = nil
227
+ end
228
+
229
+ def write_metadata(update: true)
230
+ data = @metadata.to_h.merge({
231
+ id: @unique_id,
232
+ s: (update ? @size + @adding_size : @size),
233
+ c: @created_at.to_i,
234
+ m: (update ? Time.now : @modified_at).to_i,
235
+ })
236
+ @meta.seek(0, IO::SEEK_SET)
237
+ @meta.truncate(0)
238
+ @meta.write(msgpack_packer.pack(data))
239
+ end
240
+
241
+ def file_rename(file, old_path, new_path, callback=nil)
242
+ pos = file.pos
243
+ if Fluent.windows?
244
+ file.close
245
+ File.rename(old_path, new_path)
246
+ file = File.open(new_path, 'rb', @permission)
247
+ else
248
+ File.rename(old_path, new_path)
249
+ file.reopen(new_path, 'rb')
250
+ end
251
+ file.set_encoding(Encoding::ASCII_8BIT)
252
+ file.sync = true
253
+ file.binmode
254
+ file.pos = pos
255
+ callback.call(file) if callback
256
+ end
257
+
258
+ def create_new_chunk(path, perm)
259
+ @path = self.class.generate_stage_chunk_path(path, @unique_id)
260
+ @meta_path = @path + '.meta'
261
+ @chunk = File.open(@path, 'wb+', perm)
262
+ @chunk.set_encoding(Encoding::ASCII_8BIT)
263
+ @chunk.sync = true
264
+ @chunk.binmode
265
+ @meta = File.open(@meta_path, 'wb', perm)
266
+ @meta.set_encoding(Encoding::ASCII_8BIT)
267
+ @meta.sync = true
268
+ @meta.binmode
269
+
270
+ @state = :staged
271
+ @bytesize = 0
272
+ @commit_position = @chunk.pos # must be 0
273
+ @adding_bytes = 0
274
+ @adding_size = 0
275
+ end
276
+
277
+ def load_existing_staged_chunk(path)
278
+ @path = path
279
+ @meta_path = @path + '.meta'
280
+
281
+ @meta = nil
282
+ # staging buffer chunk without metadata is classic buffer chunk file
283
+ # and it should be enqueued immediately
284
+ if File.exist?(@meta_path)
285
+ @chunk = File.open(@path, 'rb+')
286
+ @chunk.set_encoding(Encoding::ASCII_8BIT)
287
+ @chunk.sync = true
288
+ @chunk.seek(0, IO::SEEK_END)
289
+ @chunk.binmode
290
+
291
+ @meta = File.open(@meta_path, 'rb+')
292
+ @meta.set_encoding(Encoding::ASCII_8BIT)
293
+ @meta.sync = true
294
+ @meta.binmode
295
+ restore_metadata(@meta.read)
296
+ @meta.seek(0, IO::SEEK_SET)
297
+
298
+ @state = :staged
299
+ @bytesize = @chunk.size
300
+ @commit_position = @chunk.pos
301
+ @adding_bytes = 0
302
+ @adding_size = 0
303
+ else
304
+ # classic buffer chunk - read only chunk
305
+ @chunk = File.open(@path, 'rb')
306
+ @chunk.set_encoding(Encoding::ASCII_8BIT)
307
+ @chunk.binmode
308
+ @chunk.seek(0, IO::SEEK_SET)
309
+ @state = :queued
310
+ @bytesize = @chunk.size
311
+
312
+ restore_metadata_partially(@chunk)
313
+
314
+ @commit_position = @chunk.size
315
+ @unique_id = self.class.unique_id_from_path(@path) || @unique_id
316
+ end
317
+ end
318
+
319
+ def load_existing_enqueued_chunk(path)
320
+ @path = path
321
+ @chunk = File.open(@path, 'rb')
322
+ @chunk.set_encoding(Encoding::ASCII_8BIT)
323
+ @chunk.binmode
324
+ @chunk.seek(0, IO::SEEK_SET)
325
+ @bytesize = @chunk.size
326
+ @commit_position = @chunk.size
327
+
328
+ @meta_path = @path + '.meta'
329
+ if File.readable?(@meta_path)
330
+ restore_metadata(File.open(@meta_path){|f| f.set_encoding(Encoding::ASCII_8BIT); f.binmode; f.read })
331
+ else
332
+ restore_metadata_partially(@chunk)
333
+ end
334
+ @state = :queued
335
+ end
336
+ end
337
+ end
338
+ end
339
+ end