droonga-engine 1.0.8 → 1.0.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e7b344e7b567ecc524d5f5cfb52ed6a67342a672
4
- data.tar.gz: 79ecc5c743f0f01f350a1855d55368dc024515a9
3
+ metadata.gz: f2574dab76722981c14a23373e838f1e01d18220
4
+ data.tar.gz: 9776825164dda315f20af0f0d610d2391cce93fd
5
5
  SHA512:
6
- metadata.gz: 1f94a76e05f59f76bbd6e92774bd928c10a01c8c731df1e9b548a0b255b61abfab538e3c374d1e1fd74244639cb140d9913ee09649226a2226ad54d458afd0a2
7
- data.tar.gz: 343bf2deb3d726858be67b61f222689535b939ea1ecce9d564f8f69a474e41cd22190600cf95e0b2e42f3e609ff244f44fcd9fafc946901fb2a89197de33a0b7
6
+ metadata.gz: 55b359cab3e5ca1bd0b7008233c54bbf413d27b97ee8d179ca09be701fa4f2749935cb37eaf743bfb0099600794c80d319edce22bedde28b69f685d944c8f193
7
+ data.tar.gz: 09add0504d2886e51065af0c09a4d350db98c8fe07e9a6de6f317ca08af34971016f57c2ac3706d4317df110d125077045c8973c996f4bda382a187cd903ffa0
@@ -18,6 +18,7 @@
18
18
  require "ostruct"
19
19
  require "optparse"
20
20
  require "open3"
21
+ require "socket"
21
22
 
22
23
  require "droonga/engine/version"
23
24
  require "droonga/catalog_generator"
@@ -34,6 +35,7 @@ class AbsorbDataCommand
34
35
 
35
36
  puts "Start to absorb data from #{@options.source_host}"
36
37
  puts " to #{@options.destination_host}"
38
+ puts " via #{@options.receiver_host} (this host)"
37
39
  puts " dataset = #{@options.dataset}"
38
40
  puts " port = #{@options.port}"
39
41
  puts " tag = #{@options.tag}"
@@ -57,6 +59,7 @@ class AbsorbDataCommand
57
59
  options.tag = Droonga::CatalogGenerator::DEFAULT_TAG
58
60
  options.dataset = Droonga::CatalogGenerator::DEFAULT_DATASET
59
61
  options.remote = true
62
+ options.receiver_host = Socket.gethostname
60
63
  options.messages_per_second = Droonga::DataAbsorber::DEFAULT_MESSAGES_PER_SECOND
61
64
  parser = OptionParser.new
62
65
  parser.version = Droonga::Engine::VERSION
@@ -71,6 +74,11 @@ class AbsorbDataCommand
71
74
  "Host name of this cluster to be connected.") do |host|
72
75
  options.destination_host = host
73
76
  end
77
+ parser.on("--receiver-host=HOST",
78
+ "Host name of this computer.",
79
+ "(#{options.receiver_host})") do |host|
80
+ options.receiver_host = host
81
+ end
74
82
  parser.on("--port=PORT", Integer,
75
83
  "Port number of the source cluster to be connected.",
76
84
  "(#{options.port})") do |port|
@@ -139,6 +147,7 @@ class AbsorbDataCommand
139
147
  :dataset => @options.dataset,
140
148
  :source_host => @options.source_host,
141
149
  :destination_host => @options.destination_host,
150
+ :receiver_host => @options.receiver_host,
142
151
  :port => @options.port,
143
152
  :tag => @options.tag,
144
153
  :messages_per_second => @options.messages_per_second,
@@ -18,6 +18,7 @@
18
18
  require "slop"
19
19
  require "json"
20
20
  require "pathname"
21
+ require "socket"
21
22
 
22
23
  require "droonga/engine/version"
23
24
  require "droonga/path"
@@ -30,6 +31,12 @@ class JoinCommand
30
31
  def run
31
32
  parse_options
32
33
  trap_signals
34
+
35
+ puts "Start to join a new node #{@options[:host]}"
36
+ puts " to the cluster of #{@options["replica-source-host"]}"
37
+ puts " via #{@options["receiver-host"]} (this host)"
38
+ puts ""
39
+
33
40
  set_node_role
34
41
  do_join
35
42
  sleep(5) #TODO: wait for restarting of the joining node. this should be done more safely.
@@ -54,6 +61,9 @@ class JoinCommand
54
61
  option.on("replica-source-host=",
55
62
  "Host name of the soruce node in the cluster to be connected.",
56
63
  :required => true)
64
+ option.on("receiver-host=",
65
+ "Host name of this host.",
66
+ :default => Socket.gethostname)
57
67
  option.on(:dataset=,
58
68
  "Dataset name of for the node to be joined.",
59
69
  :default => Droonga::CatalogGenerator::DEFAULT_DATASET)
@@ -101,6 +111,7 @@ class JoinCommand
101
111
  :dataset => @options[:dataset],
102
112
  :source_host => @options["replica-source-host"],
103
113
  :destination_host => @options[:host],
114
+ :receiver_host => @options["receiver-host"],
104
115
  :port => @options[:port],
105
116
  :tag => @options[:tag],
106
117
  :messages_per_second => @options["records-per-second"],
@@ -15,96 +15,121 @@
15
15
  # License along with this library; if not, write to the Free Software
16
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
 
18
- require "ostruct"
19
- require "optparse"
18
+ require "slop"
20
19
  require "json"
21
20
  require "pathname"
22
21
 
23
22
  require "droonga/engine/version"
24
23
  require "droonga/path"
24
+ require "droonga/catalog_fetcher"
25
25
  require "droonga/catalog_generator"
26
- require "droonga/safe_file_writer"
27
- require "droonga/service_installation"
28
26
  require "droonga/serf"
29
27
 
30
- service_installation = Droonga::ServiceInstallation.new
31
- service_installation.ensure_using_service_base_directory
32
-
33
- options = OpenStruct.new
34
- options.base_dir = ENV[Droonga::Path::BASE_DIR_ENV_NAME] || Dir.pwd
35
-
36
- parser = OptionParser.new
37
- parser.version = Droonga::Engine::VERSION
38
-
39
- parser.on("--base-dir=PATH",
40
- "Path to the base directory the catalog.json is located in.",
41
- "(#{options.base_dir})") do |path|
42
- options.base_dir = path
43
- end
44
- parser.on("--host=HOST",
45
- "Host name of the replica removed from cluster.") do |host|
46
- options.replica_remove_host = host
47
- end
48
-
49
- parser.parse!(ARGV)
50
-
51
-
52
- base_dir = Pathname(options.base_dir).expand_path
53
- ENV[Droonga::Path::BASE_DIR_ENV_NAME] = base_dir.to_s
54
-
55
-
56
- catalog_path = Droonga::Path.catalog
57
- unless catalog_path.exist?
58
- raise "Cannot load 'catalog.json'. You must specify correct path " +
59
- "to the base directory via --base-dir option."
60
- end
61
-
62
- unless options.replica_remove_host
63
- raise "You must specify the host name or the IP address of a node to " +
64
- "be removed from the cluster via --replica-remove-host option."
65
- end
66
-
67
- unless service_installation.have_read_permission?
68
- puts("You have no permission to read files under " +
69
- "<#{Droonga::Path.base.to_s}>.")
70
- puts("Try again with right permission.")
71
- exit(false)
72
- end
73
-
74
- source_catalog = JSON.parse(catalog_path.read)
75
- generator = Droonga::CatalogGenerator.new
76
- generator.load(source_catalog)
77
-
78
- dataset = generator.dataset_for_host(options.replica_remove_host)
79
- unless dataset
80
- raise "Specified host #{options.replica_remove_host} is not a member of "+
81
- "the cluster. You must specify correct host via --replica-remove-host " +
82
- "option."
28
+ class UnjoinCommand
29
+ def run
30
+ parse_options
31
+
32
+ puts "Start to unjoin a node #{@options[:host]}"
33
+ puts " by #{@options["receiver-host"]} (this host)"
34
+ puts ""
35
+
36
+ do_unjoin
37
+
38
+ puts("Done.")
39
+ exit(true)
40
+ end
41
+
42
+ private
43
+ def parse_options
44
+ options = Slop.parse(:help => true) do |option|
45
+ option.on(:host=,
46
+ "Host name of the replica removed from cluster.",
47
+ :required => true)
48
+ option.on("receiver-host=",
49
+ "Host name of this host.",
50
+ :default => Socket.gethostname)
51
+ option.on(:dataset=,
52
+ "Dataset name of for the node to be unjoined.",
53
+ :default => Droonga::CatalogGenerator::DEFAULT_DATASET)
54
+ option.on(:port=,
55
+ "Port number of the source cluster to be connected.",
56
+ :as => Integer,
57
+ :default => Droonga::CatalogGenerator::DEFAULT_PORT)
58
+ option.on(:tag=,
59
+ "Tag name of the soruce cluster to be connected.",
60
+ :default => Droonga::CatalogGenerator::DEFAULT_TAG)
61
+ end
62
+ @options = options
63
+ rescue Slop::MissingOptionError => error
64
+ $stderr.puts(error)
65
+ exit(false)
66
+ end
67
+
68
+ def replica_remove_host
69
+ @options[:host]
70
+ end
71
+
72
+ def tag
73
+ @options[:tag]
74
+ end
75
+
76
+ def port
77
+ @options[:port]
78
+ end
79
+
80
+ def dataset_name
81
+ @options[:dataset]
82
+ end
83
+
84
+ def replica_remove_node
85
+ "#{replica_remove_host}:#{port}/#{tag}"
86
+ end
87
+
88
+ def fetch_catalog
89
+ fetcher = Droonga::CatalogFetcher.new(:host => replica_remove_host,
90
+ :port => port,
91
+ :tag => tag,
92
+ :receiver_host => @options["receiver-host"])
93
+ fetcher.fetch(:dataset => dataset_name)
94
+ end
95
+
96
+ def remaining_node
97
+ @remaining_node ||= detect_remaining_node
98
+ end
99
+
100
+ def detect_remaining_node
101
+ catalog = fetch_catalog
102
+ generator = Droonga::CatalogGenerator.new
103
+ generator.load(catalog)
104
+
105
+ dataset = generator.dataset_for_host(replica_remove_host)
106
+ unless dataset
107
+ raise "Specified host #{replica_remove_host} is not a member of "+
108
+ "the cluster. You must specify correct host via --replica-remove-host " +
109
+ "option."
110
+ end
111
+
112
+ other_hosts = dataset.replicas.hosts
113
+
114
+ remaining_host = other_hosts.first || replica_remove_host
115
+ "#{remaining_host}:#{port}/#{tag}"
116
+ end
117
+
118
+ def run_remote_command(target, command, options)
119
+ serf = Droonga::Serf.new(nil, target)
120
+ result = serf.send_query(command, options)
121
+ puts(result[:result])
122
+ puts(result[:error]) unless result[:error].empty?
123
+ result[:response]
124
+ end
125
+
126
+ def do_unjoin
127
+ puts "Unjoining replica from the cluster..."
128
+
129
+ run_remote_command(remaining_node, "unjoin",
130
+ "dataset" => dataset_name,
131
+ "hosts" => [replica_remove_host])
132
+ end
83
133
  end
84
134
 
85
- options.dataset = dataset.name
86
- options.tag = dataset.replicas.tag
87
- options.port = dataset.replicas.port
88
- options.other_hosts = dataset.replicas.hosts
89
-
90
- remaining_host = options.other_hosts.first || options.replica_remove_host
91
- options.remaining_node = "#{remaining_host}:#{options.port}/#{options.tag}"
92
-
93
-
94
- def run_remote_command(target, command, options)
95
- serf = Droonga::Serf.new(nil, target)
96
- result = serf.send_query(command, options)
97
- puts result[:result]
98
- puts result[:error] unless result[:error].empty?
99
- end
100
-
101
-
102
- puts "Unjoining replica from the cluster..."
103
-
104
- run_remote_command(options.remaining_node, "remove_replicas",
105
- "dataset" => options.dataset,
106
- "hosts" => [options.replica_remove_host])
107
-
108
- puts "Done."
109
-
110
- exit(true)
135
+ UnjoinCommand.new.run
@@ -38,7 +38,7 @@ Gem::Specification.new do |gem|
38
38
  gem.add_dependency "archive-zip"
39
39
  gem.add_dependency "cool.io"
40
40
  gem.add_dependency "drndump"
41
- gem.add_dependency "droonga-client", ">= 0.2.0"
41
+ gem.add_dependency "droonga-client", ">= 0.1.9"
42
42
  gem.add_dependency "droonga-message-pack-packer", ">= 1.0.2"
43
43
  gem.add_dependency "groonga-command-parser"
44
44
  gem.add_dependency "faraday"
@@ -16,6 +16,7 @@
16
16
  require "digest/sha1"
17
17
  require "zlib"
18
18
  require "time"
19
+ require "digest"
19
20
  require "droonga/error_messages"
20
21
  require "droonga/catalog/errors"
21
22
 
@@ -37,7 +38,16 @@ module Droonga
37
38
  datasets[name]
38
39
  end
39
40
 
41
+ def cluster_id
42
+ @cluster_id ||= calculate_cluster_id
43
+ end
44
+
40
45
  private
46
+ def calculate_cluster_id
47
+ raw_id = all_nodes.sort.join(",")
48
+ Digest::SHA1.hexdigest(raw_id)
49
+ end
50
+
41
51
  def migrate_database_location(current_db_path, device, name)
42
52
  return if current_db_path.exist?
43
53
 
@@ -13,6 +13,8 @@
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 "socket"
17
+
16
18
  require "droonga/client"
17
19
 
18
20
  require "droonga/address"
@@ -43,7 +45,7 @@ module Droonga
43
45
  :tag => Address::DEFAULT_TAG,
44
46
  :protocol => :droonga,
45
47
  :timeout => 1,
46
- :receiver_host => "127.0.0.1",
48
+ :receiver_host => Socket.gethostname,
47
49
  :receiver_port => 0,
48
50
  }
49
51
  end
@@ -382,6 +382,7 @@ module Droonga
382
382
  catalog_observer = FileObserver.new(@loop, Path.catalog)
383
383
  catalog_observer.on_change = lambda do
384
384
  restart_graceful
385
+ @serf.update_cluster_id if @serf and @serf.running?
385
386
  end
386
387
  catalog_observer.start
387
388
  catalog_observer
@@ -327,7 +327,6 @@ module Droonga
327
327
  end
328
328
 
329
329
  @serf.join(*hosts)
330
- #XXX Now we should restart serf agent to remove unjoined nodes from the list of members...
331
330
  end
332
331
  end
333
332
 
@@ -359,8 +358,28 @@ module Droonga
359
358
  modifier.datasets[dataset].replicas.hosts -= hosts
360
359
  @service_installation.ensure_correct_file_permission(file)
361
360
  end
361
+ end
362
+ end
363
+
364
+ class Unjoin < ModifyReplicasBase
365
+ def process
366
+ return if dataset.nil? or hosts.nil?
367
+
368
+ log("unjoining replicas: #{hosts.join(",")}")
362
369
 
363
- #XXX Now we should restart serf agent to remove unjoined nodes from the list of members...
370
+ CatalogModifier.modify do |modifier, file|
371
+ if unjoining_node?
372
+ modifier.datasets[dataset].replicas.hosts = hosts
373
+ else
374
+ modifier.datasets[dataset].replicas.hosts -= hosts
375
+ end
376
+ @service_installation.ensure_correct_file_permission(file)
377
+ end
378
+ end
379
+
380
+ private
381
+ def unjoining_node?
382
+ hosts.include?(host)
364
383
  end
365
384
  end
366
385
 
@@ -77,6 +77,8 @@ module Droonga
77
77
  Remote::SetStatus
78
78
  when "join"
79
79
  Remote::Join
80
+ when "unjoin"
81
+ Remote::Unjoin
80
82
  when "set_replicas"
81
83
  Remote::SetReplicas
82
84
  when "add_replicas"
@@ -52,6 +52,7 @@ module Droonga
52
52
 
53
53
  @source_host = @params[:source_host]
54
54
  @destination_host = @params[:destination_host]
55
+ @receiver_host = @params[:receiver_host] || @destination_host
55
56
 
56
57
  @receiver_port = @params[:receiver_port]
57
58
  end
@@ -115,7 +116,7 @@ module Droonga
115
116
  :port => @port,
116
117
  :tag => @tag,
117
118
  :progocol => :droonga,
118
- :receiver_host => @destination_host,
119
+ :receiver_host => @receiver_host,
119
120
  :receiver_port => 0,
120
121
  }
121
122
  @source_client ||= Droonga::Client.new(options)
@@ -127,7 +128,7 @@ module Droonga
127
128
  :port => @port,
128
129
  :tag => @tag,
129
130
  :progocol => :droonga,
130
- :receiver_host => @destination_host,
131
+ :receiver_host => @receiver_host,
131
132
  :receiver_port => 0,
132
133
  }
133
134
  @destination_client ||= Droonga::Client.new(options)
@@ -152,7 +153,7 @@ module Droonga
152
153
  options += ["--port", @port]
153
154
  options += ["--tag", @tag]
154
155
  options += ["--dataset", @dataset]
155
- options += ["--receiver-host", @destination_host]
156
+ options += ["--receiver-host", @receiver_host]
156
157
  options += ["--receiver-port", @receiver_port] if @receiver_port
157
158
  options.collect(&:to_s)
158
159
  end
@@ -162,7 +163,7 @@ module Droonga
162
163
  options += ["--host", @destination_host]
163
164
  options += ["--port", @port]
164
165
  options += ["--tag", @tag]
165
- options += ["--receiver-host", @destination_host]
166
+ options += ["--receiver-host", @receiver_host]
166
167
  options += ["--receiver-port", @receiver_port] if @receiver_port
167
168
  options.collect(&:to_s)
168
169
  end
@@ -252,7 +253,7 @@ module Droonga
252
253
  fetcher = CatalogFetcher.new(:host => @source_host,
253
254
  :port => @port,
254
255
  :tag => @tag,
255
- :receiver_host => @destination_host)
256
+ :receiver_host => @receiver_host)
256
257
  fetcher.fetch(:dataset => @dataset)
257
258
  end
258
259
 
@@ -15,6 +15,6 @@
15
15
 
16
16
  module Droonga
17
17
  class Engine
18
- VERSION = "1.0.8"
18
+ VERSION = "1.0.9"
19
19
  end
20
20
  end
data/lib/droonga/serf.rb CHANGED
@@ -71,6 +71,7 @@ module Droonga
71
71
  "-event-handler", "droonga-engine-serf-event-handler",
72
72
  "-log-level", log_level,
73
73
  "-tag", "role=engine",
74
+ "-tag", "cluster_id=#{cluster_id}",
74
75
  *retry_joins)
75
76
  logger.trace("start: done")
76
77
  end
@@ -87,6 +88,13 @@ module Droonga
87
88
  logger.trace("stop: done")
88
89
  end
89
90
 
91
+ def restart
92
+ logger.trace("restart: start")
93
+ stop
94
+ start
95
+ logger.trace("restart: done")
96
+ end
97
+
90
98
  def join(*hosts)
91
99
  ensure_serf
92
100
  nodes = hosts.collect do |host|
@@ -123,8 +131,10 @@ module Droonga
123
131
  result = run_once("members", "-format", "json")
124
132
  result[:result] = JSON.parse(result[:result])
125
133
  members = result[:result]
134
+ current_cluster_id = cluster_id
126
135
  members["members"].each do |member|
127
- if member["status"] == "alive"
136
+ if member["status"] == "alive" and
137
+ member["tags"]["cluster_id"] == current_cluster_id
128
138
  nodes[member["name"]] = {
129
139
  "serfAddress" => member["addr"],
130
140
  "tags" => member["tags"],
@@ -134,6 +144,21 @@ module Droonga
134
144
  nodes
135
145
  end
136
146
 
147
+ def set_tag(name, value)
148
+ ensure_serf
149
+ run_once("tags", "-set", "#{name}=#{value}")
150
+ end
151
+
152
+ def update_cluster_id
153
+ set_tag("cluster_id", cluster_id)
154
+ end
155
+
156
+ def cluster_id
157
+ loader = CatalogLoader.new(Path.catalog.to_s)
158
+ catalog = loader.load
159
+ catalog.cluster_id
160
+ end
161
+
137
162
  private
138
163
  def ensure_serf
139
164
  @serf = find_system_serf
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: droonga-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Droonga Project
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-28 00:00:00.000000000 Z
11
+ date: 2014-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: archive-zip
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.2.0
61
+ version: 0.1.9
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.2.0
68
+ version: 0.1.9
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: droonga-message-pack-packer
71
71
  requirement: !ruby/object:Gem::Requirement