droonga-engine 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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