droonga-engine 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -0
- data/bin/droonga-engine-absorb-data +82 -0
- data/bin/droonga-engine-catalog-generate +16 -13
- data/bin/droonga-engine-catalog-modify +108 -0
- data/bin/droonga-engine-join +115 -0
- data/bin/droonga-engine-unjoin +90 -0
- data/doc/text/news.md +8 -0
- data/droonga-engine.gemspec +2 -1
- data/lib/droonga/buffered_tcp_socket.rb +132 -0
- data/lib/droonga/catalog_generator.rb +87 -4
- data/lib/droonga/command/droonga_engine.rb +27 -7
- data/lib/droonga/command/droonga_engine_service.rb +3 -2
- data/lib/droonga/command/serf_event_handler.rb +211 -14
- data/lib/droonga/data_absorber.rb +55 -0
- data/lib/droonga/dispatcher.rb +25 -11
- data/lib/droonga/engine/version.rb +1 -1
- data/lib/droonga/engine.rb +24 -24
- data/lib/droonga/engine_state.rb +23 -0
- data/lib/droonga/{catalog_observer.rb → file_observer.rb} +12 -7
- data/lib/droonga/fluent_message_sender.rb +24 -37
- data/lib/droonga/forwarder.rb +30 -5
- data/lib/droonga/handler_messenger.rb +3 -2
- data/lib/droonga/handler_runner.rb +29 -16
- data/lib/droonga/job_pusher.rb +12 -0
- data/lib/droonga/line_buffer.rb +42 -0
- data/lib/droonga/logger.rb +10 -6
- data/lib/droonga/path.rb +16 -0
- data/lib/droonga/plugins/search/distributed_search_planner.rb +1 -1
- data/lib/droonga/plugins/system.rb +50 -0
- data/lib/droonga/processor.rb +9 -4
- data/lib/droonga/safe_file_writer.rb +39 -0
- data/lib/droonga/serf.rb +212 -14
- data/lib/droonga/test/stub_handler_messenger.rb +3 -0
- data/lib/droonga/worker.rb +6 -1
- data/test/command/config/default/catalog.json +1 -1
- data/test/command/config/version1/catalog.json +2 -2
- data/test/command/suite/system/status.expected +12 -0
- data/test/command/suite/system/status.test +5 -0
- data/test/unit/plugins/system/test_status.rb +79 -0
- data/test/unit/test_catalog_generator.rb +1 -1
- data/test/unit/test_line_buffer.rb +62 -0
- metadata +46 -12
- data/lib/droonga/live_nodes_list_observer.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 333168fcdecd92b88dfc590746445e0ed31319c4
|
4
|
+
data.tar.gz: bb082dd818cfd171a131e0e45dc75269a1cd814d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38167299101e872c86cb07ac35449f023028ffaaa405477423c7882fd981c90677f4483671ea3c326e71338274326acbbfab644f668c77b7602d932b3c19717e
|
7
|
+
data.tar.gz: 41fe28134710faf85c694abe7c702e120d33188f321611e8627788b80ceabc5cca295f7d590621a85d1a87b936746a7d90e63cfeb938eb932287110c5548cfe1
|
data/Gemfile
CHANGED
@@ -71,3 +71,10 @@ if File.exist?(grn2drn_dir)
|
|
71
71
|
else
|
72
72
|
gem "grn2drn", :github => "droonga/grn2drn"
|
73
73
|
end
|
74
|
+
|
75
|
+
drndump_dir = File.join(parent_dir, "drndump")
|
76
|
+
if File.exist?(drndump_dir)
|
77
|
+
gem "drndump", :path => drndump_dir
|
78
|
+
else
|
79
|
+
gem "drndump", :github => "droonga/drndump"
|
80
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
require "ostruct"
|
19
|
+
require "optparse"
|
20
|
+
require "open3"
|
21
|
+
|
22
|
+
require "droonga/engine/version"
|
23
|
+
require "droonga/catalog_generator"
|
24
|
+
require "droonga/serf"
|
25
|
+
|
26
|
+
options = OpenStruct.new
|
27
|
+
options.port = Droonga::CatalogGenerator::DEFAULT_PORT
|
28
|
+
options.tag = Droonga::CatalogGenerator::DEFAULT_TAG
|
29
|
+
options.dataset = Droonga::CatalogGenerator::DEFAULT_DATASET
|
30
|
+
parser = OptionParser.new
|
31
|
+
parser.version = Droonga::Engine::VERSION
|
32
|
+
|
33
|
+
parser.separator("")
|
34
|
+
parser.separator("Connection:")
|
35
|
+
parser.on("--source-host=HOST",
|
36
|
+
"Host name of the source cluster to be connected.") do |host|
|
37
|
+
options.source_host = host
|
38
|
+
end
|
39
|
+
parser.on("--destination-host=HOST",
|
40
|
+
"Host name of this cluster to be connected.") do |host|
|
41
|
+
options.destination_host = host
|
42
|
+
end
|
43
|
+
parser.on("--port=PORT", Integer,
|
44
|
+
"Port number of the source cluster to be connected.",
|
45
|
+
"(#{options.port})") do |port|
|
46
|
+
options.port = port
|
47
|
+
end
|
48
|
+
|
49
|
+
parser.separator("")
|
50
|
+
parser.separator("Data:")
|
51
|
+
parser.on("--tag=TAG",
|
52
|
+
"Tag name to be used to communicate with Droonga system.",
|
53
|
+
"(#{options.tag})") do |tag|
|
54
|
+
options.tag = tag
|
55
|
+
end
|
56
|
+
parser.on("--dataset=DATASET",
|
57
|
+
"Dataset to be absorbed.",
|
58
|
+
"(#{options.dataset})") do |dataset|
|
59
|
+
options.dataset = dataset
|
60
|
+
end
|
61
|
+
|
62
|
+
parser.parse!(ARGV)
|
63
|
+
|
64
|
+
unless options.source_host
|
65
|
+
raise "You must specify the source host via --source-host option."
|
66
|
+
end
|
67
|
+
unless options.destination_host
|
68
|
+
raise "You must specify the destination host via --destination-host option."
|
69
|
+
end
|
70
|
+
|
71
|
+
destination_node = "#{options.destination_host}:#{options.port}/#{options.tag}"
|
72
|
+
|
73
|
+
puts "Absorbing data..."
|
74
|
+
Droonga::Serf.send_query(destination_node, "absorb_data",
|
75
|
+
"node" => destination_node,
|
76
|
+
"source" => options.source_host,
|
77
|
+
"port" => options.port,
|
78
|
+
"tag" => options.tag,
|
79
|
+
"dataset" => options.dataset)
|
80
|
+
puts "Done."
|
81
|
+
|
82
|
+
exit(true)
|
@@ -18,11 +18,11 @@
|
|
18
18
|
require "ostruct"
|
19
19
|
require "optparse"
|
20
20
|
require "json"
|
21
|
-
require "tempfile"
|
22
21
|
require "pathname"
|
23
22
|
|
24
23
|
require "droonga/engine/version"
|
25
24
|
require "droonga/catalog_generator"
|
25
|
+
require "droonga/safe_file_writer"
|
26
26
|
|
27
27
|
generator = Droonga::CatalogGenerator.new
|
28
28
|
current_dataset = {}
|
@@ -42,31 +42,38 @@ parser.on("--output=PATH",
|
|
42
42
|
end
|
43
43
|
parser.on("--dataset=NAME",
|
44
44
|
"Add a dataset its name is NAME.",
|
45
|
-
"And set the NAME to the current dataset."
|
45
|
+
"And set the NAME to the current dataset.",
|
46
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_DATASET})") do |name|
|
46
47
|
current_dataset = datasets[name] = {}
|
47
48
|
end
|
48
49
|
parser.on("--n-workers=N", Integer,
|
49
|
-
"Use N workers for the current dataset."
|
50
|
+
"Use N workers for the current dataset.",
|
51
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_N_WORKERS})") do |n|
|
50
52
|
current_dataset[:n_workers] = n
|
51
53
|
end
|
52
54
|
parser.on("--hosts=NAME1,NAME2,...", Array,
|
53
|
-
"Use given hosts for replicas of the current dataset."
|
55
|
+
"Use given hosts for replicas of the current dataset.",
|
56
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_HOSTS.join(",")})") do |hosts|
|
54
57
|
current_dataset[:hosts] = hosts
|
55
58
|
end
|
56
59
|
parser.on("--port=PORT", Integer,
|
57
|
-
"Use the PORT as the port for the current dataset."
|
60
|
+
"Use the PORT as the port for the current dataset.",
|
61
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_PORT})") do |port|
|
58
62
|
current_dataset[:port] = port
|
59
63
|
end
|
60
64
|
parser.on("--tag=TAG",
|
61
|
-
"Use the TAG as the tag for the current dataset."
|
65
|
+
"Use the TAG as the tag for the current dataset.",
|
66
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_TAG})") do |tag|
|
62
67
|
current_dataset[:tag] = tag
|
63
68
|
end
|
64
69
|
parser.on("--n-slices=N", Integer,
|
65
|
-
"Use N slices for each replica."
|
70
|
+
"Use N slices for each replica.",
|
71
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_N_SLICES})") do |n|
|
66
72
|
current_dataset[:n_slices] = n
|
67
73
|
end
|
68
74
|
parser.on("--plugins=PLUGIN1,PLUGIN2,...", Array,
|
69
|
-
"Use PLUGINS for the current dataset."
|
75
|
+
"Use PLUGINS for the current dataset.",
|
76
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_PLUGINS.join(",")})") do |plugins|
|
70
77
|
current_dataset[:plugins] = plugins
|
71
78
|
end
|
72
79
|
parser.on("--schema=PATH",
|
@@ -99,12 +106,8 @@ def open_output(path)
|
|
99
106
|
if path == "-"
|
100
107
|
yield($stdout)
|
101
108
|
else
|
102
|
-
|
103
|
-
path = Pathname(path).expand_path
|
104
|
-
Tempfile.open(path.basename.to_s, path.parent.to_s, "w") do |output|
|
109
|
+
Droonga::SafeFileWriter.write(path) do |output|
|
105
110
|
yield(output)
|
106
|
-
output.flush
|
107
|
-
File.rename(output.path, path.to_s)
|
108
111
|
end
|
109
112
|
end
|
110
113
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
require "ostruct"
|
19
|
+
require "optparse"
|
20
|
+
require "json"
|
21
|
+
require "pathname"
|
22
|
+
|
23
|
+
require "droonga/engine/version"
|
24
|
+
require "droonga/catalog_generator"
|
25
|
+
require "droonga/safe_file_writer"
|
26
|
+
|
27
|
+
generator = Droonga::CatalogGenerator.new
|
28
|
+
current_dataset = {}
|
29
|
+
datasets = {
|
30
|
+
Droonga::CatalogGenerator::DEFAULT_DATASET => current_dataset
|
31
|
+
}
|
32
|
+
|
33
|
+
options = OpenStruct.new
|
34
|
+
options.source_path = "./catalog.json"
|
35
|
+
options.output_path = "-"
|
36
|
+
options.update = false
|
37
|
+
parser = OptionParser.new
|
38
|
+
parser.version = Droonga::Engine::VERSION
|
39
|
+
parser.on("--source=PATH",
|
40
|
+
"Path to an existing catalog.json.",
|
41
|
+
"\"-\" means the standard input.",
|
42
|
+
"(#{options.source_path})") do |path|
|
43
|
+
options.source_path = path
|
44
|
+
end
|
45
|
+
parser.on("--output=PATH",
|
46
|
+
"Output catalog.json to PATH.",
|
47
|
+
"\"-\" means the standard output.",
|
48
|
+
"(#{options.output_path})") do |path|
|
49
|
+
options.output_path = path
|
50
|
+
end
|
51
|
+
parser.on("--[no-]update",
|
52
|
+
"Update the source file itself, or not.",
|
53
|
+
"(#{options.update})") do |update|
|
54
|
+
options.update = update
|
55
|
+
end
|
56
|
+
parser.on("--dataset=NAME",
|
57
|
+
"Add a dataset its name is NAME.",
|
58
|
+
"And set the NAME to the current dataset.",
|
59
|
+
"(#{Droonga::CatalogGenerator::DEFAULT_DATASET})") do |name|
|
60
|
+
current_dataset = datasets[name] = {}
|
61
|
+
end
|
62
|
+
parser.on("--replica-hosts=NAME1,NAME2,...", Array,
|
63
|
+
"Use given hosts as replicas for the current dataset.") do |hosts|
|
64
|
+
current_dataset[:replica_hosts] = hosts
|
65
|
+
end
|
66
|
+
parser.on("--add-replica-hosts=NAME1,NAME2,...", Array,
|
67
|
+
"Use given hosts to be added as replicas to the current dataset.") do |hosts|
|
68
|
+
current_dataset[:add_replica_hosts] = hosts
|
69
|
+
end
|
70
|
+
parser.on("--remove-replica-hosts=NAME1,NAME2,...", Array,
|
71
|
+
"Use given hosts to be removed as replicas from the current dataset.") do |hosts|
|
72
|
+
current_dataset[:remove_replica_hosts] = hosts
|
73
|
+
end
|
74
|
+
parser.parse!(ARGV)
|
75
|
+
|
76
|
+
if options.source_path != "-" and options.update
|
77
|
+
options.output_path = options.source_path
|
78
|
+
end
|
79
|
+
|
80
|
+
def load_source(path)
|
81
|
+
source = nil
|
82
|
+
if path == "-"
|
83
|
+
source = $stdin.read
|
84
|
+
else
|
85
|
+
source_path = Pathname(path).expand_path
|
86
|
+
source = source_path.read
|
87
|
+
end
|
88
|
+
JSON.parse(source)
|
89
|
+
end
|
90
|
+
|
91
|
+
source_catalog = load_source(options.source_path)
|
92
|
+
generator.load(source_catalog)
|
93
|
+
generator.modify(datasets)
|
94
|
+
|
95
|
+
def open_output(path)
|
96
|
+
if path == "-"
|
97
|
+
yield($stdout)
|
98
|
+
else
|
99
|
+
Droonga::SafeFileWriter.write(path) do |output|
|
100
|
+
yield(output)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
catalog = generator.generate
|
106
|
+
open_output(options.output_path) do |output|
|
107
|
+
output.puts(JSON.pretty_generate(catalog))
|
108
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
require "ostruct"
|
19
|
+
require "optparse"
|
20
|
+
require "json"
|
21
|
+
require "pathname"
|
22
|
+
|
23
|
+
require "droonga/engine/version"
|
24
|
+
require "droonga/path"
|
25
|
+
require "droonga/catalog_generator"
|
26
|
+
require "droonga/safe_file_writer"
|
27
|
+
require "droonga/data_absorber"
|
28
|
+
require "droonga/serf"
|
29
|
+
|
30
|
+
options = OpenStruct.new
|
31
|
+
options.base_dir = ENV[Droonga::Path::BASE_DIR_ENV_NAME] || Dir.pwd
|
32
|
+
options.drndump = "drndump"
|
33
|
+
options.client = "droonga-request"
|
34
|
+
options.copy = true
|
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
|
+
|
45
|
+
parser.on("--[no-]copy",
|
46
|
+
"Do or don't copy data from the source cluster.",
|
47
|
+
"(#{options.copy})") do |copy|
|
48
|
+
options.copy = copy
|
49
|
+
end
|
50
|
+
|
51
|
+
parser.separator("")
|
52
|
+
parser.separator("Connections:")
|
53
|
+
parser.on("--host=HOST",
|
54
|
+
"Host name of the node to be joined.") do |host|
|
55
|
+
options.joining_host = host
|
56
|
+
end
|
57
|
+
parser.on("--replica-source-host=HOST",
|
58
|
+
"Host name of the soruce cluster to be connected.") do |host|
|
59
|
+
options.replica_source_host = host
|
60
|
+
end
|
61
|
+
|
62
|
+
parser.parse!(ARGV)
|
63
|
+
|
64
|
+
|
65
|
+
base_dir = Pathname(options.base_dir).expand_path
|
66
|
+
ENV[Droonga::Path::BASE_DIR_ENV_NAME] = base_dir.to_s
|
67
|
+
|
68
|
+
catalog_path = Droonga::Path.catalog
|
69
|
+
unless catalog_path.exist?
|
70
|
+
raise "Cannot load 'catalog.json'. You must specify correct path " +
|
71
|
+
"to the base directory via --base-dir option."
|
72
|
+
end
|
73
|
+
source_catalog = JSON.parse(catalog_path.read)
|
74
|
+
|
75
|
+
|
76
|
+
unless options.joining_host
|
77
|
+
raise "You must specify the host name or the IP address of the node " +
|
78
|
+
"to be joined via --host option."
|
79
|
+
end
|
80
|
+
unless options.replica_source_host
|
81
|
+
raise "You must specify the host name or the IP address of a node " +
|
82
|
+
"of an existing cluster via --replica-source-host option."
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
generator = Droonga::CatalogGenerator.new
|
87
|
+
generator.load(source_catalog)
|
88
|
+
|
89
|
+
dataset = generator.dataset_for_host(options.replica_source_host)
|
90
|
+
unless dataset
|
91
|
+
raise "Specified source host #{options.replica_source_host} is not a " +
|
92
|
+
"member of the cluster. You must specify correct host via " +
|
93
|
+
"--replica-source-host option."
|
94
|
+
end
|
95
|
+
|
96
|
+
if generator.dataset_for_host(options.joining_host)
|
97
|
+
raise "The joining node is already a member of the cluster. " +
|
98
|
+
"You cannot join a member twice."
|
99
|
+
end
|
100
|
+
|
101
|
+
options.tag = dataset.replicas.tag
|
102
|
+
options.port = dataset.replicas.port
|
103
|
+
|
104
|
+
options.joining_node = "#{options.joining_host}:#{options.port}/#{options.tag}"
|
105
|
+
|
106
|
+
puts "Joining new replica to the cluster..."
|
107
|
+
Droonga::Serf.send_query(options.joining_node, "join",
|
108
|
+
"node" => options.joining_node,
|
109
|
+
"type" => "replica",
|
110
|
+
"source" => options.replica_source_host,
|
111
|
+
"copy" => options.copy)
|
112
|
+
|
113
|
+
puts "Done."
|
114
|
+
|
115
|
+
exit(true)
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
require "ostruct"
|
19
|
+
require "optparse"
|
20
|
+
require "json"
|
21
|
+
require "pathname"
|
22
|
+
|
23
|
+
require "droonga/engine/version"
|
24
|
+
require "droonga/path"
|
25
|
+
require "droonga/catalog_generator"
|
26
|
+
require "droonga/safe_file_writer"
|
27
|
+
require "droonga/serf"
|
28
|
+
|
29
|
+
options = OpenStruct.new
|
30
|
+
options.base_dir = ENV[Droonga::Path::BASE_DIR_ENV_NAME] || Dir.pwd
|
31
|
+
|
32
|
+
parser = OptionParser.new
|
33
|
+
parser.version = Droonga::Engine::VERSION
|
34
|
+
|
35
|
+
parser.on("--base-dir=PATH",
|
36
|
+
"Path to the base directory the catalog.json is located in.",
|
37
|
+
"(#{options.base_dir})") do |path|
|
38
|
+
options.base_dir = path
|
39
|
+
end
|
40
|
+
parser.on("--host=HOST",
|
41
|
+
"Host name of the replica removed from cluster.") do |host|
|
42
|
+
options.replica_remove_host = host
|
43
|
+
end
|
44
|
+
|
45
|
+
parser.parse!(ARGV)
|
46
|
+
|
47
|
+
|
48
|
+
base_dir = Pathname(options.base_dir).expand_path
|
49
|
+
ENV[Droonga::Path::BASE_DIR_ENV_NAME] = base_dir.to_s
|
50
|
+
|
51
|
+
catalog_path = Droonga::Path.catalog
|
52
|
+
unless catalog_path.exist?
|
53
|
+
raise "Cannot load 'catalog.json'. You must specify correct path " +
|
54
|
+
"to the base directory via --base-dir option."
|
55
|
+
end
|
56
|
+
|
57
|
+
unless options.replica_remove_host
|
58
|
+
raise "You must specify the host name or the IP address of a node to " +
|
59
|
+
"be removed from the cluster via --replica-remove-host option."
|
60
|
+
end
|
61
|
+
|
62
|
+
source_catalog = JSON.parse(catalog_path.read)
|
63
|
+
generator = Droonga::CatalogGenerator.new
|
64
|
+
generator.load(source_catalog)
|
65
|
+
|
66
|
+
dataset = generator.dataset_for_host(options.replica_remove_host)
|
67
|
+
unless dataset
|
68
|
+
raise "Specified host #{options.replica_remove_host} is not a member of "+
|
69
|
+
"the cluster. You must specify correct host via --replica-remove-host " +
|
70
|
+
"option."
|
71
|
+
end
|
72
|
+
|
73
|
+
options.dataset = dataset.name
|
74
|
+
options.tag = dataset.replicas.tag
|
75
|
+
options.port = dataset.replicas.port
|
76
|
+
options.other_hosts = dataset.replicas.hosts
|
77
|
+
|
78
|
+
remaining_host = options.other_hosts.first || options.replica_remove_host
|
79
|
+
options.remaining_node = "#{remaining_host}:#{options.port}/#{options.tag}"
|
80
|
+
|
81
|
+
|
82
|
+
puts "Unjoining replica from the cluster..."
|
83
|
+
|
84
|
+
Droonga::Serf.send_query(options.remaining_node, "remove_replicas",
|
85
|
+
"dataset" => options.dataset,
|
86
|
+
"hosts" => [options.replica_remove_host])
|
87
|
+
|
88
|
+
puts "Done."
|
89
|
+
|
90
|
+
exit(true)
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 1.0.4: 2014-06-29
|
4
|
+
|
5
|
+
* New command (and plugin) [`status`](http://droonga.org/reference/1.0.4/commands/status/) is now available.
|
6
|
+
* New command line tools are available.
|
7
|
+
* `droonga-engine-join` and `droonga-engine-unjoin` help you to modify cluster composition. See [the tutorial to add/remove replica](http://droonga.org/tutorial/1.0.4/add-replica/).
|
8
|
+
* `droonga-engine-absorb-data` helps you to duplicate clusters. See [the tutorial for dump/restore](http://droonga.org/tutorial/1.0.4/dump-restore/).
|
9
|
+
* `droonga-engine-catalog-modify` helps you to modify existing `catalog.json`.
|
10
|
+
|
3
11
|
## 1.0.3: 2014-05-29
|
4
12
|
|
5
13
|
* Alive monitoring (based on [Serf](http://serfdom.io/)) lands.
|
data/droonga-engine.gemspec
CHANGED
@@ -41,10 +41,11 @@ Gem::Specification.new do |gem|
|
|
41
41
|
gem.add_dependency "cool.io"
|
42
42
|
gem.add_dependency "serverengine"
|
43
43
|
gem.add_dependency "droonga-message-pack-packer", ">= 1.0.1"
|
44
|
-
gem.add_dependency "listen", "~> 2.7"
|
45
44
|
gem.add_dependency "faraday"
|
46
45
|
gem.add_dependency "faraday_middleware"
|
47
46
|
gem.add_dependency "archive-zip"
|
47
|
+
gem.add_dependency "sigdump"
|
48
|
+
gem.add_dependency "drndump"
|
48
49
|
gem.add_development_dependency "rake"
|
49
50
|
gem.add_development_dependency "bundler"
|
50
51
|
gem.add_development_dependency "test-unit"
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
8
|
+
#
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
+
# Lesser General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
15
|
+
# License along with this library; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
+
|
18
|
+
require "cool.io"
|
19
|
+
|
20
|
+
require "droonga/loggable"
|
21
|
+
|
22
|
+
module Droonga
|
23
|
+
class BufferedTCPSocket < Coolio::TCPSocket
|
24
|
+
include Loggable
|
25
|
+
|
26
|
+
def initialize(socket, data_directory)
|
27
|
+
super(socket)
|
28
|
+
@data_directory = data_directory
|
29
|
+
@_write_buffer = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_connect
|
33
|
+
logger.trace("connected to #{@remote_host}:#{@remote_port}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def write(data)
|
37
|
+
reserve_write(data)
|
38
|
+
schedule_write
|
39
|
+
data.bytesize
|
40
|
+
end
|
41
|
+
|
42
|
+
def reserve_write(data)
|
43
|
+
chunk = Chunk.new(@data_directory, data, Time.now, 0)
|
44
|
+
chunk.buffering
|
45
|
+
@_write_buffer << chunk
|
46
|
+
data.bytesize
|
47
|
+
end
|
48
|
+
|
49
|
+
def on_writable
|
50
|
+
begin
|
51
|
+
chunk = @_write_buffer.shift
|
52
|
+
written_size = @_io.write(chunk.data)
|
53
|
+
if written_size == chunk.data.bytesize
|
54
|
+
chunk.written
|
55
|
+
else
|
56
|
+
chunk.written_partial(written_size)
|
57
|
+
@_write_buffer.unshift(chunk)
|
58
|
+
end
|
59
|
+
rescue Errno::EINTR
|
60
|
+
return
|
61
|
+
rescue SystemCallError, IOError, SocketError
|
62
|
+
return close
|
63
|
+
end
|
64
|
+
|
65
|
+
if @_write_buffer.empty?
|
66
|
+
disable_write_watcher
|
67
|
+
on_write_complete
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def resume
|
72
|
+
@_write_buffer = (load_chunks + @_write_buffer).sort_by do |chunk|
|
73
|
+
chunk.time_stamp
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def load_chunks
|
79
|
+
FileUtils.mkdir_p(@data_directory.to_s)
|
80
|
+
Pathname.glob("#{@data_directory}/*.chunk").collect do |chunk_path|
|
81
|
+
Chunk.load(chunk_path)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def log_tag
|
86
|
+
"[#{Process.ppid}][#{Process.pid}] buffered-tcp-socket"
|
87
|
+
end
|
88
|
+
|
89
|
+
class Chunk
|
90
|
+
class << self
|
91
|
+
def load(path)
|
92
|
+
data_directory = path.dirname
|
93
|
+
time_stamp1, time_stamp2, revision, = path.basename.to_s.split(".", 4)
|
94
|
+
data = path.open("rb") {|file| file.read}
|
95
|
+
time_stamp = Time.iso8601("#{time_stamp1}.#{time_stamp2}")
|
96
|
+
revision = Integer(revision)
|
97
|
+
new(data_directory, data, time_stamp, revision)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
attr_reader :data, :time_stamp
|
102
|
+
def initialize(data_directory, data, time_stamp, revision)
|
103
|
+
@data_directory = data_directory
|
104
|
+
@data = data
|
105
|
+
@time_stamp = time_stamp.utc
|
106
|
+
@revision = revision
|
107
|
+
end
|
108
|
+
|
109
|
+
def buffering
|
110
|
+
path.open("wb") do |file|
|
111
|
+
file.write(@data)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def written
|
116
|
+
FileUtils.rm_f(path.to_s)
|
117
|
+
end
|
118
|
+
|
119
|
+
def written_partial(size)
|
120
|
+
written
|
121
|
+
@data = @data[size..-1]
|
122
|
+
@revision += 1
|
123
|
+
buffering
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
def path
|
128
|
+
@data_directory + "#{@time_stamp.iso8601(6)}.#{@revision}.chunk"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|