riddle 0.9.8.1231.0 → 0.9.8.1533.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ module Riddle
2
+ class Configuration
3
+ class Indexer < Riddle::Configuration::Section
4
+ self.settings = [:mem_limit, :max_iops, :max_iosize]
5
+
6
+ attr_accessor *self.settings
7
+
8
+ def render
9
+ raise ConfigurationError unless valid?
10
+
11
+ (
12
+ ["indexer", "{"] +
13
+ settings_body +
14
+ ["}", ""]
15
+ ).join("\n")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Riddle
2
+ class Configuration
3
+ class RemoteIndex
4
+ attr_accessor :address, :port, :name
5
+
6
+ def initialize(address, port, name)
7
+ @address = address
8
+ @port = port
9
+ @name = name
10
+ end
11
+
12
+ def remote
13
+ "#{address}:#{port}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Riddle
2
+ class Configuration
3
+ class Searchd < Riddle::Configuration::Section
4
+ self.settings = [:address, :port, :log, :query_log, :read_timeout,
5
+ :max_children, :pid_file, :max_matches, :seamless_rotate,
6
+ :preopen_indexes, :unlink_old]
7
+
8
+ attr_accessor *self.settings
9
+
10
+ def render
11
+ raise ConfigurationError unless valid?
12
+
13
+ (
14
+ ["searchd", "{"] +
15
+ settings_body +
16
+ ["}", ""]
17
+ ).join("\n")
18
+ end
19
+
20
+ def valid?
21
+ !( @port.nil? || @pid_file.nil? )
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,43 @@
1
+ module Riddle
2
+ class Configuration
3
+ class Section
4
+ class << self
5
+ attr_accessor :settings
6
+ end
7
+
8
+ settings = []
9
+
10
+ def valid?
11
+ true
12
+ end
13
+
14
+ private
15
+
16
+ def settings_body
17
+ self.class.settings.select { |setting|
18
+ !send(setting).nil?
19
+ }.collect { |setting|
20
+ if send(setting) == ""
21
+ conf = " #{setting} = "
22
+ else
23
+ conf = setting_to_array(setting).collect { |set|
24
+ " #{setting} = #{set}"
25
+ }
26
+ end
27
+ conf.length == 0 ? nil : conf
28
+ }.flatten.compact
29
+ end
30
+
31
+ def setting_to_array(setting)
32
+ value = send(setting)
33
+ case value
34
+ when Array then value
35
+ when TrueClass then [1]
36
+ when FalseClass then [0]
37
+ else
38
+ [value]
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ module Riddle
2
+ class Configuration
3
+ class Source < Riddle::Configuration::Section
4
+ attr_accessor :name, :parent, :type
5
+
6
+ def render
7
+ raise ConfigurationError unless valid?
8
+
9
+ inherited_name = "#{name}"
10
+ inherited_name << " : #{parent}" if parent
11
+ (
12
+ ["source #{inherited_name}", "{"] +
13
+ settings_body +
14
+ ["}", ""]
15
+ ).join("\n")
16
+ end
17
+
18
+ def valid?
19
+ !( @name.nil? || @type.nil? )
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module Riddle
2
+ class Configuration
3
+ class SQLSource < Riddle::Configuration::Source
4
+ self.settings = [:type, :sql_host, :sql_user, :sql_pass, :sql_db,
5
+ :sql_port, :sql_sock, :mysql_connect_flags, :sql_query_pre, :sql_query,
6
+ :sql_query_range, :sql_range_step, :sql_attr_uint, :sql_attr_bool,
7
+ :sql_attr_timestamp, :sql_attr_str2ordinal, :sql_attr_float,
8
+ :sql_attr_multi, :sql_query_post, :sql_query_post_index,
9
+ :sql_ranged_throttle, :sql_query_info]
10
+
11
+ attr_accessor *self.settings
12
+
13
+ def initialize(name, type)
14
+ @name = name
15
+ @type = type
16
+
17
+ @sql_query_pre = []
18
+ @sql_attr_uint = []
19
+ @sql_attr_bool = []
20
+ @sql_attr_timestamp = []
21
+ @sql_attr_str2ordinal = []
22
+ @sql_attr_float = []
23
+ @sql_attr_multi = []
24
+ @sql_query_post = []
25
+ @sql_query_post_index = []
26
+ end
27
+
28
+ def valid?
29
+ super && (!( @sql_host.nil? || @sql_user.nil? || @sql_db.nil? ||
30
+ @sql_query.nil? ) || !@parent.nil?)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ module Riddle
2
+ class Configuration
3
+ class XMLSource < Riddle::Configuration::Source
4
+ self.settings = [:type, :xmlpipe_command, :xmlpipe_field,
5
+ :xmlpipe_attr_uint, :xmlpipe_attr_bool, :xmlpipe_attr_timestamp,
6
+ :xmlpipe_attr_str2ordinal, :xmlpipe_attr_float, :xmlpipe_attr_multi]
7
+
8
+ attr_accessor *self.settings
9
+
10
+ def initialize(name, type)
11
+ @name = name
12
+ @type = type
13
+
14
+ @xmlpipe_field = []
15
+ @xmlpipe_attr_uint = []
16
+ @xmlpipe_attr_bool = []
17
+ @xmlpipe_attr_timestamp = []
18
+ @xmlpipe_attr_str2ordinal = []
19
+ @xmlpipe_attr_float = []
20
+ @xmlpipe_attr_multi = []
21
+ end
22
+
23
+ def valid?
24
+ super && ( !@xmlpipe_command.nil? || !parent.nil? )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ module Riddle
2
+ class Controller
3
+ def initialize(configuration, path)
4
+ @configuration = configuration
5
+ @path = path
6
+ end
7
+
8
+ def index
9
+ cmd = "indexer --config #{@path} --all"
10
+ cmd << " --rotate" if running?
11
+ `#{cmd}`
12
+ end
13
+
14
+ def start
15
+ return if running?
16
+
17
+ cmd = "searchd --pidfile --config #{@path}"
18
+
19
+ if RUBY_PLATFORM =~ /mswin/
20
+ system("start /B #{cmd} 1> NUL 2>&1")
21
+ else
22
+ `#{cmd}`
23
+ end
24
+
25
+ sleep(1)
26
+
27
+ unless running?
28
+ puts "Failed to start searchd daemon. Check #{@configuration.searchd.log}."
29
+ end
30
+ end
31
+
32
+ def stop
33
+ return unless running?
34
+ Process.kill('SIGTERM', pid.to_i)
35
+ rescue Errno::EINVAL
36
+ Process.kill('SIGKILL', pid.to_i)
37
+ end
38
+
39
+ def pid
40
+ if File.exists?(@configuration.searchd.pid_file)
41
+ File.read(@configuration.searchd.pid_file)[/\d+/]
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ def running?
48
+ !!pid && !!Process.kill(0, pid.to_i)
49
+ rescue
50
+ false
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ TabTab::Definition.register("searchd") do |c|
2
+ c.flag :help, :h
3
+ c.flag :config, :c
4
+ c.flag :stop
5
+ c.flag :iostats
6
+ c.flag :console
7
+ c.flag :port, :p
8
+ c.flag :index, :i
9
+ end
10
+
11
+ TabTab::Definition.register("indexer") do |c|
12
+ c.flag :config, :c
13
+ c.flag :all
14
+ c.flag :rotate
15
+ end
@@ -177,4 +177,32 @@ describe Riddle::Client do
177
177
  true
178
178
  ).should == query_contents(:keywords_with_hits)
179
179
  end
180
- end
180
+
181
+ it "should timeout after a specified time" do
182
+ client = Riddle::Client.new
183
+ client.port = 3314
184
+ client.timeout = 1
185
+
186
+ server = TCPServer.new "localhost", 3314
187
+
188
+ lambda {
189
+ client.send(:connect) { |socket| }
190
+ }.should raise_error(Riddle::ConnectionError)
191
+
192
+ server.close
193
+ end
194
+
195
+ context "connection retrying" do
196
+ it "should try fives time when connection refused" do
197
+ client = Riddle::Client.new
198
+ client.port = 3314
199
+
200
+ TCPSocket.should_receive(:new).with('localhost', 3314).exactly(5).times.
201
+ and_raise(Errno::ECONNREFUSED)
202
+
203
+ lambda {
204
+ client.send(:connect) { |socket| }
205
+ }.should raise_error(Riddle::ConnectionError)
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Riddle::Configuration::DistributedIndex do
4
+ it "should not be valid without any indexes" do
5
+ index = Riddle::Configuration::DistributedIndex.new("dist1")
6
+ index.should_not be_valid
7
+ end
8
+
9
+ it "should be valid with just local indexes" do
10
+ index = Riddle::Configuration::DistributedIndex.new("dist1")
11
+ index.local_indexes << "local_one"
12
+ index.should be_valid
13
+ end
14
+
15
+ it "should be valid with just remote indexes" do
16
+ index = Riddle::Configuration::DistributedIndex.new("dist1")
17
+ index.remote_indexes << Riddle::Configuration::RemoteIndex.new("local", 3312, "remote_one")
18
+ index.should be_valid
19
+ end
20
+
21
+ it "should be of type 'distributed'" do
22
+ index = Riddle::Configuration::DistributedIndex.new("dist1")
23
+ index.type.should == 'distributed'
24
+ end
25
+
26
+ it "should raise a ConfigurationError if rendering when not valid" do
27
+ index = Riddle::Configuration::DistributedIndex.new("dist1")
28
+ lambda { index.render }.should raise_error(Riddle::Configuration::ConfigurationError)
29
+ end
30
+
31
+ it "should render correctly if supplied settings are valid" do
32
+ index = Riddle::Configuration::DistributedIndex.new("dist1")
33
+
34
+ index.local_indexes << "test1" << "test1stemmed"
35
+ index.remote_indexes <<
36
+ Riddle::Configuration::RemoteIndex.new("localhost", 3313, "remote1") <<
37
+ Riddle::Configuration::RemoteIndex.new("localhost", 3314, "remote2") <<
38
+ Riddle::Configuration::RemoteIndex.new("localhost", 3314, "remote3")
39
+
40
+ index.agent_connect_timeout = 1000
41
+ index.agent_query_timeout = 3000
42
+
43
+ index.render.should == <<-DISTINDEX
44
+ index dist1
45
+ {
46
+ type = distributed
47
+ local = test1
48
+ local = test1stemmed
49
+ agent = localhost:3313:remote1
50
+ agent = localhost:3314:remote2,remote3
51
+ agent_connect_timeout = 1000
52
+ agent_query_timeout = 3000
53
+ }
54
+ DISTINDEX
55
+ end
56
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Riddle::Configuration::DistributedIndex do
4
+ it "should be invalid without a name, sources or path if there's no parent" do
5
+ index = Riddle::Configuration::Index.new(nil)
6
+ index.should_not be_valid
7
+
8
+ index.name = "test1"
9
+ index.should_not be_valid
10
+
11
+ index.sources << Riddle::Configuration::SQLSource.new("source", "mysql")
12
+ index.should_not be_valid
13
+
14
+ index.path = "a/path"
15
+ index.should be_valid
16
+
17
+ index.name = nil
18
+ index.should_not be_valid
19
+
20
+ index.name = "test1"
21
+ index.sources.clear
22
+ index.should_not be_valid
23
+ end
24
+
25
+ it "should be invalid without a name but not sources or path if it has a parent" do
26
+ index = Riddle::Configuration::Index.new(nil)
27
+ index.should_not be_valid
28
+
29
+ index.name = "test1stemmed"
30
+ index.should_not be_valid
31
+
32
+ index.parent = "test1"
33
+ index.should be_valid
34
+ end
35
+
36
+ it "should raise a ConfigurationError if rendering when not valid" do
37
+ index = Riddle::Configuration::Index.new("test1")
38
+ lambda { index.render }.should raise_error(Riddle::Configuration::ConfigurationError)
39
+ end
40
+
41
+ it "should render correctly if supplied settings are valid" do
42
+ source = Riddle::Configuration::XMLSource.new("src1", "xmlpipe")
43
+ source.xmlpipe_command = "ls /dev/null"
44
+
45
+ index = Riddle::Configuration::Index.new("test1", source)
46
+ index.path = "/var/data/test1"
47
+ index.docinfo = "extern"
48
+ index.mlock = 0
49
+ index.morphologies << "stem_en" << "stem_ru" << "soundex"
50
+ index.stopword_files << "/var/data/stopwords.txt" << "/var/data/stopwords2.txt"
51
+ index.wordform_files << "/var/data/wordforms.txt"
52
+ index.exception_files << "/var/data/exceptions.txt"
53
+ index.min_word_len = 1
54
+ index.charset_type = "utf-8"
55
+ index.charset_table = "0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F"
56
+ index.ignore_characters << "U+00AD"
57
+ index.min_prefix_len = 0
58
+ index.min_infix_len = 0
59
+ index.prefix_field_names << "filename"
60
+ index.infix_field_names << "url" << "domain"
61
+ index.enable_star = true
62
+ index.ngram_len = 1
63
+ index.ngram_characters << "U+3000..U+2FA1F"
64
+ index.phrase_boundaries << "." << "?" << "!" << "U+2026"
65
+ index.phrase_boundary_step = 100
66
+ index.html_strip = 0
67
+ index.html_index_attrs = "img=alt,title; a=title"
68
+ index.html_remove_element_tags << "style" << "script"
69
+ index.preopen = 1
70
+
71
+ index.render.should == <<-INDEX
72
+ source src1
73
+ {
74
+ type = xmlpipe
75
+ xmlpipe_command = ls /dev/null
76
+ }
77
+
78
+ index test1
79
+ {
80
+ source = src1
81
+ path = /var/data/test1
82
+ docinfo = extern
83
+ mlock = 0
84
+ morphology = stem_en, stem_ru, soundex
85
+ stopwords = /var/data/stopwords.txt /var/data/stopwords2.txt
86
+ wordforms = /var/data/wordforms.txt
87
+ exceptions = /var/data/exceptions.txt
88
+ min_word_len = 1
89
+ charset_type = utf-8
90
+ charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
91
+ ignore_chars = U+00AD
92
+ min_prefix_len = 0
93
+ min_infix_len = 0
94
+ prefix_fields = filename
95
+ infix_fields = url, domain
96
+ enable_star = 1
97
+ ngram_len = 1
98
+ ngram_chars = U+3000..U+2FA1F
99
+ phrase_boundary = ., ?, !, U+2026
100
+ phrase_boundary_step = 100
101
+ html_strip = 0
102
+ html_index_attrs = img=alt,title; a=title
103
+ html_remove_elements = style, script
104
+ preopen = 1
105
+ }
106
+ INDEX
107
+ end
108
+ end