droonga-engine 1.0.3 → 1.0.4
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/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
|