droonga-engine 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/benchmark/timer-watcher/benchmark.rb +44 -0
  4. data/bin/droonga-engine-absorb-data +246 -187
  5. data/bin/droonga-engine-catalog-generate +12 -12
  6. data/bin/droonga-engine-catalog-modify +4 -4
  7. data/bin/droonga-engine-join +352 -171
  8. data/bin/droonga-engine-set-role +54 -0
  9. data/bin/droonga-engine-unjoin +107 -112
  10. data/droonga-engine.gemspec +3 -3
  11. data/install.sh +55 -36
  12. data/install/centos/functions.sh +2 -2
  13. data/install/debian/functions.sh +2 -2
  14. data/lib/droonga/address.rb +26 -24
  15. data/lib/droonga/buffered_tcp_socket.rb +65 -10
  16. data/lib/droonga/catalog/base.rb +9 -6
  17. data/lib/droonga/catalog/dataset.rb +17 -41
  18. data/lib/droonga/catalog/fetcher.rb +64 -0
  19. data/lib/droonga/catalog/generator.rb +245 -0
  20. data/lib/droonga/catalog/loader.rb +66 -0
  21. data/lib/droonga/{catalog_modifier.rb → catalog/modifier.rb} +11 -18
  22. data/lib/droonga/catalog/replicas_volume.rb +123 -0
  23. data/lib/droonga/catalog/schema.rb +37 -37
  24. data/lib/droonga/catalog/single_volume.rb +11 -3
  25. data/lib/droonga/catalog/slice.rb +10 -6
  26. data/lib/droonga/catalog/{collection_volume.rb → slices_volume.rb} +47 -11
  27. data/lib/droonga/catalog/version1.rb +47 -19
  28. data/lib/droonga/catalog/version2.rb +11 -10
  29. data/lib/droonga/catalog/version2_validator.rb +4 -4
  30. data/lib/droonga/catalog/volume.rb +17 -5
  31. data/lib/droonga/changable.rb +25 -0
  32. data/lib/droonga/cluster.rb +237 -0
  33. data/lib/droonga/collector_runner.rb +4 -0
  34. data/lib/droonga/collectors.rb +2 -1
  35. data/lib/droonga/collectors/recursive_sum.rb +26 -0
  36. data/lib/droonga/command/droonga_engine.rb +404 -127
  37. data/lib/droonga/command/droonga_engine_service.rb +47 -11
  38. data/lib/droonga/command/droonga_engine_worker.rb +21 -1
  39. data/lib/droonga/command/remote_command_base.rb +78 -0
  40. data/lib/droonga/command/serf_event_handler.rb +29 -20
  41. data/lib/droonga/data_absorber_client.rb +222 -0
  42. data/lib/droonga/database_scanner.rb +106 -0
  43. data/lib/droonga/{live_nodes_list_loader.rb → deferrable.rb} +11 -24
  44. data/lib/droonga/differ.rb +58 -0
  45. data/lib/droonga/dispatcher.rb +155 -32
  46. data/lib/droonga/distributed_command_planner.rb +9 -11
  47. data/lib/droonga/engine.rb +83 -78
  48. data/lib/droonga/engine/version.rb +1 -1
  49. data/lib/droonga/engine_node.rb +301 -0
  50. data/lib/droonga/engine_state.rb +62 -40
  51. data/lib/droonga/farm.rb +44 -5
  52. data/lib/droonga/file_observer.rb +16 -12
  53. data/lib/droonga/fluent_message_receiver.rb +98 -29
  54. data/lib/droonga/fluent_message_sender.rb +30 -23
  55. data/lib/droonga/forward_buffer.rb +160 -0
  56. data/lib/droonga/forwarder.rb +73 -40
  57. data/lib/droonga/handler.rb +7 -6
  58. data/lib/droonga/handler_messenger.rb +15 -6
  59. data/lib/droonga/handler_runner.rb +6 -1
  60. data/lib/droonga/internal_fluent_message_receiver.rb +28 -8
  61. data/lib/droonga/job_pusher.rb +10 -7
  62. data/lib/droonga/job_receiver.rb +6 -4
  63. data/lib/droonga/logger.rb +7 -1
  64. data/lib/droonga/node_name.rb +90 -0
  65. data/lib/droonga/node_role.rb +72 -0
  66. data/lib/droonga/path.rb +34 -9
  67. data/lib/droonga/planner.rb +73 -7
  68. data/lib/droonga/plugin/async_command.rb +154 -0
  69. data/lib/droonga/plugins/catalog.rb +1 -0
  70. data/lib/droonga/plugins/crud.rb +22 -6
  71. data/lib/droonga/plugins/dump.rb +66 -135
  72. data/lib/droonga/plugins/groonga/delete.rb +13 -0
  73. data/lib/droonga/plugins/search/distributed_search_planner.rb +4 -4
  74. data/lib/droonga/plugins/system.rb +5 -26
  75. data/lib/droonga/plugins/system/absorb_data.rb +405 -0
  76. data/lib/droonga/plugins/system/statistics.rb +71 -0
  77. data/lib/droonga/plugins/system/status.rb +53 -0
  78. data/lib/droonga/process_control_protocol.rb +3 -1
  79. data/lib/droonga/process_supervisor.rb +32 -15
  80. data/lib/droonga/reducer.rb +69 -0
  81. data/lib/droonga/safe_file_writer.rb +1 -1
  82. data/lib/droonga/serf.rb +207 -276
  83. data/lib/droonga/serf/agent.rb +228 -0
  84. data/lib/droonga/serf/command.rb +94 -0
  85. data/lib/droonga/serf/downloader.rb +120 -0
  86. data/lib/droonga/serf/remote_command.rb +348 -0
  87. data/lib/droonga/serf/tag.rb +56 -0
  88. data/lib/droonga/service_installation.rb +2 -2
  89. data/lib/droonga/session.rb +49 -1
  90. data/lib/droonga/single_step.rb +6 -11
  91. data/lib/droonga/single_step_definition.rb +32 -1
  92. data/lib/droonga/slice.rb +14 -9
  93. data/lib/droonga/supervisor.rb +27 -20
  94. data/lib/droonga/test/stub_handler_messenger.rb +2 -1
  95. data/lib/droonga/timestamp.rb +69 -0
  96. data/lib/droonga/worker_process_agent.rb +33 -15
  97. data/sample/cluster-state.json +8 -0
  98. data/sample/cluster/Rakefile +30 -6
  99. data/test/command/fixture/integer-key-table.jsons +11 -0
  100. data/test/command/fixture/string-key-table.jsons +11 -0
  101. data/test/command/run-test.rb +4 -0
  102. data/test/command/suite/add/error/invalid-integer.expected +3 -3
  103. data/test/command/suite/add/error/invalid-time.expected +3 -3
  104. data/test/command/suite/add/{minimum.expected → key-integer.expected} +0 -0
  105. data/test/command/suite/add/{minimum.test → key-integer.test} +0 -0
  106. data/test/command/suite/add/key-string.expected +6 -0
  107. data/test/command/suite/add/key-string.test +9 -0
  108. data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.expected +6 -0
  109. data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.test +9 -0
  110. data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.expected +6 -0
  111. data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.test +9 -0
  112. data/test/command/suite/add/without-values.expected +6 -0
  113. data/test/command/suite/add/without-values.test +11 -0
  114. data/test/command/suite/dump/column/index.expected +33 -1
  115. data/test/command/suite/dump/column/index.test +1 -0
  116. data/test/command/suite/dump/column/scalar.expected +29 -1
  117. data/test/command/suite/dump/column/scalar.test +1 -0
  118. data/test/command/suite/dump/column/vector.expected +29 -1
  119. data/test/command/suite/dump/column/vector.test +1 -0
  120. data/test/command/suite/dump/record/scalar.catalog.json +12 -0
  121. data/test/command/suite/dump/record/scalar.expected +84 -0
  122. data/test/command/suite/dump/record/scalar.test +16 -0
  123. data/test/command/suite/dump/record/vector/reference.expected +83 -1
  124. data/test/command/suite/dump/record/vector/reference.test +1 -0
  125. data/test/command/suite/dump/table/array.expected +27 -1
  126. data/test/command/suite/dump/table/array.test +1 -0
  127. data/test/command/suite/dump/table/double_array_trie.expected +27 -1
  128. data/test/command/suite/dump/table/double_array_trie.test +1 -0
  129. data/test/command/suite/dump/table/hash.expected +27 -1
  130. data/test/command/suite/dump/table/hash.test +1 -0
  131. data/test/command/suite/dump/table/patricia_trie.expected +27 -1
  132. data/test/command/suite/dump/table/patricia_trie.test +1 -0
  133. data/test/command/suite/groonga/delete/{success.expected → key-integer.expected} +0 -0
  134. data/test/command/suite/groonga/delete/key-integer.test +17 -0
  135. data/test/command/suite/groonga/delete/key-string.expected +19 -0
  136. data/test/command/suite/groonga/delete/{success.test → key-string.test} +4 -6
  137. data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.expected +19 -0
  138. data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.test +17 -0
  139. data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.expected +19 -0
  140. data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.test +17 -0
  141. data/test/command/suite/message/error/missing-dataset.test +1 -0
  142. data/test/command/suite/system/absorb-data/records.catalog.json +58 -0
  143. data/test/command/suite/system/absorb-data/records.expected +32 -0
  144. data/test/command/suite/system/absorb-data/records.test +24 -0
  145. data/test/command/suite/system/statistics/object/count/empty.expected +11 -0
  146. data/test/command/suite/system/statistics/object/count/empty.test +12 -0
  147. data/test/command/suite/system/statistics/object/count/per-volume/empty.catalog.json +36 -0
  148. data/test/command/suite/system/statistics/object/count/per-volume/empty.expected +19 -0
  149. data/test/command/suite/system/statistics/object/count/per-volume/empty.test +12 -0
  150. data/test/command/suite/system/statistics/object/count/per-volume/record.catalog.json +40 -0
  151. data/test/command/suite/system/statistics/object/count/per-volume/record.expected +19 -0
  152. data/test/command/suite/system/statistics/object/count/per-volume/record.test +23 -0
  153. data/test/command/suite/system/statistics/object/count/per-volume/schema.catalog.json +40 -0
  154. data/test/command/suite/system/statistics/object/count/per-volume/schema.expected +19 -0
  155. data/test/command/suite/system/statistics/object/count/per-volume/schema.test +13 -0
  156. data/test/command/suite/system/statistics/object/count/record.catalog.json +12 -0
  157. data/test/command/suite/system/statistics/object/count/record.expected +11 -0
  158. data/test/command/suite/system/statistics/object/count/record.test +23 -0
  159. data/test/command/suite/system/statistics/object/count/schema.catalog.json +12 -0
  160. data/test/command/suite/system/statistics/object/count/schema.expected +11 -0
  161. data/test/command/suite/system/statistics/object/count/schema.test +13 -0
  162. data/test/command/suite/system/status.expected +3 -2
  163. data/test/unit/catalog/test_dataset.rb +4 -1
  164. data/test/unit/{test_catalog_generator.rb → catalog/test_generator.rb} +2 -2
  165. data/test/unit/catalog/test_replicas_volume.rb +79 -0
  166. data/test/unit/catalog/test_single_volume.rb +2 -2
  167. data/test/unit/catalog/test_slice.rb +33 -1
  168. data/test/unit/catalog/{test_collection_volume.rb → test_slices_volume.rb} +72 -11
  169. data/test/unit/catalog/test_version2.rb +3 -0
  170. data/test/unit/helper/distributed_search_planner_helper.rb +2 -2
  171. data/test/unit/plugins/catalog/test_fetch.rb +4 -4
  172. data/test/unit/plugins/crud/test_add.rb +44 -4
  173. data/test/unit/plugins/groonga/test_column_create.rb +4 -4
  174. data/test/unit/plugins/groonga/test_column_list.rb +4 -4
  175. data/test/unit/plugins/groonga/test_column_remove.rb +4 -4
  176. data/test/unit/plugins/groonga/test_column_rename.rb +4 -4
  177. data/test/unit/plugins/groonga/test_delete.rb +73 -10
  178. data/test/unit/plugins/groonga/test_table_create.rb +4 -4
  179. data/test/unit/plugins/groonga/test_table_list.rb +4 -4
  180. data/test/unit/plugins/groonga/test_table_remove.rb +4 -4
  181. data/test/unit/plugins/search/test_handler.rb +4 -4
  182. data/test/unit/plugins/search/test_planner.rb +4 -2
  183. data/test/unit/plugins/system/test_status.rb +31 -15
  184. data/test/unit/plugins/test_watch.rb +16 -16
  185. data/test/unit/test_address.rb +4 -4
  186. metadata +134 -35
  187. data/lib/droonga/catalog/volume_collection.rb +0 -79
  188. data/lib/droonga/catalog_fetcher.rb +0 -53
  189. data/lib/droonga/catalog_generator.rb +0 -243
  190. data/lib/droonga/catalog_loader.rb +0 -56
  191. data/lib/droonga/command/remote.rb +0 -404
  192. data/lib/droonga/data_absorber.rb +0 -264
  193. data/lib/droonga/node_status.rb +0 -71
  194. data/lib/droonga/serf_downloader.rb +0 -115
  195. data/test/unit/catalog/test_volume_collection.rb +0 -78
@@ -13,20 +13,24 @@
13
13
  # License along with this library; if not, write to the Free Software
14
14
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
15
 
16
+ require "time"
17
+
16
18
  require "droonga/replier"
17
19
  require "droonga/forwarder"
20
+ require "droonga/timestamp"
18
21
 
19
22
  module Droonga
20
23
  class HandlerMessenger
21
- attr_reader :database_name, :dispatcher, :engine_state
24
+ attr_reader :database_name, :dispatcher, :engine_state, :cluster
22
25
 
23
26
  def initialize(forwarder, message, options={})
24
27
  @forwarder = forwarder
25
- @message = message
26
- @options = options
27
- @replier = Replier.new(@forwarder)
28
- @dispatcher = options[:dispatcher]
29
- @engine_state = options[:engine_state]
28
+ @message = message
29
+ @options = options
30
+ @replier = Replier.new(@forwarder)
31
+ @dispatcher = options[:dispatcher]
32
+ @engine_state = options[:engine_state]
33
+ @cluster = options[:cluster]
30
34
  @database_name = options[:database]
31
35
  end
32
36
 
@@ -105,6 +109,7 @@ module Droonga
105
109
  #
106
110
  # @see Forwarder#forward
107
111
  def forward(droonga_message, destination)
112
+ droonga_message["date"] ||= new_date
108
113
  @forwarder.forward(droonga_message, destination)
109
114
  end
110
115
 
@@ -116,5 +121,9 @@ module Droonga
116
121
  def log_tag
117
122
  "[#{Process.ppid}] handler_messenger"
118
123
  end
124
+
125
+ def new_date
126
+ Timestamp.stringify(Time.now)
127
+ end
119
128
  end
120
129
  end
@@ -28,6 +28,7 @@ module Droonga
28
28
  @loop = loop
29
29
  @options = options
30
30
  @name = options[:name]
31
+ @label = options[:label]
31
32
  @dataset_name = options[:dataset]
32
33
  @database_name = options[:database]
33
34
  prepare
@@ -112,7 +113,11 @@ module Droonga
112
113
  handler_message.validate
113
114
 
114
115
  messenger = HandlerMessenger.new(@forwarder, handler_message, @options)
115
- handler = handler_class.new(@name, @context, messenger, @loop)
116
+ handler = handler_class.new(:name => @name,
117
+ :label => @label,
118
+ :context => @context,
119
+ :messenger => messenger,
120
+ :loop => @loop)
116
121
  begin
117
122
  result = handler.handle(handler_message)
118
123
  unless result.nil?
@@ -38,12 +38,22 @@ module Droonga
38
38
  [@host, @port]
39
39
  end
40
40
 
41
- def shutdown
42
- logger.trace("shutdown: start")
43
- shutdown_message_receiver
41
+ def shutdown_gracefully
42
+ logger.trace("shutdown_gracefully: start")
44
43
  shutdown_heartbeat_socket
45
44
  shutdown_listen_socket
46
- logger.trace("shutdown: done")
45
+ shutdown_message_receiver_gracefully do
46
+ yield
47
+ logger.trace("shutdown_gracefully: done")
48
+ end
49
+ end
50
+
51
+ def shutdown_immediately
52
+ logger.trace("shutdown_immediately: start")
53
+ shutdown_heartbeat_socket
54
+ shutdown_listen_socket
55
+ shutdown_message_receiver_immediately
56
+ logger.trace("shutdown_immediately: done")
47
57
  end
48
58
 
49
59
  private
@@ -56,6 +66,7 @@ module Droonga
56
66
 
57
67
  def shutdown_listen_socket
58
68
  logger.trace("shutdown_listen_socket: start")
69
+ @listen_socket.close
59
70
  logger.trace("shutdown_listen_socket: done")
60
71
  end
61
72
 
@@ -73,6 +84,8 @@ module Droonga
73
84
 
74
85
  def shutdown_heartbeat_socket
75
86
  logger.trace("shutdown_heartbeat_socket: start")
87
+ #XXX don't close the heartbeat socket here, because it is used by the generic receiver.
88
+ # @heartbeat_socket.close
76
89
  logger.trace("shutdown_heartbeat_socket: done")
77
90
  end
78
91
 
@@ -87,11 +100,18 @@ module Droonga
87
100
  logger.trace("start_heartbeat_socket: done")
88
101
  end
89
102
 
90
- # TODO: Use stop_gracefully/stop_immediately interface
91
- def shutdown_message_receiver
92
- logger.trace("shutdown_message_receiver: start")
103
+ def shutdown_message_receiver_gracefully
104
+ logger.trace("shutdown_message_receiver_gracefully: start")
105
+ @message_receiver.stop_gracefully do
106
+ yield
107
+ logger.trace("shutdown_message_receiver_gracefully: done")
108
+ end
109
+ end
110
+
111
+ def shutdown_message_receiver_immediately
112
+ logger.trace("shutdown_message_receiver_immediately: start")
93
113
  @message_receiver.stop_immediately
94
- logger.trace("shutdown_message_receiver: done")
114
+ logger.trace("shutdown_message_receiver_immediately: done")
95
115
  end
96
116
 
97
117
  def log_tag
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013-2014 Droonga Project
1
+ # Copyright (C) 2013-2015 Droonga Project
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -37,15 +37,21 @@ module Droonga
37
37
  end
38
38
  FileUtils.chmod(0600, @socket_path)
39
39
  @loop.attach(@server)
40
+ logger.trace("connect: socket watcher attached",
41
+ :watcher => @socket,
42
+ :socket_path => @socket_path)
40
43
  end
41
44
 
42
45
  def close
43
- @server.close if @server
46
+ return unless @server
47
+ @server.close
48
+ logger.trace("close: socket watcher detached",
49
+ :watcher => @socket)
44
50
  end
45
51
 
46
52
  def shutdown
47
53
  logger.trace("shutdown: start")
48
- @server.close if @server
54
+ close
49
55
  @job_queue.close
50
56
  FileUtils.rm_f(@socket_path)
51
57
  logger.trace("shutdown: done")
@@ -178,13 +184,10 @@ module Droonga
178
184
 
179
185
  private
180
186
  def setup_connection
181
- on_read = lambda do |data|
187
+ @connection.on_read do |data|
182
188
  @ready = (data == JobProtocol::READY_SIGNAL)
183
189
  @on_ready.call(self) if @on_ready
184
190
  end
185
- @connection.on_read do |data|
186
- on_read.call(data)
187
- end
188
191
  end
189
192
  end
190
193
  end
@@ -33,19 +33,24 @@ module Droonga
33
33
  @receiver = Coolio::UNIXSocket.connect(@socket_path)
34
34
  setup_receive_handler(@receiver)
35
35
  @loop.attach(@receiver)
36
+ logger.trace("start: socket watcher attached",
37
+ :watcher => @receiver,
38
+ :socket_path => @socket_path)
36
39
  logger.trace("start: done")
37
40
  end
38
41
 
39
42
  def shutdown
40
43
  logger.trace("shutdown: start")
41
44
  @receiver.close
45
+ logger.trace("shutdown: socket watcher attached",
46
+ :watcher => @receiver)
42
47
  logger.trace("shutdown: done")
43
48
  end
44
49
 
45
50
  private
46
51
  def setup_receive_handler(connection)
47
52
  unpacker = MessagePack::Unpacker.new
48
- on_read = lambda do |data|
53
+ connection.on_read do |data|
49
54
  logger.trace("on_read: start")
50
55
  unpacker.feed_each(data) do |message|
51
56
  @callback.call(message)
@@ -53,9 +58,6 @@ module Droonga
53
58
  logger.trace("on_read: done")
54
59
  send_ready(connection)
55
60
  end
56
- connection.on_read do |data|
57
- on_read.call(data)
58
- end
59
61
  send_ready(connection)
60
62
  end
61
63
 
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2013-2014 Droonga Project
3
+ # Copyright (C) 2013-2015 Droonga Project
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -119,12 +119,14 @@ module Droonga
119
119
  def log(level, message, data)
120
120
  return unless target_level?(level)
121
121
  @output.print(build_log_line(level, message, data))
122
+ @output.flush if debug_level?
122
123
  end
123
124
 
124
125
  def log_backtrace(level, backtrace)
125
126
  return unless target_level?(level)
126
127
  backtrace.each do |message|
127
128
  @output.write(build_log_line(level, message))
129
+ @output.flush if debug_level?
128
130
  end
129
131
  end
130
132
 
@@ -132,6 +134,10 @@ module Droonga
132
134
  @level <= level
133
135
  end
134
136
 
137
+ def debug_level?
138
+ @level <= Level::DEBUG
139
+ end
140
+
135
141
  def build_log_line(level, message, data={})
136
142
  line = "#{Time.now.iso8601}[#{Process.pid}][#{Level.label(level)}]: "
137
143
  line << "#{@tag}: " if @tag
@@ -0,0 +1,90 @@
1
+ # Copyright (C) 2015
2
+ # This library is free software; you can redistribute it and/or
3
+ # modify it under the terms of the GNU Lesser General Public
4
+ # License version 2.1 as published by the Free Software Foundation.
5
+ #
6
+ # This library is distributed in the hope that it will be useful,
7
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
+ # Lesser General Public License for more details.
10
+ #
11
+ # You should have received a copy of the GNU Lesser General Public
12
+ # License along with this library; if not, write to the Free Software
13
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14
+
15
+ require "socket"
16
+
17
+ module Droonga
18
+ class NodeName
19
+ class << self
20
+ def parse(string)
21
+ return string if string.is_a?(self)
22
+
23
+ if /\A(.+):(\d+)\/([^.]+)\z/ =~ string
24
+ components = {
25
+ :host => $1,
26
+ :port => $2.to_i,
27
+ :tag => $3,
28
+ }
29
+ new(components)
30
+ else
31
+ format = "${host_name}:${port_number}/${tag}"
32
+ message = "node name must be <#{format}> format: <#{string}>"
33
+ raise ArgumentError, message
34
+ end
35
+ end
36
+
37
+ def valid?(string)
38
+ begin
39
+ parse(string)
40
+ true
41
+ rescue ArgumentError
42
+ false
43
+ end
44
+ end
45
+ end
46
+
47
+ DEFAULT_HOST = Socket.gethostname
48
+ DEFAULT_HOST.force_encoding("US-ASCII") if DEFAULT_HOST.ascii_only?
49
+ DEFAULT_PORT = 10031
50
+ DEFAULT_TAG = "droonga"
51
+
52
+ attr_reader :host
53
+ attr_reader :port
54
+ attr_reader :tag
55
+
56
+ def initialize(components={})
57
+ if components.is_a?(self.class)
58
+ node_name = components
59
+ components = {
60
+ :host => node_name.host,
61
+ :port => node_name.port,
62
+ :tag => node_name.tag,
63
+ }
64
+ end
65
+
66
+ @host = components[:host] || DEFAULT_HOST
67
+ @port = components[:port] || DEFAULT_PORT
68
+ @tag = components[:tag] || DEFAULT_TAG
69
+ end
70
+
71
+ def to_s
72
+ node
73
+ end
74
+
75
+ def node
76
+ "#{@host}:#{@port}/#{@tag}"
77
+ end
78
+
79
+ def to_a
80
+ [@host, @port, @tag]
81
+ end
82
+
83
+ def ==(other)
84
+ if other.is_a?(String)
85
+ return to_s == other
86
+ end
87
+ other.is_a?(self.class) and to_a == other.to_a
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,72 @@
1
+ # Copyright (C) 2015 Droonga Project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
+
16
+ require "json"
17
+
18
+ require "droonga/path"
19
+ require "droonga/serf/tag"
20
+
21
+ module Droonga
22
+ class NodeRole
23
+ SERVICE_PROVIDER = "service-provider".downcase
24
+ ABSORB_SOURCE = "absorb-source".downcase
25
+ ABSORB_DESTINATION = "absorb-destination".downcase
26
+
27
+ ANY = "any".downcase
28
+
29
+ ROLES = [
30
+ SERVICE_PROVIDER,
31
+ ABSORB_SOURCE,
32
+ ABSORB_DESTINATION,
33
+ ]
34
+
35
+ class << self
36
+ def normalize(role)
37
+ new(role).to_s
38
+ end
39
+
40
+ def mine
41
+ if Path.serf_tags_file.exist?
42
+ tags = Path.serf_tags_file.read
43
+ tags = JSON.parse(tags)
44
+ role_from_tag = tags[Serf::Tag.node_role]
45
+ return role_from_tag.downcase if role_from_tag
46
+ end
47
+ SERVICE_PROVIDER
48
+ rescue Errno::ENOENT, JSON::ParserError
49
+ SERVICE_PROVIDER
50
+ end
51
+ end
52
+
53
+ def initialize(role)
54
+ @role = normalize(role)
55
+ end
56
+
57
+ def to_s
58
+ @role
59
+ end
60
+
61
+ private
62
+ def valid?(role)
63
+ ROLES.include?(role)
64
+ end
65
+
66
+ def normalize(role)
67
+ role = role.to_s.downcase
68
+ role = SERVICE_PROVIDER unless valid?(role)
69
+ role
70
+ end
71
+ end
72
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014 Droonga Project
1
+ # Copyright (C) 2014-2015 Droonga Project
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -44,12 +44,8 @@ module Droonga
44
44
  base + "state"
45
45
  end
46
46
 
47
- def node_status
48
- state + "status_file"
49
- end
50
-
51
- def live_nodes
52
- state + "live-nodes.json"
47
+ def cluster_state
48
+ state + "cluster-state.json"
53
49
  end
54
50
 
55
51
  def config
@@ -65,8 +61,24 @@ module Droonga
65
61
  Pathname.new(base_file_name).expand_path(base)
66
62
  end
67
63
 
68
- def buffer
69
- state + "buffer"
64
+ def last_message_timestamp
65
+ base + "last-message-timestamp.txt"
66
+ end
67
+
68
+ def accidental_buffer
69
+ state + "buffer" + "accidental"
70
+ end
71
+
72
+ def intentional_buffer
73
+ state + "buffer" + "intentional"
74
+ end
75
+
76
+ def serf_command
77
+ base + "serf"
78
+ end
79
+
80
+ def serf_tags_file
81
+ state + "serf-tags.json"
70
82
  end
71
83
 
72
84
  def serf_event_handler_errors
@@ -80,6 +92,19 @@ module Droonga
80
92
  now.hour, now.min, now.sec, now.nsec)
81
93
  serf_event_handler_errors + name
82
94
  end
95
+
96
+ def unique_file_path(directory, basename, suffix)
97
+ directory = Pathname(directory)
98
+ basename = basename.sub(/\.\z/, "")
99
+ suffix = suffix.sub(/\A\./, "")
100
+ uniqueness_count = 0
101
+ path = nil
102
+ begin
103
+ path = directory + "#{basename}.#{uniqueness_count}.#{suffix}"
104
+ uniqueness_count += 1
105
+ end while path.exist?
106
+ path
107
+ end
83
108
  end
84
109
  end
85
110
  end