fluentd 0.14.17-x64-mingw32 → 1.3.1-x64-mingw32

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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +16 -5
  3. data/ADOPTERS.md +5 -0
  4. data/{ChangeLog → CHANGELOG.md} +495 -6
  5. data/CONTRIBUTING.md +5 -2
  6. data/GOVERNANCE.md +55 -0
  7. data/LICENSE +202 -0
  8. data/MAINTAINERS.md +7 -5
  9. data/README.md +17 -10
  10. data/bin/fluent-ca-generate +6 -0
  11. data/example/counter.conf +18 -0
  12. data/example/secondary_file.conf +3 -2
  13. data/fluentd.gemspec +3 -3
  14. data/lib/fluent/agent.rb +1 -1
  15. data/lib/fluent/command/binlog_reader.rb +11 -2
  16. data/lib/fluent/command/ca_generate.rb +181 -0
  17. data/lib/fluent/command/cat.rb +28 -15
  18. data/lib/fluent/command/debug.rb +4 -4
  19. data/lib/fluent/command/fluentd.rb +2 -2
  20. data/lib/fluent/command/plugin_config_formatter.rb +24 -2
  21. data/lib/fluent/command/plugin_generator.rb +26 -8
  22. data/lib/fluent/config/configure_proxy.rb +7 -1
  23. data/lib/fluent/config/dsl.rb +8 -5
  24. data/lib/fluent/config/element.rb +5 -0
  25. data/lib/fluent/config/literal_parser.rb +7 -1
  26. data/lib/fluent/config/types.rb +28 -2
  27. data/lib/fluent/config/v1_parser.rb +1 -2
  28. data/lib/fluent/configurable.rb +1 -0
  29. data/lib/fluent/counter.rb +23 -0
  30. data/lib/fluent/counter/base_socket.rb +46 -0
  31. data/lib/fluent/counter/client.rb +297 -0
  32. data/lib/fluent/counter/error.rb +86 -0
  33. data/lib/fluent/counter/mutex_hash.rb +163 -0
  34. data/lib/fluent/counter/server.rb +273 -0
  35. data/lib/fluent/counter/store.rb +205 -0
  36. data/lib/fluent/counter/validator.rb +145 -0
  37. data/lib/fluent/env.rb +1 -0
  38. data/lib/fluent/event_router.rb +1 -1
  39. data/lib/fluent/log.rb +119 -29
  40. data/lib/fluent/plugin/base.rb +12 -0
  41. data/lib/fluent/plugin/buf_file.rb +20 -16
  42. data/lib/fluent/plugin/buffer.rb +130 -32
  43. data/lib/fluent/plugin/buffer/file_chunk.rb +23 -4
  44. data/lib/fluent/plugin/compressable.rb +1 -1
  45. data/lib/fluent/plugin/filter_grep.rb +135 -21
  46. data/lib/fluent/plugin/filter_parser.rb +13 -2
  47. data/lib/fluent/plugin/filter_record_transformer.rb +16 -14
  48. data/lib/fluent/plugin/formatter_stdout.rb +3 -2
  49. data/lib/fluent/plugin/formatter_tsv.rb +5 -1
  50. data/lib/fluent/plugin/in_debug_agent.rb +8 -1
  51. data/lib/fluent/plugin/in_forward.rb +1 -1
  52. data/lib/fluent/plugin/in_http.rb +84 -3
  53. data/lib/fluent/plugin/in_monitor_agent.rb +7 -1
  54. data/lib/fluent/plugin/in_syslog.rb +31 -10
  55. data/lib/fluent/plugin/in_tail.rb +142 -53
  56. data/lib/fluent/plugin/in_tcp.rb +5 -6
  57. data/lib/fluent/plugin/in_udp.rb +6 -2
  58. data/lib/fluent/plugin/in_unix.rb +1 -1
  59. data/lib/fluent/plugin/multi_output.rb +1 -0
  60. data/lib/fluent/plugin/out_copy.rb +25 -2
  61. data/lib/fluent/plugin/out_file.rb +26 -7
  62. data/lib/fluent/plugin/out_forward.rb +81 -42
  63. data/lib/fluent/plugin/out_secondary_file.rb +2 -2
  64. data/lib/fluent/plugin/out_stdout.rb +0 -1
  65. data/lib/fluent/plugin/out_stream.rb +1 -1
  66. data/lib/fluent/plugin/output.rb +221 -57
  67. data/lib/fluent/plugin/parser_apache.rb +1 -1
  68. data/lib/fluent/plugin/parser_apache2.rb +5 -1
  69. data/lib/fluent/plugin/parser_apache_error.rb +1 -1
  70. data/lib/fluent/plugin/parser_json.rb +10 -3
  71. data/lib/fluent/plugin/parser_ltsv.rb +7 -0
  72. data/lib/fluent/plugin/parser_multiline.rb +2 -1
  73. data/lib/fluent/plugin/parser_nginx.rb +1 -1
  74. data/lib/fluent/plugin/parser_none.rb +1 -0
  75. data/lib/fluent/plugin/parser_regexp.rb +15 -14
  76. data/lib/fluent/plugin/parser_syslog.rb +9 -5
  77. data/lib/fluent/plugin_helper.rb +2 -0
  78. data/lib/fluent/plugin_helper/cert_option.rb +28 -9
  79. data/lib/fluent/plugin_helper/compat_parameters.rb +3 -1
  80. data/lib/fluent/plugin_helper/counter.rb +51 -0
  81. data/lib/fluent/plugin_helper/event_loop.rb +9 -0
  82. data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
  83. data/lib/fluent/plugin_helper/retry_state.rb +15 -7
  84. data/lib/fluent/plugin_helper/server.rb +87 -25
  85. data/lib/fluent/plugin_helper/socket_option.rb +5 -2
  86. data/lib/fluent/plugin_helper/timer.rb +8 -7
  87. data/lib/fluent/root_agent.rb +18 -9
  88. data/lib/fluent/supervisor.rb +63 -23
  89. data/lib/fluent/system_config.rb +30 -2
  90. data/lib/fluent/test/helpers.rb +1 -1
  91. data/lib/fluent/time.rb +15 -7
  92. data/lib/fluent/timezone.rb +26 -2
  93. data/lib/fluent/version.rb +1 -1
  94. data/templates/new_gem/README.md.erb +2 -2
  95. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +1 -1
  96. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +1 -1
  97. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +1 -1
  98. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +4 -4
  99. data/test/command/test_ca_generate.rb +70 -0
  100. data/test/command/test_fluentd.rb +2 -2
  101. data/test/command/test_plugin_config_formatter.rb +8 -7
  102. data/test/command/test_plugin_generator.rb +65 -39
  103. data/test/config/test_config_parser.rb +7 -2
  104. data/test/config/test_configurable.rb +7 -2
  105. data/test/config/test_configure_proxy.rb +41 -3
  106. data/test/config/test_dsl.rb +10 -10
  107. data/test/config/test_element.rb +10 -0
  108. data/test/config/test_literal_parser.rb +8 -0
  109. data/test/config/test_plugin_configuration.rb +56 -0
  110. data/test/config/test_system_config.rb +19 -1
  111. data/test/config/test_types.rb +37 -0
  112. data/test/counter/test_client.rb +559 -0
  113. data/test/counter/test_error.rb +44 -0
  114. data/test/counter/test_mutex_hash.rb +179 -0
  115. data/test/counter/test_server.rb +589 -0
  116. data/test/counter/test_store.rb +258 -0
  117. data/test/counter/test_validator.rb +137 -0
  118. data/test/plugin/test_buf_file.rb +124 -0
  119. data/test/plugin/test_buffer.rb +3 -2
  120. data/test/plugin/test_filter_grep.rb +580 -2
  121. data/test/plugin/test_filter_parser.rb +33 -2
  122. data/test/plugin/test_filter_record_transformer.rb +22 -1
  123. data/test/plugin/test_formatter_ltsv.rb +3 -0
  124. data/test/plugin/test_formatter_tsv.rb +68 -0
  125. data/test/plugin/test_in_debug_agent.rb +21 -0
  126. data/test/plugin/test_in_exec.rb +3 -5
  127. data/test/plugin/test_in_http.rb +178 -0
  128. data/test/plugin/test_in_monitor_agent.rb +1 -1
  129. data/test/plugin/test_in_syslog.rb +64 -0
  130. data/test/plugin/test_in_tail.rb +116 -6
  131. data/test/plugin/test_in_tcp.rb +21 -0
  132. data/test/plugin/test_in_udp.rb +78 -0
  133. data/test/plugin/test_metadata.rb +89 -0
  134. data/test/plugin/test_out_copy.rb +31 -0
  135. data/test/plugin/test_out_file.rb +108 -2
  136. data/test/plugin/test_out_forward.rb +195 -2
  137. data/test/plugin/test_out_secondary_file.rb +14 -0
  138. data/test/plugin/test_output.rb +159 -45
  139. data/test/plugin/test_output_as_buffered.rb +19 -0
  140. data/test/plugin/test_output_as_buffered_backup.rb +307 -0
  141. data/test/plugin/test_output_as_buffered_retries.rb +70 -0
  142. data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
  143. data/test/plugin/test_parser_apache2.rb +1 -0
  144. data/test/plugin/test_parser_labeled_tsv.rb +17 -0
  145. data/test/plugin/test_parser_nginx.rb +40 -0
  146. data/test/plugin/test_parser_regexp.rb +6 -7
  147. data/test/plugin/test_parser_syslog.rb +155 -5
  148. data/test/plugin_helper/test_child_process.rb +4 -4
  149. data/test/plugin_helper/test_compat_parameters.rb +22 -0
  150. data/test/plugin_helper/test_record_accessor.rb +197 -0
  151. data/test/plugin_helper/test_retry_state.rb +20 -0
  152. data/test/plugin_helper/test_server.rb +30 -2
  153. data/test/test_config.rb +3 -3
  154. data/test/test_configdsl.rb +2 -2
  155. data/test/test_log.rb +51 -1
  156. data/test/test_root_agent.rb +33 -0
  157. data/test/test_supervisor.rb +105 -0
  158. metadata +68 -8
  159. data/COPYING +0 -14
@@ -370,6 +370,12 @@ module Fluent
370
370
 
371
371
  def dump_config_definition
372
372
  dumped_config = {}
373
+ if @argument
374
+ argument_name, _block, options = @argument
375
+ options[:required] = !@defaults.key?(argument_name)
376
+ options[:argument] = true
377
+ dumped_config[argument_name] = options
378
+ end
373
379
  @params.each do |name, config|
374
380
  dumped_config[name] = config[1]
375
381
  dumped_config[name][:required] = !@defaults.key?(name)
@@ -378,7 +384,7 @@ module Fluent
378
384
  end
379
385
  # Overwrite by config_set_default
380
386
  @defaults.each do |name, value|
381
- if @params.key?(name)
387
+ if @params.key?(name) || (@argument && @argument.first == name)
382
388
  dumped_config[name][:default] = value
383
389
  else
384
390
  dumped_config[name] = { default: value }
@@ -22,6 +22,8 @@ require 'fluent/config/element'
22
22
  module Fluent
23
23
  module Config
24
24
  module DSL
25
+ RESERVED_PARAMETERS = [:type, :id, :log_level, :label] # Need '@' prefix for reserved parameters
26
+
25
27
  module Parser
26
28
  def self.read(path)
27
29
  path = File.expand_path(path)
@@ -95,11 +97,12 @@ module Fluent
95
97
  proxy.element.instance_exec(&block)
96
98
  @elements.push(proxy.to_config_element)
97
99
  else
98
- @attrs[name.to_s] = if value.is_a?(Array) || value.is_a?(Hash)
99
- JSON.dump(value)
100
- else
101
- value.to_s
102
- end
100
+ param_name = RESERVED_PARAMETERS.include?(name) ? "@#{name}" : name.to_s
101
+ @attrs[param_name] = if value.is_a?(Array) || value.is_a?(Hash)
102
+ JSON.dump(value)
103
+ else
104
+ value.to_s
105
+ end
103
106
  end
104
107
 
105
108
  self
@@ -76,6 +76,11 @@ module Fluent
76
76
  "name:#{@name}, arg:#{@arg}, " + attrs + ", " + @elements.inspect
77
77
  end
78
78
 
79
+ # Used by PP and Pry
80
+ def pretty_print(q)
81
+ q.text(inspect)
82
+ end
83
+
79
84
  # This method assumes _o_ is an Element object. Should return false for nil or other object
80
85
  def ==(o)
81
86
  self.name == o.name && self.arg == o.arg &&
@@ -18,6 +18,7 @@ require 'stringio'
18
18
 
19
19
  require 'json'
20
20
  require 'yajl'
21
+ require 'socket'
21
22
  require 'irb/ruby-lex' # RubyLex
22
23
 
23
24
  require 'fluent/config/basic_parser'
@@ -162,6 +163,11 @@ module Fluent
162
163
  if @eval_context.nil?
163
164
  parse_error! "embedded code is not allowed in this file"
164
165
  end
166
+ # Add hostname and worker_id to code for preventing unused warnings
167
+ code = <<EOM + code
168
+ hostname = Socket.gethostname
169
+ worker_id = ENV['SERVERENGINE_WORKER_ID'] || ''
170
+ EOM
165
171
  @eval_context.instance_eval(code)
166
172
  end
167
173
 
@@ -192,7 +198,7 @@ module Fluent
192
198
 
193
199
  def scan_json(is_array)
194
200
  result = nil
195
- # Yajl does not raise ParseError for imcomplete json string, like '[1', '{"h"', '{"h":' or '{"h1":1'
201
+ # Yajl does not raise ParseError for incomplete json string, like '[1', '{"h"', '{"h":' or '{"h1":1'
196
202
  # This is the reason to use JSON module.
197
203
 
198
204
  buffer = (is_array ? "[" : "{")
@@ -60,11 +60,35 @@ module Fluent
60
60
  when ''
61
61
  true
62
62
  else
63
- nil
63
+ # Current parser passes comment without actual values, e.g. "param #foo".
64
+ # parser should pass empty string in this case but changing behaviour may break existing environment so keep parser behaviour. Just ignore comment value in boolean handling for now.
65
+ if str.respond_to?('start_with?') && str.start_with?('#')
66
+ true
67
+ else
68
+ nil
69
+ end
70
+ end
71
+ end
72
+
73
+ def self.regexp_value(str)
74
+ return nil unless str
75
+ return Regexp.compile(str) unless str.start_with?("/")
76
+ right_slash_position = str.rindex("/")
77
+ if right_slash_position < str.size - 3
78
+ raise Fluent::ConfigError, "invalid regexp: missing right slash: #{str}"
64
79
  end
80
+ options = str[(right_slash_position + 1)..-1]
81
+ option = 0
82
+ option |= Regexp::IGNORECASE if options.include?("i")
83
+ option |= Regexp::MULTILINE if options.include?("m")
84
+ Regexp.compile(str[1...right_slash_position], option)
65
85
  end
66
86
 
67
- STRING_TYPE = Proc.new { |val, opts| val.to_s.force_encoding(Encoding::UTF_8) }
87
+ STRING_TYPE = Proc.new { |val, opts|
88
+ v = val.to_s
89
+ v = v.frozen? ? v.dup : v # config_param can't assume incoming string is mutable
90
+ v.force_encoding(Encoding::UTF_8)
91
+ }
68
92
  ENUM_TYPE = Proc.new { |val, opts|
69
93
  s = val.to_sym
70
94
  list = opts[:list]
@@ -79,6 +103,7 @@ module Fluent
79
103
  SIZE_TYPE = Proc.new { |val, opts| Config.size_value(val) }
80
104
  BOOL_TYPE = Proc.new { |val, opts| Config.bool_value(val) }
81
105
  TIME_TYPE = Proc.new { |val, opts| Config.time_value(val) }
106
+ REGEXP_TYPE = Proc.new { |val, opts| Config.regexp_value(val) }
82
107
 
83
108
  REFORMAT_VALUE = ->(type, value) {
84
109
  if value.nil?
@@ -91,6 +116,7 @@ module Fluent
91
116
  when :size then Config.size_value(value)
92
117
  when :bool then Config.bool_value(value)
93
118
  when :time then Config.time_value(value)
119
+ when :regexp then Config.regexp_value(value)
94
120
  else
95
121
  raise "unknown type in REFORMAT: #{type}"
96
122
  end
@@ -174,9 +174,8 @@ module Fluent
174
174
  ss = StringScanner.new(data)
175
175
  V1Parser.new(ss, basepath, fname, @eval_context).parse_element(true, nil, attrs, elems)
176
176
  end
177
-
178
177
  rescue SystemCallError => e
179
- cpe = ConfigParseError.new("include error #{uri}")
178
+ cpe = ConfigParseError.new("include error #{uri} - #{e}")
180
179
  cpe.set_backtrace(e.backtrace)
181
180
  raise cpe
182
181
  end
@@ -128,6 +128,7 @@ module Fluent
128
128
  time: Config::TIME_TYPE,
129
129
  hash: Config::HASH_TYPE,
130
130
  array: Config::ARRAY_TYPE,
131
+ regexp: Config::REGEXP_TYPE,
131
132
  }.each do |name, type|
132
133
  register_type(name, type)
133
134
  end
@@ -0,0 +1,23 @@
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/counter/client'
18
+ require 'fluent/counter/server'
19
+
20
+ module Fluent
21
+ module Counter
22
+ end
23
+ end
@@ -0,0 +1,46 @@
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 'cool.io'
18
+ require 'fluent/msgpack_factory'
19
+
20
+ module Fluent
21
+ module Counter
22
+ class BaseSocket < Coolio::TCPSocket
23
+ include Fluent::MessagePackFactory::Mixin
24
+
25
+ def packed_write(data)
26
+ write pack(data)
27
+ end
28
+
29
+ def on_read(data)
30
+ msgpack_unpacker.feed_each(data) do |d|
31
+ on_message d
32
+ end
33
+ end
34
+
35
+ def on_message(data)
36
+ raise NotImplementedError
37
+ end
38
+
39
+ private
40
+
41
+ def pack(data)
42
+ msgpack_packer.pack(data)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,297 @@
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 'cool.io'
18
+ require 'fluent/counter/base_socket'
19
+ require 'fluent/counter/error'
20
+ require 'timeout'
21
+
22
+ module Fluent
23
+ module Counter
24
+ class Client
25
+ DEFAULT_PORT = 24321
26
+ DEFAULT_ADDR = '127.0.0.1'
27
+ DEFAULT_TIMEOUT = 5
28
+ ID_LIMIT_COUNT = 1 << 31
29
+
30
+ def initialize(loop = nil, opt = {})
31
+ @loop = loop || Coolio::Loop.new
32
+ @port = opt[:port] || DEFAULT_PORT
33
+ @host = opt[:host] || DEFAULT_ADDR
34
+ @log = opt[:log] || $log
35
+ @timeout = opt[:timeout] || DEFAULT_TIMEOUT
36
+ @conn = Connection.connect(@host, @port, method(:on_message))
37
+ @responses = {}
38
+ @id = 0
39
+ @id_mutex = Mutex.new
40
+ @loop_mutex = Mutex.new
41
+ end
42
+
43
+ def start
44
+ @loop.attach(@conn)
45
+ @log.debug("starting counter client: #{@host}:#{@port}")
46
+ self
47
+ rescue => e
48
+ if @log
49
+ @log.error e
50
+ else
51
+ STDERR.puts e
52
+ end
53
+ end
54
+
55
+ def stop
56
+ @conn.close
57
+ @log.debug("calling stop in counter client: #{@host}:#{@port}")
58
+ end
59
+
60
+ def establish(scope)
61
+ scope = Timeout.timeout(@timeout) {
62
+ response = send_request('establish', nil, [scope])
63
+ Fluent::Counter.raise_error(response.errors.first) if response.errors?
64
+ data = response.data
65
+ data.first
66
+ }
67
+ @scope = scope
68
+ rescue Timeout::Error
69
+ raise "Can't establish the connection to counter server due to timeout"
70
+ end
71
+
72
+ # === Example
73
+ # `init` receives various arguments.
74
+ #
75
+ # 1. init(name: 'name')
76
+ # 2. init({ name: 'name',reset_interval: 20 }, options: {})
77
+ # 3. init([{ name: 'name1',reset_interval: 20 }, { name: 'name2',reset_interval: 20 }])
78
+ # 4. init([{ name: 'name1',reset_interval: 20 }, { name: 'name2',reset_interval: 20 }], options: {})
79
+ # 5. init([{ name: 'name1',reset_interval: 20 }, { name: 'name2',reset_interval: 20 }]) { |res| ... }
80
+ def init(params, options: {})
81
+ exist_scope!
82
+ params = [params] unless params.is_a?(Array)
83
+ res = send_request('init', @scope, params, options)
84
+
85
+ # if `async` is false or missing, block at this method and return a Future::Result object.
86
+ if block_given?
87
+ Thread.start do
88
+ yield res.get
89
+ end
90
+ else
91
+ res
92
+ end
93
+ end
94
+
95
+ def delete(*params, options: {})
96
+ exist_scope!
97
+ res = send_request('delete', @scope, params, options)
98
+
99
+ if block_given?
100
+ Thread.start do
101
+ yield res.get
102
+ end
103
+ else
104
+ res
105
+ end
106
+ end
107
+
108
+ # === Example
109
+ # `inc` receives various arguments.
110
+ #
111
+ # 1. inc(name: 'name')
112
+ # 2. inc({ name: 'name',value: 20 }, options: {})
113
+ # 3. inc([{ name: 'name1',value: 20 }, { name: 'name2',value: 20 }])
114
+ # 4. inc([{ name: 'name1',value: 20 }, { name: 'name2',value: 20 }], options: {})
115
+ def inc(params, options: {})
116
+ exist_scope!
117
+ params = [params] unless params.is_a?(Array)
118
+ res = send_request('inc', @scope, params, options)
119
+
120
+ if block_given?
121
+ Thread.start do
122
+ yield res.get
123
+ end
124
+ else
125
+ res
126
+ end
127
+ end
128
+
129
+ def get(*params, options: {})
130
+ exist_scope!
131
+ res = send_request('get', @scope, params, options)
132
+
133
+ if block_given?
134
+ Thread.start do
135
+ yield res.get
136
+ end
137
+ else
138
+ res
139
+ end
140
+ end
141
+
142
+ def reset(*params, options: {})
143
+ exist_scope!
144
+ res = send_request('reset', @scope, params, options)
145
+
146
+ if block_given?
147
+ Thread.start do
148
+ yield res.get
149
+ end
150
+ else
151
+ res
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ def exist_scope!
158
+ raise 'Call `establish` method to get a `scope` before calling this method' unless @scope
159
+ end
160
+
161
+ def on_message(data)
162
+ if response = @responses.delete(data['id'])
163
+ response.set(data)
164
+ else
165
+ @log.warn("Receiving missing id data: #{data}")
166
+ end
167
+ end
168
+
169
+ def send_request(method, scope, params, opt = {})
170
+ id = generate_id
171
+ res = Future.new(@loop, @loop_mutex)
172
+ @responses[id] = res # set a response value to this future object at `on_message`
173
+ request = build_request(method, id, scope, params, opt)
174
+ @log.debug(request)
175
+ @conn.send_data request
176
+ res
177
+ end
178
+
179
+ def build_request(method, id, scope = nil, params = nil, options = nil)
180
+ r = { id: id, method: method }
181
+ r[:scope] = scope if scope
182
+ r[:params] = params if params
183
+ r[:options] = options if options
184
+ r
185
+ end
186
+
187
+ def generate_id
188
+ id = 0
189
+ @id_mutex.synchronize do
190
+ id = @id
191
+ @id += 1
192
+ @id = 0 if ID_LIMIT_COUNT < @id
193
+ end
194
+ id
195
+ end
196
+ end
197
+
198
+ class Connection < Fluent::Counter::BaseSocket
199
+ def initialize(io, on_message)
200
+ super(io)
201
+ @connection = false
202
+ @buffer = ''
203
+ @on_message = on_message
204
+ end
205
+
206
+ def send_data(data)
207
+ if @connection
208
+ packed_write data
209
+ else
210
+ @buffer += pack(data)
211
+ end
212
+ end
213
+
214
+ def on_connect
215
+ @connection = true
216
+ write @buffer
217
+ @buffer = ''
218
+ end
219
+
220
+ def on_close
221
+ @connection = false
222
+ end
223
+
224
+ def on_message(data)
225
+ @on_message.call(data)
226
+ end
227
+ end
228
+
229
+ class Future
230
+ class Result
231
+ attr_reader :data, :errors
232
+
233
+ def initialize(result)
234
+ @errors = result['errors']
235
+ @data = result['data']
236
+ end
237
+
238
+ def success?
239
+ @errors.nil? || @errors.empty?
240
+ end
241
+
242
+ def error?
243
+ !success?
244
+ end
245
+ end
246
+
247
+ def initialize(loop, mutex)
248
+ @set = false
249
+ @result = nil
250
+ @mutex = mutex
251
+ @loop = loop
252
+ end
253
+
254
+ def set(v)
255
+ @result = Result.new(v)
256
+ @set = true
257
+ end
258
+
259
+ def errors
260
+ get.errors
261
+ end
262
+
263
+ def errors?
264
+ es = errors
265
+ es && !es.empty?
266
+ end
267
+
268
+ def data
269
+ get.data
270
+ end
271
+
272
+ def get
273
+ # Block until `set` method is called and @result is set
274
+ join if @result.nil?
275
+ @result
276
+ end
277
+
278
+ def wait
279
+ res = get
280
+ if res.error?
281
+ Fluent::Counter.raise_error(res.errors.first)
282
+ end
283
+ res
284
+ end
285
+
286
+ private
287
+
288
+ def join
289
+ until @set
290
+ @mutex.synchronize do
291
+ @loop.run_once(0.0001) # retun a lock as soon as possible
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end
297
+ end