droonga-engine 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/bin/droonga-engine-absorb-data +2 -1
  3. data/bin/droonga-engine-catalog-generate +21 -5
  4. data/bin/droonga-engine-catalog-modify +22 -6
  5. data/bin/droonga-engine-configure +215 -0
  6. data/bin/droonga-engine-join +48 -123
  7. data/bin/droonga-engine-unjoin +14 -1
  8. data/doc/text/news.md +21 -0
  9. data/droonga-engine.gemspec +12 -10
  10. data/install/centos/droonga-engine +60 -0
  11. data/install/centos/functions.sh +35 -0
  12. data/install/debian/droonga-engine +155 -0
  13. data/install/debian/functions.sh +33 -0
  14. data/install.sh +360 -0
  15. data/lib/droonga/address.rb +3 -1
  16. data/lib/droonga/catalog/dataset.rb +2 -0
  17. data/lib/droonga/catalog/version1.rb +16 -3
  18. data/lib/droonga/catalog/version2.rb +16 -3
  19. data/lib/droonga/catalog_fetcher.rb +51 -0
  20. data/lib/droonga/catalog_generator.rb +6 -5
  21. data/lib/droonga/catalog_modifier.rb +45 -0
  22. data/lib/droonga/command/droonga_engine.rb +96 -29
  23. data/lib/droonga/command/droonga_engine_service.rb +5 -0
  24. data/lib/droonga/command/remote.rb +368 -0
  25. data/lib/droonga/command/serf_event_handler.rb +37 -304
  26. data/lib/droonga/dispatcher.rb +15 -1
  27. data/lib/droonga/engine/version.rb +1 -1
  28. data/lib/droonga/engine.rb +11 -4
  29. data/lib/droonga/engine_state.rb +2 -0
  30. data/lib/droonga/farm.rb +14 -5
  31. data/lib/droonga/fluent_message_receiver.rb +23 -6
  32. data/lib/droonga/fluent_message_sender.rb +5 -1
  33. data/lib/droonga/node_status.rb +67 -0
  34. data/lib/droonga/path.rb +28 -4
  35. data/lib/droonga/plugins/catalog.rb +40 -0
  36. data/lib/droonga/safe_file_writer.rb +1 -1
  37. data/lib/droonga/searcher.rb +3 -15
  38. data/lib/droonga/serf.rb +17 -32
  39. data/lib/droonga/serf_downloader.rb +26 -1
  40. data/lib/droonga/service_installation.rb +123 -0
  41. data/lib/droonga/session.rb +4 -0
  42. data/lib/droonga/slice.rb +22 -12
  43. data/lib/droonga/supervisor.rb +16 -2
  44. data/lib/droonga/worker_process_agent.rb +13 -1
  45. data/sample/droonga-engine.yaml +5 -0
  46. data/test/command/config/default/catalog.json +1 -1
  47. data/test/command/config/default/droonga-engine.yaml +4 -0
  48. data/test/command/config/version1/catalog.json +1 -1
  49. data/test/command/suite/catalog/fetch.expected +64 -0
  50. data/test/command/suite/catalog/fetch.test +6 -0
  51. data/test/unit/catalog/test_version1.rb +2 -2
  52. data/test/unit/catalog/test_version2.rb +3 -3
  53. data/test/unit/helper/sandbox.rb +3 -1
  54. data/test/unit/plugins/catalog/test_fetch.rb +76 -0
  55. data/test/unit/test_catalog_generator.rb +7 -3
  56. metadata +74 -27
  57. data/bin/droonga-engine-data-publisher +0 -66
@@ -14,6 +14,8 @@
14
14
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
15
 
16
16
  require "English"
17
+ require "pathname"
18
+ require "fileutils"
17
19
 
18
20
  require "droonga/catalog/base"
19
21
  require "droonga/catalog/dataset"
@@ -51,11 +53,14 @@ module Droonga
51
53
  part["partitions"].each do |range, partitions|
52
54
  partitions.each do |partition|
53
55
  if partition =~ pattern
54
- path = File.join([device, $POSTMATCH, "db"])
55
- path = File.expand_path(path, base_path)
56
+ database_name = $POSTMATCH
57
+ path = File.join([device, Path.databases.basename.to_s, database_name, "db"])
58
+ path = Pathname(path).expand_path(base_path)
59
+ migrate_database_location(path, :device => device,
60
+ :name => database_name)
56
61
  options = {
57
62
  :dataset => dataset_name,
58
- :database => path,
63
+ :database => path.to_s,
59
64
  :n_workers => workers,
60
65
  :plugins => plugins
61
66
  }
@@ -384,6 +389,14 @@ module Droonga
384
389
  end
385
390
  end
386
391
 
392
+ def migrate_database_location(path, params)
393
+ old_path = File.join([params[:device], params[:name], "db"])
394
+ old_path = Pathname(old_path).expand_path(base_path)
395
+ if old_path.exist? and not path.exist?
396
+ FileUtils.move(old_path.to_s, path.to_s)
397
+ end
398
+ end
399
+
387
400
  class Dataset < Catalog::Dataset
388
401
  def compute_routes(args, live_nodes=nil)
389
402
  routes = []
@@ -13,6 +13,9 @@
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 "pathname"
17
+ require "fileutils"
18
+
16
19
  require "droonga/address"
17
20
  require "droonga/catalog/base"
18
21
  require "droonga/catalog/dataset"
@@ -41,11 +44,13 @@ module Droonga
41
44
  volume.slices.each do |slice|
42
45
  volume_address = slice.volume.address
43
46
  if volume_address.node == node
44
- path = File.join([device, volume_address.name, "db"])
45
- path = File.expand_path(path, base_path)
47
+ path = File.join([device, Path.databases.basename.to_s, volume_address.name, "db"])
48
+ path = Pathname(path).expand_path(base_path)
49
+ migrate_database_location(path, :device => device,
50
+ :name => volume_address.name)
46
51
  options = {
47
52
  :dataset => dataset_name,
48
- :database => path,
53
+ :database => path.to_s,
49
54
  :n_workers => n_workers,
50
55
  :plugins => plugins
51
56
  }
@@ -81,6 +86,14 @@ module Droonga
81
86
  end
82
87
  nodes.sort.uniq
83
88
  end
89
+
90
+ def migrate_database_location(path, params)
91
+ old_path = File.join([params[:device], params[:name], "db"])
92
+ old_path = Pathname(old_path).expand_path(base_path)
93
+ if old_path.exist? and not path.exist?
94
+ FileUtils.move(old_path.to_s, path.to_s)
95
+ end
96
+ end
84
97
  end
85
98
  end
86
99
  end
@@ -0,0 +1,51 @@
1
+ # Copyright (C) 2014 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 "droonga/client"
17
+
18
+ require "droonga/address"
19
+ require "droonga/catalog/dataset"
20
+
21
+ module Droonga
22
+ class CatalogFetcher
23
+ def initialize(client_options)
24
+ @client_options = default_options.merge(client_options)
25
+ end
26
+
27
+ def fetch(options={})
28
+ message = {
29
+ "dataset" => options[:dataset] || Catalog::Dataset::DEFAULT_NAME,
30
+ "type" => "catalog.fetch"
31
+ }
32
+ Droonga::Client.open(@client_options) do |client|
33
+ response = client.request(message)
34
+ response["body"]
35
+ end
36
+ end
37
+
38
+ private
39
+ def default_options
40
+ {
41
+ :host => "127.0.0.1",
42
+ :port => Address::DEFAULT_PORT,
43
+ :tag => Address::DEFAULT_TAG,
44
+ :protocol => :droonga,
45
+ :timeout => 1,
46
+ :receiver_host => "127.0.0.1",
47
+ :receiver_port => 0,
48
+ }
49
+ end
50
+ end
51
+ end
@@ -15,17 +15,18 @@
15
15
 
16
16
  require "time"
17
17
 
18
+ require "droonga/address"
18
19
  require "droonga/catalog/dataset"
19
20
 
20
21
  module Droonga
21
22
  class CatalogGenerator
22
- DEFAULT_DATASET = "Default"
23
- DEFAULT_HOSTS = ["127.0.0.1"]
23
+ DEFAULT_DATASET = Catalog::Dataset::DEFAULT_NAME
24
+ DEFAULT_HOSTS = [Address::DEFAULT_HOST]
24
25
  DEFAULT_N_WORKERS = 4
25
26
  DEFAULT_N_SLICES = 1
26
- DEFAULT_PLUGINS = ["groonga", "search", "crud", "dump", "system"]
27
- DEFAULT_PORT = 10031
28
- DEFAULT_TAG = "droonga"
27
+ DEFAULT_PLUGINS = ["groonga", "search", "crud", "dump", "system", "catalog"]
28
+ DEFAULT_PORT = Address::DEFAULT_PORT
29
+ DEFAULT_TAG = Address::DEFAULT_TAG
29
30
 
30
31
  attr_reader :datasets
31
32
 
@@ -0,0 +1,45 @@
1
+ # Copyright (C) 2014 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/catalog_generator"
20
+ require "droonga/safe_file_writer"
21
+
22
+ module Droonga
23
+ class CatalogModifier
24
+ class << self
25
+ def modify
26
+ new.modify do |generator, file|
27
+ yield(generator, file)
28
+ end
29
+ end
30
+ end
31
+
32
+ def initialize
33
+ @generator = CatalogGenerator.new
34
+ @catalog = JSON.parse(Path.catalog.read)
35
+ @generator.load(@catalog)
36
+ end
37
+
38
+ def modify
39
+ SafeFileWriter.write(Path.catalog) do |output, file|
40
+ yield(@generator, file)
41
+ output.puts(JSON.pretty_generate(@generator.generate))
42
+ end
43
+ end
44
+ end
45
+ end
@@ -17,12 +17,16 @@ require "optparse"
17
17
  require "socket"
18
18
  require "ipaddr"
19
19
  require "fileutils"
20
+ require "yaml"
20
21
 
21
22
  require "coolio"
22
23
  require "sigdump"
23
24
 
25
+ require "droonga/engine/version"
24
26
  require "droonga/path"
27
+ require "droonga/address"
25
28
  require "droonga/serf"
29
+ require "droonga/node_status"
26
30
  require "droonga/file_observer"
27
31
  require "droonga/process_supervisor"
28
32
 
@@ -59,6 +63,7 @@ module Droonga
59
63
  private
60
64
  def parse_command_line_arguments!(command_line_arguments)
61
65
  parser = OptionParser.new
66
+ parser.version = Engine::VERSION
62
67
  @configuration.add_command_line_options(parser)
63
68
  parser.parse!(command_line_arguments)
64
69
  end
@@ -108,19 +113,74 @@ module Droonga
108
113
  end
109
114
 
110
115
  class Configuration
111
- DEFAULT_HOST = Socket.gethostname
112
- DEFAULT_PORT = 10031
113
-
114
116
  attr_reader :host, :port, :tag, :log_file, :pid_file_path
115
117
  attr_reader :ready_notify_fd
116
118
  def initialize
117
- @host = DEFAULT_HOST
118
- @port = DEFAULT_PORT
119
- @tag = "droonga"
120
- @log_file = nil
121
- @daemon = false
122
- @pid_file_path = nil
119
+ config = load_config
120
+
121
+ @host = config["host"] || Address::DEFAULT_HOST
122
+ @port = config["port"] || Address::DEFAULT_PORT
123
+ @tag = config["tag"] || Address::DEFAULT_TAG
124
+
125
+ @given_values = {}
126
+
127
+ @log_file = nil
128
+ @daemon = false
129
+ @pid_file_path = nil
123
130
  @ready_notify_fd = nil
131
+
132
+ if have_config_file?
133
+ if config.include?("daemon")
134
+ @daemon = config["daemon"]
135
+ else
136
+ @daemon = true
137
+ end
138
+ if @daemon
139
+ self.pid_file_path = config["pid_file"] || Path.default_pid_file
140
+ end
141
+ self.log_file = config["log_file"] || Path.default_log_file
142
+ self.log_level = config["log_level"] if config.include?("log_level")
143
+ end
144
+ end
145
+
146
+ def have_config_file?
147
+ File.exist?(Path.config)
148
+ end
149
+
150
+ def have_given_host?
151
+ @given_values.include?(:host)
152
+ end
153
+
154
+ def have_given_port?
155
+ @given_values.include?(:port)
156
+ end
157
+
158
+ def have_given_tag?
159
+ @given_values.include?(:tag)
160
+ end
161
+
162
+ def have_given_daemon?
163
+ @given_values.include?(:daemon)
164
+ end
165
+
166
+ def have_given_log_file?
167
+ @given_values.include?(:log_file)
168
+ end
169
+
170
+ def have_given_log_level?
171
+ @given_values.include?(:log_level)
172
+ end
173
+
174
+ def have_given_pid_file?
175
+ @given_values.include?(:pid_file)
176
+ end
177
+
178
+ def load_config
179
+ if have_config_file?
180
+ YAML.load_file(Path.config)
181
+ else
182
+ {}
183
+ end
124
184
  end
125
185
 
126
186
  def engine_name
@@ -136,6 +196,18 @@ module Droonga
136
196
  ENV["DROONGA_LOG_LEVEL"] || Logger::Level.default
137
197
  end
138
198
 
199
+ def log_level=(level)
200
+ ENV["DROONGA_LOG_LEVEL"] = level
201
+ end
202
+
203
+ def log_file=(file)
204
+ @log_file = File.expand_path(file)
205
+ end
206
+
207
+ def pid_file_path=(path)
208
+ @pid_file_path = Pathname.new(path).expand_path
209
+ end
210
+
139
211
  def daemon?
140
212
  @daemon
141
213
  end
@@ -171,16 +243,19 @@ module Droonga
171
243
  "The host name of the Droonga engine",
172
244
  "(#{@host})") do |host|
173
245
  @host = host
246
+ @given_values[:host] = host
174
247
  end
175
248
  parser.on("--port=PORT", Integer,
176
249
  "The port number of the Droonga engine",
177
250
  "(#{@port})") do |port|
178
251
  @port = port
252
+ @given_values[:port] = port
179
253
  end
180
254
  parser.on("--tag=TAG",
181
255
  "The tag of the Droonga engine",
182
256
  "(#{@tag})") do |tag|
183
257
  @tag = tag
258
+ @given_values[:tag] = tag
184
259
  end
185
260
  end
186
261
 
@@ -193,11 +268,13 @@ module Droonga
193
268
  "The log level of the Droonga engine",
194
269
  "[#{levels_label}]",
195
270
  "(#{log_level})") do |level|
196
- ENV["DROONGA_LOG_LEVEL"] = level
271
+ self.log_level = level
272
+ @given_values[:log_level] = log_level
197
273
  end
198
274
  parser.on("--log-file=FILE",
199
275
  "Output logs to FILE") do |file|
200
- @log_file = File.expand_path(file)
276
+ self.log_file = file
277
+ @given_values[:log_file] = file
201
278
  end
202
279
  end
203
280
 
@@ -207,10 +284,17 @@ module Droonga
207
284
  parser.on("--daemon",
208
285
  "Run as a daemon") do
209
286
  @daemon = true
287
+ @given_values[:daemon] = true
288
+ end
289
+ parser.on("--no-daemon",
290
+ "Run as a regular process") do
291
+ @daemon = false
292
+ @given_values[:daemon] = false
210
293
  end
211
294
  parser.on("--pid-file=PATH",
212
295
  "Put PID to PATH") do |path|
213
- @pid_file_path = Pathname.new(path).expand_path
296
+ self.pid_file_path = path
297
+ @given_values[:pid_file] = path
214
298
  end
215
299
  end
216
300
 
@@ -248,7 +332,6 @@ module Droonga
248
332
 
249
333
  def run
250
334
  @serf = run_serf
251
- @serf_status_observer = run_serf_status_observer
252
335
  @service_runner = run_service
253
336
  setup_initial_on_ready
254
337
  @catalog_observer = run_catalog_observer
@@ -298,7 +381,6 @@ module Droonga
298
381
  def stop_gracefully
299
382
  @command_runner.stop
300
383
  @serf.stop
301
- @serf_status_observer.stop
302
384
  @catalog_observer.stop
303
385
  @service_runner.stop_gracefully
304
386
  end
@@ -306,7 +388,6 @@ module Droonga
306
388
  def stop_immediately
307
389
  @command_runner.stop
308
390
  @serf.stop
309
- @serf_status_observer.stop
310
391
  @catalog_observer.stop
311
392
  @service_runner.stop_immediately
312
393
  end
@@ -342,20 +423,6 @@ module Droonga
342
423
  serf
343
424
  end
344
425
 
345
- def restart_serf
346
- @serf.stop if @serf
347
- @serf = run_serf
348
- end
349
-
350
- def run_serf_status_observer
351
- serf_status_observer = FileObserver.new(@loop, Serf.status_file)
352
- serf_status_observer.on_change = lambda do
353
- restart_serf
354
- end
355
- serf_status_observer.start
356
- serf_status_observer
357
- end
358
-
359
426
  def run_catalog_observer
360
427
  catalog_observer = FileObserver.new(@loop, Path.catalog)
361
428
  catalog_observer.on_change = lambda do
@@ -204,11 +204,16 @@ module Droonga
204
204
 
205
205
  def stop_gracefully
206
206
  return if @stopping
207
+ logger.trace("stop_gracefully: start")
207
208
  @stopping = true
208
209
  @receiver.stop_gracefully
209
210
  @engine.stop_gracefully do
210
211
  shutdown_worker_process_agent
211
212
  shutdown_internal_message_receiver
213
+ @receiver.shutdown_clients
214
+ logger.trace("stop_gracefully: done",
215
+ :n_rest_watchers => @loop.watchers.size,
216
+ :rest_watchers => @loop.watchers)
212
217
  end
213
218
  end
214
219