sphinx 0.9.9.2117 → 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -3
- data/README.rdoc +18 -213
- data/Rakefile +15 -24
- data/VERSION.yml +1 -2
- data/install.rb +5 -0
- data/lib/sphinx/client.rb +893 -2089
- data/lib/sphinx/request.rb +11 -82
- data/lib/sphinx/response.rb +0 -2
- data/lib/sphinx.rb +5 -50
- data/spec/client_response_spec.rb +40 -33
- data/spec/client_spec.rb +471 -669
- data/spec/fixtures/ranking_sph04.php +9 -0
- data/spec/fixtures/sphinxapi.php +69 -54
- data/spec/sphinx/sphinx-id64.conf +1 -1
- data/spec/sphinx/sphinx.conf +1 -1
- data/spec/sphinx/sphinx_test.sql +2 -4
- data/sphinx.gemspec +8 -13
- data/sphinx.yml.tpl +3 -0
- data/tasks/sphinx.rake +75 -0
- metadata +6 -11
- data/lib/sphinx/buffered_io.rb +0 -26
- data/lib/sphinx/constants.rb +0 -179
- data/lib/sphinx/indifferent_access.rb +0 -152
- data/lib/sphinx/server.rb +0 -170
- data/lib/sphinx/timeout.rb +0 -31
- data/spec/client_validations_spec.rb +0 -859
- data/spec/spec_helper.rb +0 -24
data/lib/sphinx/constants.rb
DELETED
@@ -1,179 +0,0 @@
|
|
1
|
-
module Sphinx
|
2
|
-
# Contains all constants need by Sphinx API.
|
3
|
-
#
|
4
|
-
module Constants
|
5
|
-
#=================================================================
|
6
|
-
# Known searchd commands
|
7
|
-
#=================================================================
|
8
|
-
|
9
|
-
# search command
|
10
|
-
# @private
|
11
|
-
SEARCHD_COMMAND_SEARCH = 0
|
12
|
-
# excerpt command
|
13
|
-
# @private
|
14
|
-
SEARCHD_COMMAND_EXCERPT = 1
|
15
|
-
# update command
|
16
|
-
# @private
|
17
|
-
SEARCHD_COMMAND_UPDATE = 2
|
18
|
-
# keywords command
|
19
|
-
# @private
|
20
|
-
SEARCHD_COMMAND_KEYWORDS = 3
|
21
|
-
# persist command
|
22
|
-
# @private
|
23
|
-
SEARCHD_COMMAND_PERSIST = 4
|
24
|
-
# status command
|
25
|
-
# @private
|
26
|
-
SEARCHD_COMMAND_STATUS = 5
|
27
|
-
# query command
|
28
|
-
# @private
|
29
|
-
SEARCHD_COMMAND_QUERY = 6
|
30
|
-
|
31
|
-
#=================================================================
|
32
|
-
# Current client-side command implementation versions
|
33
|
-
#=================================================================
|
34
|
-
|
35
|
-
# search command version
|
36
|
-
# @private
|
37
|
-
VER_COMMAND_SEARCH = 0x116
|
38
|
-
# excerpt command version
|
39
|
-
# @private
|
40
|
-
VER_COMMAND_EXCERPT = 0x100
|
41
|
-
# update command version
|
42
|
-
# @private
|
43
|
-
VER_COMMAND_UPDATE = 0x102
|
44
|
-
# keywords command version
|
45
|
-
# @private
|
46
|
-
VER_COMMAND_KEYWORDS = 0x100
|
47
|
-
# persist command version
|
48
|
-
# @private
|
49
|
-
VER_COMMAND_PERSIST = 0x000
|
50
|
-
# status command version
|
51
|
-
# @private
|
52
|
-
VER_COMMAND_STATUS = 0x100
|
53
|
-
# query command version
|
54
|
-
# @private
|
55
|
-
VER_COMMAND_QUERY = 0x100
|
56
|
-
|
57
|
-
#=================================================================
|
58
|
-
# Known searchd status codes
|
59
|
-
#=================================================================
|
60
|
-
|
61
|
-
# general success, command-specific reply follows
|
62
|
-
# @private
|
63
|
-
SEARCHD_OK = 0
|
64
|
-
# general failure, command-specific reply may follow
|
65
|
-
# @private
|
66
|
-
SEARCHD_ERROR = 1
|
67
|
-
# temporaty failure, client should retry later
|
68
|
-
# @private
|
69
|
-
SEARCHD_RETRY = 2
|
70
|
-
# general success, warning message and command-specific reply follow
|
71
|
-
# @private
|
72
|
-
SEARCHD_WARNING = 3
|
73
|
-
|
74
|
-
#=================================================================
|
75
|
-
# Known match modes
|
76
|
-
#=================================================================
|
77
|
-
|
78
|
-
# match all query words
|
79
|
-
SPH_MATCH_ALL = 0
|
80
|
-
# match any query word
|
81
|
-
SPH_MATCH_ANY = 1
|
82
|
-
# match this exact phrase
|
83
|
-
SPH_MATCH_PHRASE = 2
|
84
|
-
# match this boolean query
|
85
|
-
SPH_MATCH_BOOLEAN = 3
|
86
|
-
# match this extended query
|
87
|
-
SPH_MATCH_EXTENDED = 4
|
88
|
-
# match all document IDs w/o fulltext query, apply filters
|
89
|
-
SPH_MATCH_FULLSCAN = 5
|
90
|
-
# extended engine V2 (TEMPORARY, WILL BE REMOVED IN 0.9.8-RELEASE)
|
91
|
-
SPH_MATCH_EXTENDED2 = 6
|
92
|
-
|
93
|
-
#=================================================================
|
94
|
-
# Known ranking modes (ext2 only)
|
95
|
-
#=================================================================
|
96
|
-
|
97
|
-
# default mode, phrase proximity major factor and BM25 minor one
|
98
|
-
SPH_RANK_PROXIMITY_BM25 = 0
|
99
|
-
# statistical mode, BM25 ranking only (faster but worse quality)
|
100
|
-
SPH_RANK_BM25 = 1
|
101
|
-
# no ranking, all matches get a weight of 1
|
102
|
-
SPH_RANK_NONE = 2
|
103
|
-
# simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts
|
104
|
-
SPH_RANK_WORDCOUNT = 3
|
105
|
-
# phrase proximity
|
106
|
-
SPH_RANK_PROXIMITY = 4
|
107
|
-
# emulate old match-any weighting
|
108
|
-
SPH_RANK_MATCHANY = 5
|
109
|
-
# sets bits where there were matches
|
110
|
-
SPH_RANK_FIELDMASK = 6
|
111
|
-
|
112
|
-
#=================================================================
|
113
|
-
# Known sort modes
|
114
|
-
#=================================================================
|
115
|
-
|
116
|
-
# sort by document relevance desc, then by date
|
117
|
-
SPH_SORT_RELEVANCE = 0
|
118
|
-
# sort by document date desc, then by relevance desc
|
119
|
-
SPH_SORT_ATTR_DESC = 1
|
120
|
-
# sort by document date asc, then by relevance desc
|
121
|
-
SPH_SORT_ATTR_ASC = 2
|
122
|
-
# sort by time segments (hour/day/week/etc) desc, then by relevance desc
|
123
|
-
SPH_SORT_TIME_SEGMENTS = 3
|
124
|
-
# sort by SQL-like expression (eg. "@relevance DESC, price ASC, @id DESC")
|
125
|
-
SPH_SORT_EXTENDED = 4
|
126
|
-
# sort by arithmetic expression in descending order (eg. "@id + max(@weight,1000)*boost + log(price)")
|
127
|
-
SPH_SORT_EXPR = 5
|
128
|
-
|
129
|
-
#=================================================================
|
130
|
-
# Known filter types
|
131
|
-
#=================================================================
|
132
|
-
|
133
|
-
# filter by integer values set
|
134
|
-
SPH_FILTER_VALUES = 0
|
135
|
-
# filter by integer range
|
136
|
-
SPH_FILTER_RANGE = 1
|
137
|
-
# filter by float range
|
138
|
-
SPH_FILTER_FLOATRANGE = 2
|
139
|
-
|
140
|
-
#=================================================================
|
141
|
-
# Known attribute types
|
142
|
-
#=================================================================
|
143
|
-
|
144
|
-
# this attr is just an integer
|
145
|
-
SPH_ATTR_INTEGER = 1
|
146
|
-
# this attr is a timestamp
|
147
|
-
SPH_ATTR_TIMESTAMP = 2
|
148
|
-
# this attr is an ordinal string number (integer at search time,
|
149
|
-
# specially handled at indexing time)
|
150
|
-
SPH_ATTR_ORDINAL = 3
|
151
|
-
# this attr is a boolean bit field
|
152
|
-
SPH_ATTR_BOOL = 4
|
153
|
-
# this attr is a float
|
154
|
-
SPH_ATTR_FLOAT = 5
|
155
|
-
# signed 64-bit integer
|
156
|
-
SPH_ATTR_BIGINT = 6
|
157
|
-
# this attr has multiple values (0 or more)
|
158
|
-
SPH_ATTR_MULTI = 0x40000000
|
159
|
-
|
160
|
-
#=================================================================
|
161
|
-
# Known grouping functions
|
162
|
-
#=================================================================
|
163
|
-
|
164
|
-
# group by day
|
165
|
-
SPH_GROUPBY_DAY = 0
|
166
|
-
# group by week
|
167
|
-
SPH_GROUPBY_WEEK = 1
|
168
|
-
# group by month
|
169
|
-
SPH_GROUPBY_MONTH = 2
|
170
|
-
# group by year
|
171
|
-
SPH_GROUPBY_YEAR = 3
|
172
|
-
# group by attribute value
|
173
|
-
SPH_GROUPBY_ATTR = 4
|
174
|
-
# group by sequential attrs pair
|
175
|
-
SPH_GROUPBY_ATTRPAIR = 5
|
176
|
-
end
|
177
|
-
|
178
|
-
include Constants
|
179
|
-
end
|
@@ -1,152 +0,0 @@
|
|
1
|
-
module Sphinx
|
2
|
-
begin
|
3
|
-
HashWithIndifferentAccess = ::HashWithIndifferentAccess
|
4
|
-
rescue NameError
|
5
|
-
# This class has dubious semantics and we only have it so that
|
6
|
-
# people can write params[:key] instead of params['key']
|
7
|
-
# and they get the same value for both keys.
|
8
|
-
#
|
9
|
-
# This is part of Rails' ActiveSupport project. If you are
|
10
|
-
# using Rails, this class will not be used.
|
11
|
-
#
|
12
|
-
class HashWithIndifferentAccess < Hash
|
13
|
-
def initialize(constructor = {})
|
14
|
-
if constructor.is_a?(Hash)
|
15
|
-
super()
|
16
|
-
update(constructor)
|
17
|
-
else
|
18
|
-
super(constructor)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def default(key = nil)
|
23
|
-
if key.is_a?(Symbol) && include?(key = key.to_s)
|
24
|
-
self[key]
|
25
|
-
else
|
26
|
-
super
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
31
|
-
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
32
|
-
|
33
|
-
# Assigns a new value to the hash:
|
34
|
-
#
|
35
|
-
# hash = HashWithIndifferentAccess.new
|
36
|
-
# hash[:key] = "value"
|
37
|
-
#
|
38
|
-
def []=(key, value)
|
39
|
-
regular_writer(convert_key(key), convert_value(value))
|
40
|
-
end
|
41
|
-
|
42
|
-
# Updates the instantized hash with values from the second:
|
43
|
-
#
|
44
|
-
# hash_1 = HashWithIndifferentAccess.new
|
45
|
-
# hash_1[:key] = "value"
|
46
|
-
#
|
47
|
-
# hash_2 = HashWithIndifferentAccess.new
|
48
|
-
# hash_2[:key] = "New Value!"
|
49
|
-
#
|
50
|
-
# hash_1.update(hash_2) # => {"key"=>"New Value!"}
|
51
|
-
#
|
52
|
-
def update(other_hash)
|
53
|
-
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
|
54
|
-
self
|
55
|
-
end
|
56
|
-
|
57
|
-
alias_method :merge!, :update
|
58
|
-
|
59
|
-
# Checks the hash for a key matching the argument passed in:
|
60
|
-
#
|
61
|
-
# hash = HashWithIndifferentAccess.new
|
62
|
-
# hash["key"] = "value"
|
63
|
-
# hash.key? :key # => true
|
64
|
-
# hash.key? "key" # => true
|
65
|
-
#
|
66
|
-
def key?(key)
|
67
|
-
super(convert_key(key))
|
68
|
-
end
|
69
|
-
|
70
|
-
alias_method :include?, :key?
|
71
|
-
alias_method :has_key?, :key?
|
72
|
-
alias_method :member?, :key?
|
73
|
-
|
74
|
-
# Fetches the value for the specified key, same as doing hash[key]
|
75
|
-
def fetch(key, *extras)
|
76
|
-
super(convert_key(key), *extras)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Returns an array of the values at the specified indices:
|
80
|
-
#
|
81
|
-
# hash = HashWithIndifferentAccess.new
|
82
|
-
# hash[:a] = "x"
|
83
|
-
# hash[:b] = "y"
|
84
|
-
# hash.values_at("a", "b") # => ["x", "y"]
|
85
|
-
#
|
86
|
-
def values_at(*indices)
|
87
|
-
indices.collect {|key| self[convert_key(key)]}
|
88
|
-
end
|
89
|
-
|
90
|
-
# Returns an exact copy of the hash.
|
91
|
-
def dup
|
92
|
-
HashWithIndifferentAccess.new(self)
|
93
|
-
end
|
94
|
-
|
95
|
-
# Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
|
96
|
-
# Does not overwrite the existing hash.
|
97
|
-
def merge(hash)
|
98
|
-
self.dup.update(hash)
|
99
|
-
end
|
100
|
-
|
101
|
-
# Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
|
102
|
-
# This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
|
103
|
-
def reverse_merge(other_hash)
|
104
|
-
super other_hash.with_indifferent_access
|
105
|
-
end
|
106
|
-
|
107
|
-
# Removes a specified key from the hash.
|
108
|
-
def delete(key)
|
109
|
-
super(convert_key(key))
|
110
|
-
end
|
111
|
-
|
112
|
-
def stringify_keys!; self end
|
113
|
-
def symbolize_keys!; self end
|
114
|
-
def to_options!; self end
|
115
|
-
|
116
|
-
# Convert to a Hash with String keys.
|
117
|
-
def to_hash
|
118
|
-
Hash.new(default).merge(self)
|
119
|
-
end
|
120
|
-
|
121
|
-
protected
|
122
|
-
def convert_key(key)
|
123
|
-
key.kind_of?(Symbol) ? key.to_s : key
|
124
|
-
end
|
125
|
-
|
126
|
-
def convert_value(value)
|
127
|
-
case value
|
128
|
-
when Hash
|
129
|
-
value.with_indifferent_access
|
130
|
-
when Array
|
131
|
-
value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
|
132
|
-
else
|
133
|
-
value
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
module HashIndifferentAccess #:nodoc:
|
139
|
-
def with_indifferent_access
|
140
|
-
hash = HashWithIndifferentAccess.new(self)
|
141
|
-
hash.default = self.default
|
142
|
-
hash
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
class ::Hash #:nodoc:
|
147
|
-
unless respond_to?(:with_indifferent_access)
|
148
|
-
include Sphinx::HashIndifferentAccess
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
data/lib/sphinx/server.rb
DELETED
@@ -1,170 +0,0 @@
|
|
1
|
-
# Represents an instance of searchd server.
|
2
|
-
#
|
3
|
-
# @private
|
4
|
-
class Sphinx::Server
|
5
|
-
# The host the Sphinx server is running on
|
6
|
-
attr_reader :host
|
7
|
-
|
8
|
-
# The port the Sphinx server is listening on
|
9
|
-
attr_reader :port
|
10
|
-
|
11
|
-
# The path to UNIX socket where Sphinx server is running on
|
12
|
-
attr_reader :path
|
13
|
-
|
14
|
-
# Creates a new instance of +Server+.
|
15
|
-
#
|
16
|
-
# Parameters:
|
17
|
-
# * +sphinx+ -- an instance of <tt>Sphinx::Client</tt>.
|
18
|
-
# * +host+ -- name of host where search is running (if +path+ is not specified).
|
19
|
-
# * +port+ -- searchd port (if +path+ is not specified).
|
20
|
-
# * +path+ -- an absolute path to the UNIX socket.
|
21
|
-
#
|
22
|
-
def initialize(sphinx, host, port, path)
|
23
|
-
@sphinx = sphinx
|
24
|
-
@host = host
|
25
|
-
@port = port
|
26
|
-
@path = path
|
27
|
-
|
28
|
-
@socket = nil
|
29
|
-
end
|
30
|
-
|
31
|
-
# Gets the opened socket to the server.
|
32
|
-
#
|
33
|
-
# You can pass a block to make any connection establishing related things,
|
34
|
-
# like protocol version interchange. They will be treated as a part of
|
35
|
-
# connection routine, so connection timeout will include them.
|
36
|
-
#
|
37
|
-
# In case of connection error, +SphinxConnectError+ exception will be raised.
|
38
|
-
#
|
39
|
-
# Method returns opened socket, so do not forget to close it using +free_socket+
|
40
|
-
# method. Make sure you will close socket in case of any emergency.
|
41
|
-
#
|
42
|
-
def get_socket(&block)
|
43
|
-
if persistent?
|
44
|
-
yield @socket
|
45
|
-
@socket
|
46
|
-
else
|
47
|
-
socket = nil
|
48
|
-
Sphinx::safe_execute(@sphinx.timeout) do
|
49
|
-
socket = establish_connection
|
50
|
-
|
51
|
-
# Do custom initialization
|
52
|
-
yield socket if block_given?
|
53
|
-
end
|
54
|
-
socket
|
55
|
-
end
|
56
|
-
rescue SocketError, SystemCallError, IOError, EOFError, ::Timeout::Error, ::Errno::EPIPE => e
|
57
|
-
# Close previously opened socket (in case of it has been really opened)
|
58
|
-
free_socket(socket, true)
|
59
|
-
|
60
|
-
error = "connection to #{to_s} failed ("
|
61
|
-
if e.kind_of?(SystemCallError)
|
62
|
-
error << "errno=#{e.class::Errno}, "
|
63
|
-
end
|
64
|
-
error << "msg=#{e.message})"
|
65
|
-
raise Sphinx::SphinxConnectError, error
|
66
|
-
end
|
67
|
-
|
68
|
-
# Closes previously opened socket.
|
69
|
-
#
|
70
|
-
# Pass socket retrieved with +get_socket+ method when finished work. It does
|
71
|
-
# not close persistent sockets, but if really you need to do it, pass +true+
|
72
|
-
# as +force+ parameter value.
|
73
|
-
#
|
74
|
-
def free_socket(socket, force = false)
|
75
|
-
# Socket has not been open
|
76
|
-
return false if socket.nil?
|
77
|
-
|
78
|
-
# Do we try to close persistent socket?
|
79
|
-
if socket == @socket
|
80
|
-
# do not close it if not forced
|
81
|
-
if force
|
82
|
-
@socket.close unless @socket.closed?
|
83
|
-
@socket = nil
|
84
|
-
true
|
85
|
-
else
|
86
|
-
false
|
87
|
-
end
|
88
|
-
else
|
89
|
-
# Just close this socket
|
90
|
-
socket.close unless socket.closed?
|
91
|
-
true
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# Makes specified socket persistent.
|
96
|
-
#
|
97
|
-
# Previous persistent socket will be closed as well.
|
98
|
-
def make_persistent!(socket)
|
99
|
-
unless socket == @socket
|
100
|
-
close_persistent!
|
101
|
-
@socket = socket
|
102
|
-
end
|
103
|
-
@socket
|
104
|
-
end
|
105
|
-
|
106
|
-
# Closes persistent socket.
|
107
|
-
def close_persistent!
|
108
|
-
free_socket(@socket, true)
|
109
|
-
end
|
110
|
-
|
111
|
-
# Gets a value indicating whether server has persistent socket associated.
|
112
|
-
def persistent?
|
113
|
-
!@socket.nil?
|
114
|
-
end
|
115
|
-
|
116
|
-
# Returns a string representation of the sphinx server object.
|
117
|
-
#
|
118
|
-
def to_s
|
119
|
-
@path || "#{@host}:#{@port}"
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns a string representation of the sphinx server object.
|
123
|
-
#
|
124
|
-
def inspect
|
125
|
-
"<Sphinx::Server: %s%s>" % [to_s, @socket ? '; persistent' : '']
|
126
|
-
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
# This is internal method which establishes a connection to a configured server.
|
131
|
-
#
|
132
|
-
# Method configures various socket options (like TCP_NODELAY), and
|
133
|
-
# sets socket timeouts.
|
134
|
-
#
|
135
|
-
# It does not close socket on any failure, please do it from calling code!
|
136
|
-
#
|
137
|
-
def establish_connection
|
138
|
-
if @path
|
139
|
-
sock = UNIXSocket.new(@path)
|
140
|
-
else
|
141
|
-
sock = TCPSocket.new(@host, @port)
|
142
|
-
end
|
143
|
-
|
144
|
-
io = Sphinx::BufferedIO.new(sock)
|
145
|
-
io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
146
|
-
if @sphinx.reqtimeout > 0
|
147
|
-
io.read_timeout = @sphinx.reqtimeout
|
148
|
-
|
149
|
-
# This is a part of memcache-client library.
|
150
|
-
#
|
151
|
-
# Getting reports from several customers, including 37signals,
|
152
|
-
# that the non-blocking timeouts in 1.7.5 don't seem to be reliable.
|
153
|
-
# It can't hurt to set the underlying socket timeout also, if possible.
|
154
|
-
secs = Integer(@sphinx.reqtimeout)
|
155
|
-
usecs = Integer((@sphinx.reqtimeout - secs) * 1_000_000)
|
156
|
-
optval = [secs, usecs].pack("l_2")
|
157
|
-
begin
|
158
|
-
io.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
|
159
|
-
io.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
|
160
|
-
rescue Exception => ex
|
161
|
-
# Solaris, for one, does not like/support socket timeouts.
|
162
|
-
@sphinx.logger.warn { "[sphinx] Unable to use raw socket timeouts: #{ex.class.name}: #{ex.message}" } if @sphinx.logger
|
163
|
-
end
|
164
|
-
else
|
165
|
-
io.read_timeout = false
|
166
|
-
end
|
167
|
-
|
168
|
-
io
|
169
|
-
end
|
170
|
-
end
|
data/lib/sphinx/timeout.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module Sphinx
|
2
|
-
begin
|
3
|
-
# Try to use the SystemTimer gem instead of Ruby's timeout library
|
4
|
-
# when running on something that looks like Ruby 1.8.x. See:
|
5
|
-
# http://ph7spot.com/articles/system_timer
|
6
|
-
# We don't want to bother trying to load SystemTimer on jruby and
|
7
|
-
# ruby 1.9+
|
8
|
-
if defined?(JRUBY_VERSION) || (RUBY_VERSION >= '1.9')
|
9
|
-
require 'timeout'
|
10
|
-
Timeout = ::Timeout
|
11
|
-
else
|
12
|
-
require 'system_timer'
|
13
|
-
Timeout = ::SystemTimer
|
14
|
-
end
|
15
|
-
rescue LoadError => e
|
16
|
-
puts "[sphinx] Could not load SystemTimer gem, falling back to Ruby's slower/unsafe timeout library: #{e.message}"
|
17
|
-
require 'timeout'
|
18
|
-
Timeout = ::Timeout
|
19
|
-
end
|
20
|
-
|
21
|
-
# Executes specified block respecting timeout passed.
|
22
|
-
#
|
23
|
-
# @private
|
24
|
-
def self.safe_execute(timeout = 5, &block)
|
25
|
-
if timeout > 0
|
26
|
-
Sphinx::Timeout.timeout(timeout, &block)
|
27
|
-
else
|
28
|
-
yield
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|