fluent-plugin-droonga 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +40 -0
- data/LICENSE.txt +14 -0
- data/README.md +18 -0
- data/Rakefile +25 -0
- data/benchmark/benchmark.rb +123 -0
- data/benchmark/utils.rb +243 -0
- data/benchmark/watch/benchmark-notify.rb +143 -0
- data/benchmark/watch/benchmark-notify.sh +19 -0
- data/benchmark/watch/benchmark-publish.rb +120 -0
- data/benchmark/watch/benchmark-scan.rb +210 -0
- data/benchmark/watch/catalog.json +32 -0
- data/benchmark/watch/fluentd.conf +12 -0
- data/bin/grn2jsons +85 -0
- data/fluent-plugin-droonga.gemspec +41 -0
- data/lib/droonga/adapter.rb +156 -0
- data/lib/droonga/catalog.rb +153 -0
- data/lib/droonga/command_mapper.rb +45 -0
- data/lib/droonga/engine.rb +83 -0
- data/lib/droonga/executor.rb +289 -0
- data/lib/droonga/handler.rb +140 -0
- data/lib/droonga/handler_plugin.rb +35 -0
- data/lib/droonga/job_queue.rb +83 -0
- data/lib/droonga/job_queue_schema.rb +65 -0
- data/lib/droonga/logger.rb +34 -0
- data/lib/droonga/plugin.rb +41 -0
- data/lib/droonga/plugin/adapter/groonga/select.rb +88 -0
- data/lib/droonga/plugin/adapter_groonga.rb +40 -0
- data/lib/droonga/plugin/handler/groonga/column_create.rb +103 -0
- data/lib/droonga/plugin/handler/groonga/table_create.rb +100 -0
- data/lib/droonga/plugin/handler_add.rb +44 -0
- data/lib/droonga/plugin/handler_forward.rb +70 -0
- data/lib/droonga/plugin/handler_groonga.rb +52 -0
- data/lib/droonga/plugin/handler_proxy.rb +82 -0
- data/lib/droonga/plugin/handler_search.rb +33 -0
- data/lib/droonga/plugin/handler_watch.rb +102 -0
- data/lib/droonga/proxy.rb +371 -0
- data/lib/droonga/searcher.rb +415 -0
- data/lib/droonga/server.rb +112 -0
- data/lib/droonga/sweeper.rb +42 -0
- data/lib/droonga/watch_schema.rb +88 -0
- data/lib/droonga/watcher.rb +256 -0
- data/lib/droonga/worker.rb +51 -0
- data/lib/fluent/plugin/out_droonga.rb +56 -0
- data/lib/groonga_command_converter.rb +137 -0
- data/sample/cluster/catalog.json +43 -0
- data/sample/cluster/fluentd.conf +12 -0
- data/sample/fluentd.conf +8 -0
- data/test/fixtures/catalog.json +43 -0
- data/test/fixtures/document.grn +23 -0
- data/test/helper.rb +24 -0
- data/test/helper/fixture.rb +28 -0
- data/test/helper/sandbox.rb +73 -0
- data/test/helper/stub_worker.rb +27 -0
- data/test/helper/watch_helper.rb +35 -0
- data/test/plugin/adapter/groonga/test_select.rb +176 -0
- data/test/plugin/handler/groonga/test_column_create.rb +127 -0
- data/test/plugin/handler/groonga/test_table_create.rb +140 -0
- data/test/plugin/handler/test_handler_add.rb +135 -0
- data/test/plugin/handler/test_handler_groonga.rb +64 -0
- data/test/plugin/handler/test_handler_search.rb +512 -0
- data/test/plugin/handler/test_handler_watch.rb +168 -0
- data/test/run-test.rb +55 -0
- data/test/test_adapter.rb +48 -0
- data/test/test_catalog.rb +59 -0
- data/test/test_command_mapper.rb +44 -0
- data/test/test_groonga_command_converter.rb +242 -0
- data/test/test_handler.rb +53 -0
- data/test/test_job_queue_schema.rb +45 -0
- data/test/test_output.rb +99 -0
- data/test/test_sweeper.rb +95 -0
- data/test/test_watch_schema.rb +57 -0
- data/test/test_watcher.rb +336 -0
- data/test/test_worker.rb +144 -0
- metadata +299 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"effective_date": "2013-09-01T00:00:00Z",
|
3
|
+
"zones": ["localhost:23003/droonga"],
|
4
|
+
"farms": {
|
5
|
+
"localhost:23003/droonga": {
|
6
|
+
"device": ".",
|
7
|
+
"capacity": 10
|
8
|
+
}
|
9
|
+
},
|
10
|
+
"datasets": {
|
11
|
+
"Watch": {
|
12
|
+
"workers": 0,
|
13
|
+
"plugins": ["search", "groonga", "add", "watch"],
|
14
|
+
"number_of_replicas": 1,
|
15
|
+
"number_of_partitions": 1,
|
16
|
+
"partition_key": "_key",
|
17
|
+
"date_range": "infinity",
|
18
|
+
"ring": {
|
19
|
+
"localhost:23041": {
|
20
|
+
"weight": 50,
|
21
|
+
"partitions": {
|
22
|
+
"2013-09-01": [
|
23
|
+
"localhost:23003/droonga.watch"
|
24
|
+
]
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
},
|
30
|
+
"options": {
|
31
|
+
}
|
32
|
+
}
|
data/bin/grn2jsons
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
#
|
4
|
+
# Copyright (C) 2013 droonga project
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License version 2.1 as published by the Free Software Foundation.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
|
19
|
+
require "groonga_command_converter"
|
20
|
+
require "json"
|
21
|
+
require "ostruct"
|
22
|
+
require "optparse"
|
23
|
+
|
24
|
+
options = OpenStruct.new
|
25
|
+
option_parser = OptionParser.new do |parser|
|
26
|
+
parser.on("-i=ID", "--id=ID",
|
27
|
+
"base id. (optional)") do |id|
|
28
|
+
options.id = id
|
29
|
+
end
|
30
|
+
|
31
|
+
parser.on("-d=DATE", "--date=DATE",
|
32
|
+
"date. (optional)") do |date|
|
33
|
+
options.date = date
|
34
|
+
end
|
35
|
+
|
36
|
+
parser.on("-r=REPLYTO", "--reply-to=REPLYTO",
|
37
|
+
"value of replyTo field.") do |reply_to|
|
38
|
+
options.reply_to = reply_to
|
39
|
+
end
|
40
|
+
|
41
|
+
parser.on("-s=DATASET", "--dataset=DATASET",
|
42
|
+
"dataset.") do |dataset|
|
43
|
+
options.dataset = dataset
|
44
|
+
end
|
45
|
+
end
|
46
|
+
args = option_parser.parse!(ARGV)
|
47
|
+
|
48
|
+
if options.reply_to.nil?
|
49
|
+
raise "You must specify the value of the \"replyTo\" field by --reply-to option."
|
50
|
+
end
|
51
|
+
if options.dataset.nil?
|
52
|
+
raise "You must specify the name of the dataset by --dataset option."
|
53
|
+
end
|
54
|
+
|
55
|
+
convert_options = {
|
56
|
+
:id => options.id,
|
57
|
+
:date => options.date,
|
58
|
+
:reply_to => options.reply_to,
|
59
|
+
:dataset => options.dataset,
|
60
|
+
}
|
61
|
+
converter = Droonga::GroongaCommandConverter.new(convert_options)
|
62
|
+
|
63
|
+
source_file = args[0]
|
64
|
+
result_file = args[1]
|
65
|
+
|
66
|
+
input = nil
|
67
|
+
if source_file.nil?
|
68
|
+
input = STDIN.read
|
69
|
+
else
|
70
|
+
input = File.read(source_file)
|
71
|
+
end
|
72
|
+
|
73
|
+
result_file = args[1]
|
74
|
+
|
75
|
+
if result_file.nil?
|
76
|
+
converter.convert(input) do |command|
|
77
|
+
puts(JSON.generate(command))
|
78
|
+
end
|
79
|
+
else
|
80
|
+
File.open("w", result_file) do |file|
|
81
|
+
converter.convert(input) do |command|
|
82
|
+
file.puts(JSON.generate(command))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 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
|
+
Gem::Specification.new do |gem|
|
19
|
+
gem.name = "fluent-plugin-droonga"
|
20
|
+
gem.version = "0.0.2"
|
21
|
+
gem.authors = ["Droonga Project"]
|
22
|
+
gem.email = ["droonga@groonga.org"]
|
23
|
+
gem.description = "Droonga(distributed groonga) plugin for Fluent event collector"
|
24
|
+
gem.summary = gem.description
|
25
|
+
gem.homepage = "https://github.com/droonga/fluent-plugin-droonga"
|
26
|
+
gem.files = `git ls-files`.split($/)
|
27
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
28
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
29
|
+
gem.require_paths = ["lib"]
|
30
|
+
gem.add_dependency "fluentd"
|
31
|
+
gem.add_dependency "rroonga", ">= 3.0.3"
|
32
|
+
gem.add_dependency "groonga-command-parser"
|
33
|
+
gem.add_dependency "fluent-logger"
|
34
|
+
gem.add_dependency "serverengine"
|
35
|
+
gem.add_development_dependency "rake"
|
36
|
+
gem.add_development_dependency "bundler"
|
37
|
+
gem.add_development_dependency "droonga-client"
|
38
|
+
gem.add_development_dependency "test-unit"
|
39
|
+
gem.add_development_dependency "test-unit-notify"
|
40
|
+
gem.add_development_dependency "test-unit-rr"
|
41
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 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 "droonga/handler"
|
19
|
+
|
20
|
+
module Droonga
|
21
|
+
class Adapter < Droonga::Handler
|
22
|
+
def scatter_all(request, key)
|
23
|
+
message = [{
|
24
|
+
"command"=> envelope["type"],
|
25
|
+
"dataset"=> envelope["dataset"],
|
26
|
+
"body"=> request,
|
27
|
+
"key"=> key,
|
28
|
+
"type"=> "scatter",
|
29
|
+
"replica"=> "all",
|
30
|
+
"post"=> true
|
31
|
+
}]
|
32
|
+
post(message, "proxy")
|
33
|
+
end
|
34
|
+
|
35
|
+
def broadcast_all(request)
|
36
|
+
message = [{
|
37
|
+
"command"=> envelope["type"],
|
38
|
+
"dataset"=> envelope["dataset"],
|
39
|
+
"body"=> request,
|
40
|
+
"type"=> "broadcast",
|
41
|
+
"replica"=> "all",
|
42
|
+
"post"=> true
|
43
|
+
}]
|
44
|
+
post(message, "proxy")
|
45
|
+
end
|
46
|
+
|
47
|
+
def prefer_synchronous?(command)
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class BasicAdapter < Adapter
|
53
|
+
Droonga::HandlerPlugin.register("adapter", self)
|
54
|
+
|
55
|
+
command :table_create
|
56
|
+
def table_create(request)
|
57
|
+
broadcast_all(request)
|
58
|
+
end
|
59
|
+
|
60
|
+
command :column_create
|
61
|
+
def column_create(request)
|
62
|
+
broadcast_all(request)
|
63
|
+
end
|
64
|
+
|
65
|
+
command "watch.feed" => :feed
|
66
|
+
def feed(request)
|
67
|
+
broadcast_all(request)
|
68
|
+
end
|
69
|
+
|
70
|
+
command "watch.subscribe" => :subscribe
|
71
|
+
def subscribe(request)
|
72
|
+
broadcast_all(request)
|
73
|
+
end
|
74
|
+
|
75
|
+
command "watch.unsubscribe" => :unsubscribe
|
76
|
+
def unsubscribe(request)
|
77
|
+
broadcast_all(request)
|
78
|
+
end
|
79
|
+
|
80
|
+
command :add
|
81
|
+
def add(request)
|
82
|
+
# TODO: update events must be serialized in the primary node of replicas.
|
83
|
+
key = request["key"] || rand.to_s
|
84
|
+
scatter_all(request, key)
|
85
|
+
end
|
86
|
+
|
87
|
+
command :update
|
88
|
+
def update(request)
|
89
|
+
# TODO: update events must be serialized in the primary node of replicas.
|
90
|
+
key = request["key"] || rand.to_s
|
91
|
+
scatter_all(request, key)
|
92
|
+
end
|
93
|
+
|
94
|
+
command :reset
|
95
|
+
def add(request)
|
96
|
+
# TODO: update events must be serialized in the primary node of replicas.
|
97
|
+
key = request["key"] || rand.to_s
|
98
|
+
scatter_all(request, key)
|
99
|
+
end
|
100
|
+
|
101
|
+
command :search
|
102
|
+
def search(request)
|
103
|
+
message = []
|
104
|
+
input_names = []
|
105
|
+
output_names = []
|
106
|
+
name_mapper = {}
|
107
|
+
request["queries"].each do |input_name, query|
|
108
|
+
output = query["output"]
|
109
|
+
next unless output
|
110
|
+
input_names << input_name
|
111
|
+
output_name = input_name + "_reduced"
|
112
|
+
output_names << output_name
|
113
|
+
name_mapper[output_name] = input_name
|
114
|
+
# TODO: offset & limit must be arranged here.
|
115
|
+
elements = {}
|
116
|
+
output["elements"].each do |element|
|
117
|
+
case element
|
118
|
+
when "count"
|
119
|
+
elements[element] = ["sum"]
|
120
|
+
when "records"
|
121
|
+
# TODO: must take "sortBy" section into account.
|
122
|
+
elements[element] = ["sort", "<"]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
reducer = {
|
126
|
+
"inputs"=> [input_name],
|
127
|
+
"outputs"=> [output_name],
|
128
|
+
"type"=> "reduce",
|
129
|
+
"body"=> {
|
130
|
+
input_name=> {
|
131
|
+
output_name=> elements
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
message << reducer
|
136
|
+
end
|
137
|
+
gatherer = {
|
138
|
+
"inputs"=> output_names,
|
139
|
+
"type"=> "gather",
|
140
|
+
"body"=> name_mapper,
|
141
|
+
"post"=> true
|
142
|
+
}
|
143
|
+
message << gatherer
|
144
|
+
searcher = {
|
145
|
+
"dataset"=> envelope["dataset"] || request["dataset"],
|
146
|
+
"outputs"=> input_names,
|
147
|
+
"type"=> "broadcast",
|
148
|
+
"command"=> "search",
|
149
|
+
"replica"=> "random",
|
150
|
+
"body"=> request
|
151
|
+
}
|
152
|
+
message.push(searcher)
|
153
|
+
post(message, "proxy")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 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 "digest/sha1"
|
19
|
+
require "zlib"
|
20
|
+
|
21
|
+
module Droonga
|
22
|
+
class << self
|
23
|
+
def catalog
|
24
|
+
@catalog ||= Catalog.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Catalog
|
29
|
+
CATALOG_FILE_PATH = "catalog.json"
|
30
|
+
|
31
|
+
attr_reader :path
|
32
|
+
|
33
|
+
def initialize(path=nil)
|
34
|
+
@path = path || default_path
|
35
|
+
|
36
|
+
open(@path) do |file|
|
37
|
+
@catalog = JSON.parse(file.read)
|
38
|
+
end
|
39
|
+
@catalog["datasets"].each do |name, dataset|
|
40
|
+
number_of_partitions = dataset["number_of_partitions"]
|
41
|
+
next if number_of_partitions < 2
|
42
|
+
total_weight = dataset["ring"].reduce do |a, b|
|
43
|
+
a[1]["weight"] + b[1]["weight"]
|
44
|
+
end
|
45
|
+
continuum = []
|
46
|
+
dataset["ring"].each do |key, value|
|
47
|
+
points = number_of_partitions * 160 * value["weight"] / total_weight
|
48
|
+
points.times do |point|
|
49
|
+
hash = Digest::SHA1.hexdigest("#{key}:#{point}")
|
50
|
+
continuum << [hash[0..7].to_i(16), key]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
dataset["continuum"] = continuum.sort do |a, b| a[0] - b[0]; end
|
54
|
+
end
|
55
|
+
@options = @catalog["options"] || {}
|
56
|
+
end
|
57
|
+
|
58
|
+
def base_path
|
59
|
+
@base_path ||= File.dirname(@path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def option(name)
|
63
|
+
@options[name]
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_engines(name)
|
67
|
+
device = @catalog["farms"][name]["device"]
|
68
|
+
pattern = Regexp.new("^#{name}\.")
|
69
|
+
results = {}
|
70
|
+
@catalog["datasets"].each do |key, dataset|
|
71
|
+
workers = dataset["workers"]
|
72
|
+
plugins = dataset["plugins"]
|
73
|
+
dataset["ring"].each do |key, part|
|
74
|
+
part["partitions"].each do |range, partitions|
|
75
|
+
partitions.each do |partition|
|
76
|
+
if partition =~ pattern
|
77
|
+
path = File.join([device, $POSTMATCH, "db"])
|
78
|
+
path = File.expand_path(path, base_path)
|
79
|
+
options = {
|
80
|
+
:database => path,
|
81
|
+
:n_workers => workers,
|
82
|
+
:handlers => plugins
|
83
|
+
}
|
84
|
+
results[partition] = options
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
return results
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_routes(name, args)
|
94
|
+
routes = []
|
95
|
+
dataset = dataset(name)
|
96
|
+
return routes unless dataset
|
97
|
+
case args["type"]
|
98
|
+
when "broadcast"
|
99
|
+
dataset["ring"].each do |key, partition|
|
100
|
+
select_range_and_replicas(partition, args, routes)
|
101
|
+
end
|
102
|
+
when "scatter"
|
103
|
+
name = get_partition(dataset, args["key"])
|
104
|
+
partition = dataset["ring"][name]
|
105
|
+
select_range_and_replicas(partition, args, routes)
|
106
|
+
end
|
107
|
+
return routes
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_partition(dataset, key)
|
111
|
+
continuum = dataset["continuum"]
|
112
|
+
return dataset["ring"].keys[0] unless continuum
|
113
|
+
hash = Zlib.crc32(key)
|
114
|
+
min = 0
|
115
|
+
max = continuum.size - 1
|
116
|
+
while (min < max) do
|
117
|
+
index = (min + max) / 2
|
118
|
+
value, key = continuum[index]
|
119
|
+
return key if value == hash
|
120
|
+
if value > hash
|
121
|
+
max = index
|
122
|
+
else
|
123
|
+
min = index + 1
|
124
|
+
end
|
125
|
+
end
|
126
|
+
return continuum[max][1]
|
127
|
+
end
|
128
|
+
|
129
|
+
def dataset(name)
|
130
|
+
@catalog["datasets"][name]
|
131
|
+
end
|
132
|
+
|
133
|
+
def select_range_and_replicas(partition, args, routes)
|
134
|
+
date_range = args["date_range"] || 0..-1
|
135
|
+
partition["partitions"].sort[date_range].each do |time, replicas|
|
136
|
+
case args["replica"]
|
137
|
+
when "top"
|
138
|
+
routes << replicas[0]
|
139
|
+
when "random"
|
140
|
+
routes << replicas[rand(replicas.size)]
|
141
|
+
when "all"
|
142
|
+
routes.concat(replicas)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
def default_path
|
149
|
+
path = ENV["DROONGA_CATALOG"] || Catalog::CATALOG_FILE_PATH
|
150
|
+
File.expand_path(path)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|