droonga-engine 1.0.5 → 1.0.6

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 (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