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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/benchmark/timer-watcher/benchmark.rb +44 -0
- data/bin/droonga-engine-absorb-data +246 -187
- data/bin/droonga-engine-catalog-generate +12 -12
- data/bin/droonga-engine-catalog-modify +4 -4
- data/bin/droonga-engine-join +352 -171
- data/bin/droonga-engine-set-role +54 -0
- data/bin/droonga-engine-unjoin +107 -112
- data/droonga-engine.gemspec +3 -3
- data/install.sh +55 -36
- data/install/centos/functions.sh +2 -2
- data/install/debian/functions.sh +2 -2
- data/lib/droonga/address.rb +26 -24
- data/lib/droonga/buffered_tcp_socket.rb +65 -10
- data/lib/droonga/catalog/base.rb +9 -6
- data/lib/droonga/catalog/dataset.rb +17 -41
- data/lib/droonga/catalog/fetcher.rb +64 -0
- data/lib/droonga/catalog/generator.rb +245 -0
- data/lib/droonga/catalog/loader.rb +66 -0
- data/lib/droonga/{catalog_modifier.rb → catalog/modifier.rb} +11 -18
- data/lib/droonga/catalog/replicas_volume.rb +123 -0
- data/lib/droonga/catalog/schema.rb +37 -37
- data/lib/droonga/catalog/single_volume.rb +11 -3
- data/lib/droonga/catalog/slice.rb +10 -6
- data/lib/droonga/catalog/{collection_volume.rb → slices_volume.rb} +47 -11
- data/lib/droonga/catalog/version1.rb +47 -19
- data/lib/droonga/catalog/version2.rb +11 -10
- data/lib/droonga/catalog/version2_validator.rb +4 -4
- data/lib/droonga/catalog/volume.rb +17 -5
- data/lib/droonga/changable.rb +25 -0
- data/lib/droonga/cluster.rb +237 -0
- data/lib/droonga/collector_runner.rb +4 -0
- data/lib/droonga/collectors.rb +2 -1
- data/lib/droonga/collectors/recursive_sum.rb +26 -0
- data/lib/droonga/command/droonga_engine.rb +404 -127
- data/lib/droonga/command/droonga_engine_service.rb +47 -11
- data/lib/droonga/command/droonga_engine_worker.rb +21 -1
- data/lib/droonga/command/remote_command_base.rb +78 -0
- data/lib/droonga/command/serf_event_handler.rb +29 -20
- data/lib/droonga/data_absorber_client.rb +222 -0
- data/lib/droonga/database_scanner.rb +106 -0
- data/lib/droonga/{live_nodes_list_loader.rb → deferrable.rb} +11 -24
- data/lib/droonga/differ.rb +58 -0
- data/lib/droonga/dispatcher.rb +155 -32
- data/lib/droonga/distributed_command_planner.rb +9 -11
- data/lib/droonga/engine.rb +83 -78
- data/lib/droonga/engine/version.rb +1 -1
- data/lib/droonga/engine_node.rb +301 -0
- data/lib/droonga/engine_state.rb +62 -40
- data/lib/droonga/farm.rb +44 -5
- data/lib/droonga/file_observer.rb +16 -12
- data/lib/droonga/fluent_message_receiver.rb +98 -29
- data/lib/droonga/fluent_message_sender.rb +30 -23
- data/lib/droonga/forward_buffer.rb +160 -0
- data/lib/droonga/forwarder.rb +73 -40
- data/lib/droonga/handler.rb +7 -6
- data/lib/droonga/handler_messenger.rb +15 -6
- data/lib/droonga/handler_runner.rb +6 -1
- data/lib/droonga/internal_fluent_message_receiver.rb +28 -8
- data/lib/droonga/job_pusher.rb +10 -7
- data/lib/droonga/job_receiver.rb +6 -4
- data/lib/droonga/logger.rb +7 -1
- data/lib/droonga/node_name.rb +90 -0
- data/lib/droonga/node_role.rb +72 -0
- data/lib/droonga/path.rb +34 -9
- data/lib/droonga/planner.rb +73 -7
- data/lib/droonga/plugin/async_command.rb +154 -0
- data/lib/droonga/plugins/catalog.rb +1 -0
- data/lib/droonga/plugins/crud.rb +22 -6
- data/lib/droonga/plugins/dump.rb +66 -135
- data/lib/droonga/plugins/groonga/delete.rb +13 -0
- data/lib/droonga/plugins/search/distributed_search_planner.rb +4 -4
- data/lib/droonga/plugins/system.rb +5 -26
- data/lib/droonga/plugins/system/absorb_data.rb +405 -0
- data/lib/droonga/plugins/system/statistics.rb +71 -0
- data/lib/droonga/plugins/system/status.rb +53 -0
- data/lib/droonga/process_control_protocol.rb +3 -1
- data/lib/droonga/process_supervisor.rb +32 -15
- data/lib/droonga/reducer.rb +69 -0
- data/lib/droonga/safe_file_writer.rb +1 -1
- data/lib/droonga/serf.rb +207 -276
- data/lib/droonga/serf/agent.rb +228 -0
- data/lib/droonga/serf/command.rb +94 -0
- data/lib/droonga/serf/downloader.rb +120 -0
- data/lib/droonga/serf/remote_command.rb +348 -0
- data/lib/droonga/serf/tag.rb +56 -0
- data/lib/droonga/service_installation.rb +2 -2
- data/lib/droonga/session.rb +49 -1
- data/lib/droonga/single_step.rb +6 -11
- data/lib/droonga/single_step_definition.rb +32 -1
- data/lib/droonga/slice.rb +14 -9
- data/lib/droonga/supervisor.rb +27 -20
- data/lib/droonga/test/stub_handler_messenger.rb +2 -1
- data/lib/droonga/timestamp.rb +69 -0
- data/lib/droonga/worker_process_agent.rb +33 -15
- data/sample/cluster-state.json +8 -0
- data/sample/cluster/Rakefile +30 -6
- data/test/command/fixture/integer-key-table.jsons +11 -0
- data/test/command/fixture/string-key-table.jsons +11 -0
- data/test/command/run-test.rb +4 -0
- data/test/command/suite/add/error/invalid-integer.expected +3 -3
- data/test/command/suite/add/error/invalid-time.expected +3 -3
- data/test/command/suite/add/{minimum.expected → key-integer.expected} +0 -0
- data/test/command/suite/add/{minimum.test → key-integer.test} +0 -0
- data/test/command/suite/add/key-string.expected +6 -0
- data/test/command/suite/add/key-string.test +9 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.expected +6 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.test +9 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.expected +6 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.test +9 -0
- data/test/command/suite/add/without-values.expected +6 -0
- data/test/command/suite/add/without-values.test +11 -0
- data/test/command/suite/dump/column/index.expected +33 -1
- data/test/command/suite/dump/column/index.test +1 -0
- data/test/command/suite/dump/column/scalar.expected +29 -1
- data/test/command/suite/dump/column/scalar.test +1 -0
- data/test/command/suite/dump/column/vector.expected +29 -1
- data/test/command/suite/dump/column/vector.test +1 -0
- data/test/command/suite/dump/record/scalar.catalog.json +12 -0
- data/test/command/suite/dump/record/scalar.expected +84 -0
- data/test/command/suite/dump/record/scalar.test +16 -0
- data/test/command/suite/dump/record/vector/reference.expected +83 -1
- data/test/command/suite/dump/record/vector/reference.test +1 -0
- data/test/command/suite/dump/table/array.expected +27 -1
- data/test/command/suite/dump/table/array.test +1 -0
- data/test/command/suite/dump/table/double_array_trie.expected +27 -1
- data/test/command/suite/dump/table/double_array_trie.test +1 -0
- data/test/command/suite/dump/table/hash.expected +27 -1
- data/test/command/suite/dump/table/hash.test +1 -0
- data/test/command/suite/dump/table/patricia_trie.expected +27 -1
- data/test/command/suite/dump/table/patricia_trie.test +1 -0
- data/test/command/suite/groonga/delete/{success.expected → key-integer.expected} +0 -0
- data/test/command/suite/groonga/delete/key-integer.test +17 -0
- data/test/command/suite/groonga/delete/key-string.expected +19 -0
- data/test/command/suite/groonga/delete/{success.test → key-string.test} +4 -6
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.expected +19 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.test +17 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.expected +19 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.test +17 -0
- data/test/command/suite/message/error/missing-dataset.test +1 -0
- data/test/command/suite/system/absorb-data/records.catalog.json +58 -0
- data/test/command/suite/system/absorb-data/records.expected +32 -0
- data/test/command/suite/system/absorb-data/records.test +24 -0
- data/test/command/suite/system/statistics/object/count/empty.expected +11 -0
- data/test/command/suite/system/statistics/object/count/empty.test +12 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.catalog.json +36 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.test +12 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.catalog.json +40 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.test +23 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.catalog.json +40 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.test +13 -0
- data/test/command/suite/system/statistics/object/count/record.catalog.json +12 -0
- data/test/command/suite/system/statistics/object/count/record.expected +11 -0
- data/test/command/suite/system/statistics/object/count/record.test +23 -0
- data/test/command/suite/system/statistics/object/count/schema.catalog.json +12 -0
- data/test/command/suite/system/statistics/object/count/schema.expected +11 -0
- data/test/command/suite/system/statistics/object/count/schema.test +13 -0
- data/test/command/suite/system/status.expected +3 -2
- data/test/unit/catalog/test_dataset.rb +4 -1
- data/test/unit/{test_catalog_generator.rb → catalog/test_generator.rb} +2 -2
- data/test/unit/catalog/test_replicas_volume.rb +79 -0
- data/test/unit/catalog/test_single_volume.rb +2 -2
- data/test/unit/catalog/test_slice.rb +33 -1
- data/test/unit/catalog/{test_collection_volume.rb → test_slices_volume.rb} +72 -11
- data/test/unit/catalog/test_version2.rb +3 -0
- data/test/unit/helper/distributed_search_planner_helper.rb +2 -2
- data/test/unit/plugins/catalog/test_fetch.rb +4 -4
- data/test/unit/plugins/crud/test_add.rb +44 -4
- data/test/unit/plugins/groonga/test_column_create.rb +4 -4
- data/test/unit/plugins/groonga/test_column_list.rb +4 -4
- data/test/unit/plugins/groonga/test_column_remove.rb +4 -4
- data/test/unit/plugins/groonga/test_column_rename.rb +4 -4
- data/test/unit/plugins/groonga/test_delete.rb +73 -10
- data/test/unit/plugins/groonga/test_table_create.rb +4 -4
- data/test/unit/plugins/groonga/test_table_list.rb +4 -4
- data/test/unit/plugins/groonga/test_table_remove.rb +4 -4
- data/test/unit/plugins/search/test_handler.rb +4 -4
- data/test/unit/plugins/search/test_planner.rb +4 -2
- data/test/unit/plugins/system/test_status.rb +31 -15
- data/test/unit/plugins/test_watch.rb +16 -16
- data/test/unit/test_address.rb +4 -4
- metadata +134 -35
- data/lib/droonga/catalog/volume_collection.rb +0 -79
- data/lib/droonga/catalog_fetcher.rb +0 -53
- data/lib/droonga/catalog_generator.rb +0 -243
- data/lib/droonga/catalog_loader.rb +0 -56
- data/lib/droonga/command/remote.rb +0 -404
- data/lib/droonga/data_absorber.rb +0 -264
- data/lib/droonga/node_status.rb +0 -71
- data/lib/droonga/serf_downloader.rb +0 -115
- data/test/unit/catalog/test_volume_collection.rb +0 -78
|
@@ -1,79 +0,0 @@
|
|
|
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
|
-
module Droonga
|
|
17
|
-
module Catalog
|
|
18
|
-
class VolumeCollection
|
|
19
|
-
include Enumerable
|
|
20
|
-
|
|
21
|
-
def initialize(volumes)
|
|
22
|
-
@volumes = volumes
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def each(&block)
|
|
26
|
-
@volumes.each(&block)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def ==(other)
|
|
30
|
-
other.is_a?(self.class) and
|
|
31
|
-
to_a == other.to_a
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def eql?(other)
|
|
35
|
-
self == other
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def hash
|
|
39
|
-
to_a.hash
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def select(how=nil, live_nodes=nil)
|
|
43
|
-
volumes = live_volumes(live_nodes)
|
|
44
|
-
case how
|
|
45
|
-
when :top
|
|
46
|
-
[volumes.first]
|
|
47
|
-
when :random
|
|
48
|
-
[volumes.sample]
|
|
49
|
-
when :all
|
|
50
|
-
@volumes
|
|
51
|
-
else
|
|
52
|
-
super
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def all_nodes
|
|
57
|
-
@all_nodes ||= collect_all_nodes
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def live_volumes(live_nodes=nil)
|
|
61
|
-
return @volumes unless live_nodes
|
|
62
|
-
|
|
63
|
-
@volumes.select do |volume|
|
|
64
|
-
dead_nodes = volume.all_nodes - live_nodes
|
|
65
|
-
dead_nodes.empty?
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
private
|
|
70
|
-
def collect_all_nodes
|
|
71
|
-
nodes = []
|
|
72
|
-
@volumes.each do |volume|
|
|
73
|
-
nodes += volume.all_nodes
|
|
74
|
-
end
|
|
75
|
-
nodes.sort.uniq
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
@@ -1,53 +0,0 @@
|
|
|
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 "socket"
|
|
17
|
-
|
|
18
|
-
require "droonga/client"
|
|
19
|
-
|
|
20
|
-
require "droonga/address"
|
|
21
|
-
require "droonga/catalog/dataset"
|
|
22
|
-
|
|
23
|
-
module Droonga
|
|
24
|
-
class CatalogFetcher
|
|
25
|
-
def initialize(client_options)
|
|
26
|
-
@client_options = default_options.merge(client_options)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def fetch(options={})
|
|
30
|
-
message = {
|
|
31
|
-
"dataset" => options[:dataset] || Catalog::Dataset::DEFAULT_NAME,
|
|
32
|
-
"type" => "catalog.fetch"
|
|
33
|
-
}
|
|
34
|
-
Droonga::Client.open(@client_options) do |client|
|
|
35
|
-
response = client.request(message)
|
|
36
|
-
response["body"]
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
private
|
|
41
|
-
def default_options
|
|
42
|
-
{
|
|
43
|
-
:host => "127.0.0.1",
|
|
44
|
-
:port => Address::DEFAULT_PORT,
|
|
45
|
-
:tag => Address::DEFAULT_TAG,
|
|
46
|
-
:protocol => :droonga,
|
|
47
|
-
:timeout => 1,
|
|
48
|
-
:receiver_host => Socket.gethostname,
|
|
49
|
-
:receiver_port => 0,
|
|
50
|
-
}
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,243 +0,0 @@
|
|
|
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 "time"
|
|
17
|
-
|
|
18
|
-
require "droonga/address"
|
|
19
|
-
require "droonga/catalog/dataset"
|
|
20
|
-
|
|
21
|
-
module Droonga
|
|
22
|
-
class CatalogGenerator
|
|
23
|
-
DEFAULT_DATASET = Catalog::Dataset::DEFAULT_NAME
|
|
24
|
-
DEFAULT_HOSTS = [Address::DEFAULT_HOST]
|
|
25
|
-
DEFAULT_N_WORKERS = 4
|
|
26
|
-
DEFAULT_N_SLICES = 1
|
|
27
|
-
DEFAULT_PLUGINS = ["groonga", "search", "crud", "dump", "system", "catalog"]
|
|
28
|
-
DEFAULT_PORT = Address::DEFAULT_PORT
|
|
29
|
-
DEFAULT_TAG = Address::DEFAULT_TAG
|
|
30
|
-
|
|
31
|
-
attr_reader :datasets
|
|
32
|
-
|
|
33
|
-
class << self
|
|
34
|
-
def generate(datasets_params)
|
|
35
|
-
generator = new
|
|
36
|
-
datasets_params.each do |name, params|
|
|
37
|
-
generator.add_dataset(name, params)
|
|
38
|
-
end
|
|
39
|
-
generator.generate
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def initialize
|
|
44
|
-
@version = 2
|
|
45
|
-
@effective_date = Time.now
|
|
46
|
-
@datasets = {}
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def add_dataset(name, options)
|
|
50
|
-
@datasets[name] = Dataset.new(name, options)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def generate
|
|
54
|
-
{
|
|
55
|
-
"version" => @version,
|
|
56
|
-
"effectiveDate" => @effective_date.iso8601,
|
|
57
|
-
"datasets" => catalog_datasets,
|
|
58
|
-
}
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def load(catalog)
|
|
62
|
-
catalog["datasets"].each do |name, catalog_dataset|
|
|
63
|
-
load_dataset(name, catalog_dataset)
|
|
64
|
-
end
|
|
65
|
-
self
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def dataset_for_host(host)
|
|
69
|
-
@datasets.each do |name, dataset|
|
|
70
|
-
if dataset.replicas.hosts.include?(host)
|
|
71
|
-
return dataset
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
nil
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def modify(dataset_modifications)
|
|
78
|
-
dataset_modifications.each do |name, modification|
|
|
79
|
-
dataset = @datasets[name]
|
|
80
|
-
next unless dataset
|
|
81
|
-
|
|
82
|
-
replicas = dataset.replicas
|
|
83
|
-
|
|
84
|
-
if modification[:replica_hosts]
|
|
85
|
-
replicas.hosts = modification[:replica_hosts]
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
if modification[:add_replica_hosts]
|
|
89
|
-
replicas.hosts += modification[:add_replica_hosts]
|
|
90
|
-
replicas.hosts.uniq!
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
if modification[:remove_replica_hosts]
|
|
94
|
-
replicas.hosts -= modification[:remove_replica_hosts]
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
private
|
|
100
|
-
def catalog_datasets
|
|
101
|
-
catalog_datasets = {}
|
|
102
|
-
@datasets.each do |name, dataset|
|
|
103
|
-
catalog_datasets[name] = dataset.to_catalog
|
|
104
|
-
end
|
|
105
|
-
catalog_datasets
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def load_dataset(name, catalog_dataset)
|
|
109
|
-
options = {}
|
|
110
|
-
options[:n_workers] = catalog_dataset["nWorkers"]
|
|
111
|
-
options[:plugins] = catalog_dataset["plugins"]
|
|
112
|
-
options[:schema] = catalog_dataset["schema"]
|
|
113
|
-
options[:fact] = catalog_dataset["fact"]
|
|
114
|
-
options[:replicas] = catalog_dataset["replicas"]
|
|
115
|
-
add_dataset(name, options)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
class Dataset
|
|
119
|
-
attr_reader :name
|
|
120
|
-
|
|
121
|
-
def initialize(name, options)
|
|
122
|
-
@name = name
|
|
123
|
-
@options = options
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def n_workers
|
|
127
|
-
@options[:n_workers] || DEFAULT_N_WORKERS
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def plugins
|
|
131
|
-
@options[:plugins] || DEFAULT_PLUGINS
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def schema
|
|
135
|
-
@options[:schema] || {}
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def fact
|
|
139
|
-
@options[:fact]
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def replicas
|
|
143
|
-
@replicas ||= create_replicas
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def to_catalog
|
|
147
|
-
catalog = {
|
|
148
|
-
"nWorkers" => n_workers,
|
|
149
|
-
"plugins" => plugins,
|
|
150
|
-
"schema" => schema,
|
|
151
|
-
"replicas" => replicas.to_catalog,
|
|
152
|
-
}
|
|
153
|
-
catalog["fact"] = fact if fact
|
|
154
|
-
catalog
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
private
|
|
158
|
-
def create_replicas
|
|
159
|
-
catalog_replicas = @options[:replicas]
|
|
160
|
-
if catalog_replicas
|
|
161
|
-
replicas = Replicas.new
|
|
162
|
-
replicas.load(catalog_replicas)
|
|
163
|
-
replicas
|
|
164
|
-
else
|
|
165
|
-
Replicas.new(@options)
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
class Replicas
|
|
171
|
-
attr_accessor :hosts
|
|
172
|
-
attr_reader :port, :tag, :n_slices
|
|
173
|
-
|
|
174
|
-
def initialize(options={})
|
|
175
|
-
@hosts = options[:hosts] || DEFAULT_HOSTS
|
|
176
|
-
@port = options[:port]
|
|
177
|
-
@tag = options[:tag]
|
|
178
|
-
@n_slices = options[:n_slices]
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def load(catalog_replicas)
|
|
182
|
-
dataset = Catalog::Dataset.new("temporary",
|
|
183
|
-
"replicas" => catalog_replicas)
|
|
184
|
-
@hosts = dataset.replicas.collect do |replica|
|
|
185
|
-
replica.slices.first.volume.address.host
|
|
186
|
-
end
|
|
187
|
-
collection_volume = dataset.replicas.first
|
|
188
|
-
slices = collection_volume.slices
|
|
189
|
-
@n_slices = slices.size
|
|
190
|
-
single_volume_address = slices.first.volume.address
|
|
191
|
-
@port = single_volume_address.port
|
|
192
|
-
@tag = single_volume_address.tag
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def to_catalog
|
|
196
|
-
catalog_replicas = []
|
|
197
|
-
@hosts.each do |host|
|
|
198
|
-
replica = Replica.new(host, :port => @port,
|
|
199
|
-
:tag => @tag,
|
|
200
|
-
:n_slices => @n_slices)
|
|
201
|
-
catalog_replicas << replica.to_catalog
|
|
202
|
-
end
|
|
203
|
-
catalog_replicas
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
class Replica
|
|
208
|
-
def initialize(host, options={})
|
|
209
|
-
@host = host
|
|
210
|
-
@port = options[:port] || DEFAULT_PORT
|
|
211
|
-
@tag = options[:tag] || DEFAULT_TAG
|
|
212
|
-
@n_slices = options[:n_slices] || DEFAULT_N_SLICES
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def to_catalog
|
|
216
|
-
slices = []
|
|
217
|
-
@n_slices.times do |i|
|
|
218
|
-
slices << catalog_slice(i)
|
|
219
|
-
end
|
|
220
|
-
{
|
|
221
|
-
"dimension" => "_key",
|
|
222
|
-
"slicer" => "hash",
|
|
223
|
-
"slices" => slices,
|
|
224
|
-
}
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
private
|
|
228
|
-
def catalog_slice(nth_slice)
|
|
229
|
-
name = "%03d" % nth_slice
|
|
230
|
-
{
|
|
231
|
-
"weight" => weight,
|
|
232
|
-
"volume" => {
|
|
233
|
-
"address" => "#{@host}:#{@port}/#{@tag}.#{name}",
|
|
234
|
-
},
|
|
235
|
-
}
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def weight
|
|
239
|
-
@weight ||= 100 / @n_slices
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Copyright (C) 2013-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/catalog/version1"
|
|
19
|
-
require "droonga/catalog/version2"
|
|
20
|
-
|
|
21
|
-
module Droonga
|
|
22
|
-
class CatalogLoader
|
|
23
|
-
def initialize(path)
|
|
24
|
-
@path = path
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def load
|
|
28
|
-
data = nil
|
|
29
|
-
begin
|
|
30
|
-
data = File.open(@path) do |file|
|
|
31
|
-
JSON.parse(file.read)
|
|
32
|
-
end
|
|
33
|
-
rescue Errno::ENOENT => error
|
|
34
|
-
raise Error.new("Missing catalog file #{@path}")
|
|
35
|
-
rescue JSON::ParserError => error
|
|
36
|
-
raise Error.new("Syntax error in #{@path}:\n#{error.to_s}")
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
unless data.is_a?(Hash)
|
|
40
|
-
raise Error.new("Root element of catalog must be an object in #{@path}")
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
version = data["version"]
|
|
44
|
-
case version
|
|
45
|
-
when 1
|
|
46
|
-
Catalog::Version1.new(data, @path)
|
|
47
|
-
when 2
|
|
48
|
-
Catalog::Version2.new(data, @path)
|
|
49
|
-
when nil
|
|
50
|
-
raise Error.new("Catalog version must be specified in #{@path}")
|
|
51
|
-
else
|
|
52
|
-
raise Error.new("Unsupported catalog version <#{version}> is specified in #{@path}")
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,404 +0,0 @@
|
|
|
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/serf"
|
|
20
|
-
require "droonga/node_status"
|
|
21
|
-
require "droonga/catalog_generator"
|
|
22
|
-
require "droonga/catalog_modifier"
|
|
23
|
-
require "droonga/catalog_fetcher"
|
|
24
|
-
require "droonga/data_absorber"
|
|
25
|
-
require "droonga/safe_file_writer"
|
|
26
|
-
require "droonga/service_installation"
|
|
27
|
-
|
|
28
|
-
module Droonga
|
|
29
|
-
module Command
|
|
30
|
-
module Remote
|
|
31
|
-
class Base
|
|
32
|
-
attr_reader :response
|
|
33
|
-
|
|
34
|
-
def initialize(serf_name, params)
|
|
35
|
-
@serf_name = serf_name
|
|
36
|
-
@params = params
|
|
37
|
-
@response = {
|
|
38
|
-
"log" => []
|
|
39
|
-
}
|
|
40
|
-
@serf = Serf.new(nil, @serf_name)
|
|
41
|
-
|
|
42
|
-
@service_installation = ServiceInstallation.new
|
|
43
|
-
@service_installation.ensure_using_service_base_directory
|
|
44
|
-
|
|
45
|
-
log("params = #{params}")
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def process
|
|
49
|
-
# override me!
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def should_process?
|
|
53
|
-
for_me? or @params.nil? or not @params.include?("node")
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
private
|
|
57
|
-
def node
|
|
58
|
-
@serf_name
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def host
|
|
62
|
-
node.split(":").first
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def target_node
|
|
66
|
-
@params && @params["node"]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def for_me?
|
|
70
|
-
target_node == @serf_name
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def log(message)
|
|
74
|
-
@response["log"] << message
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
class ChangeRole < Base
|
|
79
|
-
def process
|
|
80
|
-
status = NodeStatus.new
|
|
81
|
-
status.set(:role, @params["role"])
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
class ReportStatus < Base
|
|
86
|
-
def process
|
|
87
|
-
status = NodeStatus.new
|
|
88
|
-
@response["value"] = status.get(@params["key"])
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
class SetStatus < Base
|
|
93
|
-
def process
|
|
94
|
-
status = NodeStatus.new
|
|
95
|
-
status.set(@params["key"], @params["value"])
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
class Join < Base
|
|
100
|
-
def process
|
|
101
|
-
log("type = #{type}")
|
|
102
|
-
case type
|
|
103
|
-
when "replica"
|
|
104
|
-
join_as_replica
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
private
|
|
109
|
-
def type
|
|
110
|
-
@params["type"]
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def source_node
|
|
114
|
-
@params["source"]
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def joining_node
|
|
118
|
-
@params["node"]
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def dataset_name
|
|
122
|
-
@params["dataset"]
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def messages_per_second
|
|
126
|
-
@params["messages_per_second"]
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def valid_params?
|
|
130
|
-
have_required_params? and
|
|
131
|
-
valid_node?(source_node) and
|
|
132
|
-
valid_node?(joining_node)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def have_required_params?
|
|
136
|
-
required_params = [
|
|
137
|
-
source_node,
|
|
138
|
-
joining_node,
|
|
139
|
-
dataset_name,
|
|
140
|
-
]
|
|
141
|
-
required_params.all? do |param|
|
|
142
|
-
not param.nil?
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
NODE_PATTERN = /\A([^:]+):(\d+)\/(.+)\z/
|
|
147
|
-
|
|
148
|
-
def valid_node?(node)
|
|
149
|
-
node =~ NODE_PATTERN
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def source_host
|
|
153
|
-
@source_host ||= (source_node =~ NODE_PATTERN && $1)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def joining_host
|
|
157
|
-
@joining_host ||= (joining_node =~ NODE_PATTERN && $1)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def port
|
|
161
|
-
@port ||= (source_node =~ NODE_PATTERN && $2 && $2.to_i)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def tag
|
|
165
|
-
@tag ||= (source_node =~ NODE_PATTERN && $3)
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def should_absorb_data?
|
|
169
|
-
@params["copy"]
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def join_as_replica
|
|
173
|
-
return unless valid_params?
|
|
174
|
-
|
|
175
|
-
log("source_node = #{source_node}")
|
|
176
|
-
|
|
177
|
-
@catalog = fetch_catalog
|
|
178
|
-
|
|
179
|
-
other_hosts = replica_hosts
|
|
180
|
-
log("other_hosts = #{other_hosts}")
|
|
181
|
-
return if other_hosts.empty?
|
|
182
|
-
|
|
183
|
-
# restart self with the fetched catalog.
|
|
184
|
-
SafeFileWriter.write(Path.catalog) do |output, file|
|
|
185
|
-
output.puts(JSON.pretty_generate(@catalog))
|
|
186
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
absorb_data if should_absorb_data?
|
|
190
|
-
|
|
191
|
-
log("joining to the cluster: update myself")
|
|
192
|
-
|
|
193
|
-
CatalogModifier.modify do |modifier, file|
|
|
194
|
-
modifier.datasets[dataset_name].replicas.hosts += other_hosts
|
|
195
|
-
modifier.datasets[dataset_name].replicas.hosts.uniq!
|
|
196
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
@serf.join(*other_hosts)
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def replica_hosts
|
|
203
|
-
generator = CatalogGenerator.new
|
|
204
|
-
generator.load(@catalog)
|
|
205
|
-
dataset = generator.dataset_for_host(source_host) ||
|
|
206
|
-
generator.dataset_for_host(host)
|
|
207
|
-
return [] unless dataset
|
|
208
|
-
dataset.replicas.hosts
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
def fetch_catalog
|
|
212
|
-
fetcher = CatalogFetcher.new(:host => source_host,
|
|
213
|
-
:port => port,
|
|
214
|
-
:tag => tag,
|
|
215
|
-
:receiver_host => host)
|
|
216
|
-
fetcher.fetch(:dataset => dataset_name)
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
def absorb_data
|
|
220
|
-
log("starting to copy data from #{source_host}")
|
|
221
|
-
|
|
222
|
-
CatalogModifier.modify do |modifier, file|
|
|
223
|
-
modifier.datasets[dataset_name].replicas.hosts = [host]
|
|
224
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
225
|
-
end
|
|
226
|
-
sleep(5) #TODO: wait for restart. this should be done more safely, to avoid starting of absorbing with old catalog.json.
|
|
227
|
-
|
|
228
|
-
status = NodeStatus.new
|
|
229
|
-
status.set(:absorbing, true)
|
|
230
|
-
DataAbsorber.absorb(:dataset => dataset_name,
|
|
231
|
-
:source_host => source_host,
|
|
232
|
-
:destination_host => joining_host,
|
|
233
|
-
:port => port,
|
|
234
|
-
:tag => tag,
|
|
235
|
-
:messages_per_second => messages_per_second)
|
|
236
|
-
status.delete(:absorbing)
|
|
237
|
-
sleep(1)
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
class AbsorbData < Base
|
|
242
|
-
attr_writer :dataset_name, :port, :tag
|
|
243
|
-
|
|
244
|
-
def process
|
|
245
|
-
return unless source
|
|
246
|
-
|
|
247
|
-
log("start to absorb data from #{source}")
|
|
248
|
-
|
|
249
|
-
if dataset_name.nil? or port.nil? or tag.nil?
|
|
250
|
-
current_catalog = JSON.parse(Path.catalog.read)
|
|
251
|
-
generator = CatalogGenerator.new
|
|
252
|
-
generator.load(current_catalog)
|
|
253
|
-
|
|
254
|
-
dataset = generator.dataset_for_host(source)
|
|
255
|
-
return unless dataset
|
|
256
|
-
|
|
257
|
-
self.dataset_name = dataset.name
|
|
258
|
-
self.port = dataset.replicas.port
|
|
259
|
-
self.tag = dataset.replicas.tag
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
log("dataset = #{dataset_name}")
|
|
263
|
-
log("port = #{port}")
|
|
264
|
-
log("tag = #{tag}")
|
|
265
|
-
|
|
266
|
-
status = NodeStatus.new
|
|
267
|
-
status.set(:absorbing, true)
|
|
268
|
-
DataAbsorber.absorb(:dataset => dataset_name,
|
|
269
|
-
:source_host => source,
|
|
270
|
-
:destination_host => host,
|
|
271
|
-
:port => port,
|
|
272
|
-
:tag => tag,
|
|
273
|
-
:messages_per_second => messages_per_second,
|
|
274
|
-
:client => "droonga-send")
|
|
275
|
-
status.delete(:absorbing)
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
private
|
|
279
|
-
def source
|
|
280
|
-
@params["source"]
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
def dataset_name
|
|
284
|
-
@dataset_name ||= @params["dataset"]
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
def port
|
|
288
|
-
@port ||= @params["port"]
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def tag
|
|
292
|
-
@tag ||= @params["tag"]
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def messages_per_second
|
|
296
|
-
@messages_per_second ||= @params["messages_per_second"]
|
|
297
|
-
end
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
class ModifyReplicasBase < Base
|
|
301
|
-
private
|
|
302
|
-
def dataset
|
|
303
|
-
@params["dataset"]
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
def hosts
|
|
307
|
-
@hosts ||= prepare_hosts
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
def prepare_hosts
|
|
311
|
-
hosts = @params["hosts"]
|
|
312
|
-
return nil unless hosts
|
|
313
|
-
hosts = [hosts] if hosts.is_a?(String)
|
|
314
|
-
hosts
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
class SetReplicas < ModifyReplicasBase
|
|
319
|
-
def process
|
|
320
|
-
return if dataset.nil? or hosts.nil?
|
|
321
|
-
|
|
322
|
-
log("new replicas: #{hosts.join(",")}")
|
|
323
|
-
|
|
324
|
-
CatalogModifier.modify do |modifier, file|
|
|
325
|
-
modifier.datasets[dataset].replicas.hosts = hosts
|
|
326
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
@serf.join(*hosts)
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
class AddReplicas < ModifyReplicasBase
|
|
334
|
-
def process
|
|
335
|
-
return if dataset.nil? or hosts.nil?
|
|
336
|
-
|
|
337
|
-
added_hosts = hosts - [host]
|
|
338
|
-
log("adding replicas: #{added_hosts.join(",")}")
|
|
339
|
-
return if added_hosts.empty?
|
|
340
|
-
|
|
341
|
-
CatalogModifier.modify do |modifier, file|
|
|
342
|
-
modifier.datasets[dataset].replicas.hosts += added_hosts
|
|
343
|
-
modifier.datasets[dataset].replicas.hosts.uniq!
|
|
344
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
@serf.join(*added_hosts)
|
|
348
|
-
end
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
class RemoveReplicas < ModifyReplicasBase
|
|
352
|
-
def process
|
|
353
|
-
return if dataset.nil? or hosts.nil?
|
|
354
|
-
|
|
355
|
-
log("removing replicas: #{hosts.join(",")}")
|
|
356
|
-
|
|
357
|
-
CatalogModifier.modify do |modifier, file|
|
|
358
|
-
modifier.datasets[dataset].replicas.hosts -= hosts
|
|
359
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
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(",")}")
|
|
369
|
-
|
|
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)
|
|
383
|
-
end
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
class UpdateLiveNodes < Base
|
|
387
|
-
def process
|
|
388
|
-
path = Path.live_nodes
|
|
389
|
-
nodes = live_nodes
|
|
390
|
-
file_contents = JSON.pretty_generate(nodes)
|
|
391
|
-
SafeFileWriter.write(path) do |output, file|
|
|
392
|
-
output.puts(file_contents)
|
|
393
|
-
@service_installation.ensure_correct_file_permission(file)
|
|
394
|
-
end
|
|
395
|
-
end
|
|
396
|
-
|
|
397
|
-
private
|
|
398
|
-
def live_nodes
|
|
399
|
-
@serf.live_nodes
|
|
400
|
-
end
|
|
401
|
-
end
|
|
402
|
-
end
|
|
403
|
-
end
|
|
404
|
-
end
|