mogilefs-client 1.3.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/GNUmakefile +32 -0
- data/History.txt +23 -0
- data/LICENSE.txt +1 -0
- data/Manifest.txt +12 -1
- data/README.txt +22 -13
- data/bin/mog +37 -6
- data/lib/mogilefs.rb +19 -5
- data/lib/mogilefs/admin.rb +27 -34
- data/lib/mogilefs/backend.rb +106 -39
- data/lib/mogilefs/bigfile.rb +153 -0
- data/lib/mogilefs/client.rb +1 -5
- data/lib/mogilefs/httpfile.rb +65 -71
- data/lib/mogilefs/mogilefs.rb +102 -102
- data/lib/mogilefs/mysql.rb +166 -0
- data/lib/mogilefs/network.rb +64 -0
- data/lib/mogilefs/pool.rb +1 -1
- data/lib/mogilefs/util.rb +140 -9
- data/test/.gitignore +2 -0
- data/test/aggregate.rb +13 -0
- data/test/setup.rb +72 -91
- data/test/test_admin.rb +2 -2
- data/test/test_backend.rb +100 -38
- data/test/test_bigfile.rb +48 -0
- data/test/test_client.rb +7 -2
- data/test/test_db_backend.rb +73 -0
- data/test/test_mogilefs.rb +287 -107
- data/test/test_mysql.rb +94 -0
- data/test/test_network.rb +27 -0
- data/test/test_util.rb +59 -0
- metadata +22 -6
- data/lib/mogilefs/nfsfile.rb +0 -81
data/lib/mogilefs/mogilefs.rb
CHANGED
@@ -1,27 +1,13 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'net/http'
|
3
|
-
require 'timeout'
|
4
|
-
|
5
1
|
require 'mogilefs/client'
|
6
|
-
require 'mogilefs/nfsfile'
|
7
2
|
require 'mogilefs/util'
|
8
3
|
|
9
|
-
##
|
10
|
-
# Timeout error class.
|
11
|
-
|
12
|
-
class MogileFS::Timeout < Timeout::Error; end
|
13
|
-
|
14
4
|
##
|
15
5
|
# MogileFS File manipulation client.
|
16
6
|
|
17
7
|
class MogileFS::MogileFS < MogileFS::Client
|
18
8
|
|
19
9
|
include MogileFS::Util
|
20
|
-
|
21
|
-
##
|
22
|
-
# The path to the local MogileFS mount point if you are using NFS mode.
|
23
|
-
|
24
|
-
attr_reader :root
|
10
|
+
include MogileFS::Bigfile
|
25
11
|
|
26
12
|
##
|
27
13
|
# The domain of keys for this MogileFS client.
|
@@ -33,20 +19,26 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
33
19
|
|
34
20
|
attr_accessor :get_file_data_timeout
|
35
21
|
|
22
|
+
##
|
23
|
+
# internal Regexp for matching an "HTTP 200 OK" head response
|
24
|
+
HTTP_200_OK = %r{\AHTTP/\d+\.\d+\s+200\s+}.freeze
|
25
|
+
|
36
26
|
##
|
37
27
|
# Creates a new MogileFS::MogileFS instance. +args+ must include a key
|
38
|
-
# :domain specifying the domain of this client.
|
39
|
-
# specify the root of the NFS file system.
|
28
|
+
# :domain specifying the domain of this client.
|
40
29
|
|
41
30
|
def initialize(args = {})
|
42
31
|
@domain = args[:domain]
|
43
|
-
@root = args[:root]
|
44
32
|
|
45
33
|
@get_file_data_timeout = 5
|
46
34
|
|
47
35
|
raise ArgumentError, "you must specify a domain" unless @domain
|
48
36
|
|
49
|
-
|
37
|
+
if @backend = args[:db_backend]
|
38
|
+
@readonly = true
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
50
42
|
end
|
51
43
|
|
52
44
|
##
|
@@ -62,7 +54,7 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
62
54
|
keys, after = list_keys prefix, after
|
63
55
|
end
|
64
56
|
|
65
|
-
|
57
|
+
nil
|
66
58
|
end
|
67
59
|
|
68
60
|
##
|
@@ -78,23 +70,10 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
78
70
|
case path
|
79
71
|
when /^http:\/\// then
|
80
72
|
begin
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
timeout @get_file_data_timeout, MogileFS::Timeout do
|
86
|
-
sock = TCPSocket.new(path.host, path.port)
|
87
|
-
sock.sync = true
|
88
|
-
sock.syswrite("GET #{path.request_uri} HTTP/1.0\r\n\r\n")
|
89
|
-
buf = sock.recv(4096, Socket::MSG_PEEK)
|
90
|
-
head, body = buf.split(/\r\n\r\n/, 2)
|
91
|
-
head = sock.recv(head.size + 4)
|
92
|
-
end
|
93
|
-
return yield(sock)
|
94
|
-
else
|
95
|
-
return path.read
|
96
|
-
end
|
97
|
-
rescue MogileFS::Timeout
|
73
|
+
sock = http_get_sock(URI.parse(path))
|
74
|
+
return block_given? ? yield(sock) : sock.read
|
75
|
+
rescue MogileFS::Timeout, Errno::ECONNREFUSED,
|
76
|
+
EOFError, SystemCallError, MogileFS::InvalidResponseError
|
98
77
|
next
|
99
78
|
end
|
100
79
|
else
|
@@ -103,22 +82,18 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
103
82
|
end
|
104
83
|
end
|
105
84
|
|
106
|
-
|
85
|
+
nil
|
107
86
|
end
|
108
87
|
|
109
88
|
##
|
110
89
|
# Get the paths for +key+.
|
111
90
|
|
112
91
|
def get_paths(key, noverify = true, zone = nil)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
paths = (1..res['paths'].to_i).map { |i| res["path#{i}"] }
|
119
|
-
return paths if paths.empty?
|
120
|
-
return paths if paths.first =~ /^http:\/\//
|
121
|
-
return paths.map { |path| File.join @root, path }
|
92
|
+
opts = { :domain => @domain, :key => key,
|
93
|
+
:noverify => noverify ? 1 : 0, :zone => zone }
|
94
|
+
@backend.respond_to?(:_get_paths) and return @backend._get_paths(opts)
|
95
|
+
res = @backend.get_paths(opts)
|
96
|
+
(1..res['paths'].to_i).map { |i| res["path#{i}"] }
|
122
97
|
end
|
123
98
|
|
124
99
|
##
|
@@ -126,41 +101,35 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
126
101
|
#
|
127
102
|
# The +block+ operates like File.open.
|
128
103
|
|
129
|
-
def new_file(key, klass, bytes = 0, &block) # :yields: file
|
130
|
-
raise
|
131
|
-
|
132
|
-
|
133
|
-
|
104
|
+
def new_file(key, klass = nil, bytes = 0, &block) # :yields: file
|
105
|
+
raise MogileFS::ReadOnlyError if readonly?
|
106
|
+
opts = { :domain => @domain, :key => key, :multi_dest => 1 }
|
107
|
+
opts[:class] = klass if klass
|
108
|
+
res = @backend.create_open(opts)
|
134
109
|
|
135
|
-
|
136
|
-
|
137
|
-
dests = nil
|
138
|
-
|
139
|
-
if res.include? 'dev_count' then # HACK HUH?
|
140
|
-
dests = (1..res['dev_count'].to_i).map do |i|
|
110
|
+
dests = if dev_count = res['dev_count'] # multi_dest succeeded
|
111
|
+
(1..dev_count.to_i).map do |i|
|
141
112
|
[res["devid_#{i}"], res["path_#{i}"]]
|
142
113
|
end
|
143
|
-
else
|
114
|
+
else # single destination returned
|
144
115
|
# 0x0040: d0e4 4f4b 2064 6576 6964 3d31 2666 6964 ..OK.devid=1&fid
|
145
116
|
# 0x0050: 3d33 2670 6174 683d 6874 7470 3a2f 2f31 =3&path=http://1
|
146
117
|
# 0x0060: 3932 2e31 3638 2e31 2e37 323a 3735 3030 92.168.1.72:7500
|
147
118
|
# 0x0070: 2f64 6576 312f 302f 3030 302f 3030 302f /dev1/0/000/000/
|
148
119
|
# 0x0080: 3030 3030 3030 3030 3033 2e66 6964 0d0a 0000000003.fid..
|
149
120
|
|
150
|
-
|
121
|
+
[[res['devid'], res['path']]]
|
151
122
|
end
|
152
123
|
|
153
|
-
|
154
|
-
devid, path = dest
|
155
|
-
|
156
|
-
case path
|
124
|
+
case (dests[0][1] rescue nil)
|
157
125
|
when nil, '' then
|
158
|
-
raise
|
126
|
+
raise MogileFS::EmptyPathError
|
159
127
|
when /^http:\/\// then
|
160
|
-
MogileFS::HTTPFile.open(self, res['fid'],
|
128
|
+
MogileFS::HTTPFile.open(self, res['fid'], klass, key,
|
161
129
|
dests, bytes, &block)
|
162
130
|
else
|
163
|
-
MogileFS::
|
131
|
+
raise MogileFS::UnsupportedPathError,
|
132
|
+
"paths '#{dests.inspect}' returned by backend is not supported"
|
164
133
|
end
|
165
134
|
end
|
166
135
|
|
@@ -169,15 +138,15 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
169
138
|
# either a file name or an object that responds to #read.
|
170
139
|
|
171
140
|
def store_file(key, klass, file)
|
172
|
-
raise
|
141
|
+
raise MogileFS::ReadOnlyError if readonly?
|
173
142
|
|
174
143
|
new_file key, klass do |mfp|
|
175
144
|
if file.respond_to? :sysread then
|
176
145
|
return sysrwloop(file, mfp)
|
177
146
|
else
|
178
147
|
if File.size(file) > 0x10000 # Bigass file, handle differently
|
179
|
-
mfp.
|
180
|
-
return
|
148
|
+
mfp.big_io = file
|
149
|
+
return
|
181
150
|
else
|
182
151
|
return File.open(file) { |fp| sysrwloop(fp, mfp) }
|
183
152
|
end
|
@@ -189,26 +158,22 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
189
158
|
# Stores +content+ into +key+ in class +klass+.
|
190
159
|
|
191
160
|
def store_content(key, klass, content)
|
192
|
-
raise
|
161
|
+
raise MogileFS::ReadOnlyError if readonly?
|
193
162
|
|
194
163
|
new_file key, klass do |mfp|
|
195
164
|
mfp << content
|
196
165
|
end
|
197
166
|
|
198
|
-
|
167
|
+
content.length
|
199
168
|
end
|
200
169
|
|
201
170
|
##
|
202
171
|
# Removes +key+.
|
203
172
|
|
204
173
|
def delete(key)
|
205
|
-
raise
|
174
|
+
raise MogileFS::ReadOnlyError if readonly?
|
206
175
|
|
207
|
-
|
208
|
-
|
209
|
-
if res.nil? and @backend.lasterr != 'unknown_key' then
|
210
|
-
raise "unable to delete #{key}: #{@backend.lasterr}"
|
211
|
-
end
|
176
|
+
@backend.delete :domain => @domain, :key => key
|
212
177
|
end
|
213
178
|
|
214
179
|
##
|
@@ -222,40 +187,43 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
222
187
|
# Renames a key +from+ to key +to+.
|
223
188
|
|
224
189
|
def rename(from, to)
|
225
|
-
raise
|
226
|
-
|
227
|
-
res = @backend.rename :domain => @domain, :from_key => from, :to_key => to
|
190
|
+
raise MogileFS::ReadOnlyError if readonly?
|
228
191
|
|
229
|
-
|
230
|
-
|
231
|
-
end
|
192
|
+
@backend.rename :domain => @domain, :from_key => from, :to_key => to
|
193
|
+
nil
|
232
194
|
end
|
233
195
|
|
234
196
|
##
|
235
197
|
# Returns the size of +key+.
|
236
198
|
def size(key)
|
237
|
-
|
238
|
-
|
239
|
-
|
199
|
+
@backend.respond_to?(:_size) and return @backend._size(domain, key)
|
200
|
+
paths = get_paths(key) or return nil
|
201
|
+
paths_size(paths)
|
202
|
+
end
|
240
203
|
|
204
|
+
def paths_size(paths)
|
241
205
|
paths.each do |path|
|
242
206
|
next unless path
|
243
207
|
case path
|
244
208
|
when /^http:\/\// then
|
245
209
|
begin
|
246
210
|
url = URI.parse path
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
res =
|
251
|
-
|
252
|
-
|
211
|
+
s = Socket.mogilefs_new_request(url.host, url.port,
|
212
|
+
"HEAD #{url.request_uri} HTTP/1.0\r\n\r\n",
|
213
|
+
@get_file_data_timeout)
|
214
|
+
res = s.recv(4096, 0)
|
215
|
+
if res =~ HTTP_200_OK
|
216
|
+
head, body = res.split(/\r\n\r\n/, 2)
|
217
|
+
if head =~ /^Content-Length:\s*(\d+)/i
|
218
|
+
return $1.to_i
|
253
219
|
end
|
254
220
|
end
|
255
|
-
|
256
|
-
return res['Content-Length'].to_i
|
257
|
-
rescue MogileFS::Timeout
|
258
221
|
next
|
222
|
+
rescue MogileFS::Timeout, Errno::ECONNREFUSED,
|
223
|
+
EOFError, SystemCallError
|
224
|
+
next
|
225
|
+
ensure
|
226
|
+
s.close rescue nil
|
259
227
|
end
|
260
228
|
else
|
261
229
|
next unless File.exist? path
|
@@ -263,23 +231,55 @@ class MogileFS::MogileFS < MogileFS::Client
|
|
263
231
|
end
|
264
232
|
end
|
265
233
|
|
266
|
-
|
234
|
+
nil
|
267
235
|
end
|
268
236
|
|
269
237
|
##
|
270
238
|
# Lists keys starting with +prefix+ follwing +after+ up to +limit+. If
|
271
239
|
# +after+ is nil the list starts at the beginning.
|
272
240
|
|
273
|
-
def list_keys(prefix, after = nil, limit = 1000)
|
274
|
-
|
275
|
-
|
241
|
+
def list_keys(prefix, after = nil, limit = 1000, &block)
|
242
|
+
if @backend.respond_to?(:_list_keys)
|
243
|
+
return @backend._list_keys(domain, prefix, after, limit, &block)
|
244
|
+
end
|
276
245
|
|
277
|
-
|
246
|
+
res = begin
|
247
|
+
@backend.list_keys(:domain => domain, :prefix => prefix,
|
248
|
+
:after => after, :limit => limit)
|
249
|
+
rescue MogileFS::Backend::NoneMatchError
|
250
|
+
return nil
|
251
|
+
end
|
278
252
|
|
279
253
|
keys = (1..res['key_count'].to_i).map { |i| res["key_#{i}"] }
|
254
|
+
if block_given?
|
255
|
+
# emulate the MogileFS::Mysql interface, slowly...
|
256
|
+
keys.each do |key|
|
257
|
+
paths = get_paths(key) or next
|
258
|
+
length = paths_size(paths) or next
|
259
|
+
yield key, length, paths.size
|
260
|
+
end
|
261
|
+
end
|
280
262
|
|
281
|
-
|
263
|
+
[ keys, res['next_after'] ]
|
282
264
|
end
|
283
265
|
|
266
|
+
protected
|
267
|
+
|
268
|
+
# given a URI, this returns a readable socket with ready data from the
|
269
|
+
# body of the response.
|
270
|
+
def http_get_sock(uri)
|
271
|
+
sock = Socket.mogilefs_new_request(uri.host, uri.port,
|
272
|
+
"GET #{uri.request_uri} HTTP/1.0\r\n\r\n",
|
273
|
+
@get_file_data_timeout)
|
274
|
+
buf = sock.recv(4096, Socket::MSG_PEEK)
|
275
|
+
head, body = buf.split(/\r\n\r\n/, 2)
|
276
|
+
if head =~ HTTP_200_OK
|
277
|
+
sock.recv(head.size + 4, 0)
|
278
|
+
return sock
|
279
|
+
end
|
280
|
+
raise MogileFS::InvalidResponseError,
|
281
|
+
"GET on #{uri} returned: #{head.inspect}"
|
282
|
+
end # def http_get_sock
|
283
|
+
|
284
284
|
end
|
285
285
|
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'mogilefs'
|
2
|
+
require 'mogilefs/backend' # for the exceptions
|
3
|
+
|
4
|
+
# read-only interface that can be a backend for MogileFS::MogileFS
|
5
|
+
#
|
6
|
+
# This provides direct, read-only access to any slave MySQL database to
|
7
|
+
# provide better performance, scalability and eliminate mogilefsd as a
|
8
|
+
# point of failure
|
9
|
+
class MogileFS::Mysql
|
10
|
+
|
11
|
+
attr_reader :my
|
12
|
+
attr_reader :query_method
|
13
|
+
|
14
|
+
##
|
15
|
+
# Creates a new MogileFS::Mysql instance. +args+ must include a key
|
16
|
+
# :domain specifying the domain of this client and :mysql, specifying
|
17
|
+
# an already-initialized Mysql object.
|
18
|
+
#
|
19
|
+
# The Mysql object can be either the standard Mysql driver or the
|
20
|
+
# Mysqlplus one supporting c_async_query.
|
21
|
+
def initialize(args = {})
|
22
|
+
@my = args[:mysql]
|
23
|
+
@query_method = @my.respond_to?(:c_async_query) ? :c_async_query : :query
|
24
|
+
@last_update_device = @last_update_domain = Time.at(0)
|
25
|
+
@cache_domain = @cache_device = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Lists keys starting with +prefix+ follwing +after+ up to +limit+. If
|
30
|
+
# +after+ is nil the list starts at the beginning.
|
31
|
+
def _list_keys(domain, prefix = '', after = '', limit = 1000, &block)
|
32
|
+
# this code is based on server/lib/MogileFS/Worker/Query.pm
|
33
|
+
dmid = get_dmid(domain)
|
34
|
+
|
35
|
+
# don't modify passed arguments
|
36
|
+
limit ||= 1000
|
37
|
+
limit = limit.to_i
|
38
|
+
limit = 1000 if limit > 1000 || limit <= 0
|
39
|
+
after, prefix = "#{after}", "#{prefix}"
|
40
|
+
|
41
|
+
if after.length > 0 && /^#{Regexp.quote(prefix)}/ !~ after
|
42
|
+
raise MogileFS::Backend::AfterMismatchError
|
43
|
+
end
|
44
|
+
|
45
|
+
raise MogileFS::Backend::InvalidCharsError if /[%\\]/ =~ prefix
|
46
|
+
prefix.gsub!(/_/, '\_') # not sure why MogileFS::Worker::Query does this...
|
47
|
+
|
48
|
+
sql = <<-EOS
|
49
|
+
SELECT dkey,length,devcount FROM file
|
50
|
+
WHERE dmid = #{dmid}
|
51
|
+
AND dkey LIKE '#{@my.quote(prefix)}%'
|
52
|
+
AND dkey > '#{@my.quote(after)}'
|
53
|
+
ORDER BY dkey LIMIT #{limit}
|
54
|
+
EOS
|
55
|
+
|
56
|
+
keys = []
|
57
|
+
query(sql).each do |dkey,length,devcount|
|
58
|
+
yield(dkey, length, devcount) if block_given?
|
59
|
+
keys << dkey
|
60
|
+
end
|
61
|
+
|
62
|
+
keys.empty? ? nil : [ keys, (keys.last || '') ]
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Returns the size of +key+.
|
67
|
+
def _size(domain, key)
|
68
|
+
dmid = get_dmid(domain)
|
69
|
+
|
70
|
+
sql = <<-EOS
|
71
|
+
SELECT length FROM file
|
72
|
+
WHERE dmid = #{dmid} AND dkey = '#{@my.quote(key)}'
|
73
|
+
LIMIT 1
|
74
|
+
EOS
|
75
|
+
|
76
|
+
res = query(sql).fetch_row
|
77
|
+
return res[0].to_i if res && res[0]
|
78
|
+
raise MogileFS::Backend::UnknownKeyError
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Get the paths for +key+.
|
83
|
+
def _get_paths(params = {})
|
84
|
+
zone = params[:zone]
|
85
|
+
noverify = (params[:noverify] == 1) # TODO this is unused atm
|
86
|
+
dmid = get_dmid(params[:domain])
|
87
|
+
devices = refresh_device or raise MogileFS::Backend::NoDevicesError
|
88
|
+
urls = []
|
89
|
+
sql = <<-EOS
|
90
|
+
SELECT fid FROM file
|
91
|
+
WHERE dmid = #{dmid} AND dkey = '#{@my.quote(params[:key])}'
|
92
|
+
LIMIT 1
|
93
|
+
EOS
|
94
|
+
|
95
|
+
res = query(sql).fetch_row
|
96
|
+
res && res[0] or raise MogileFS::Backend::UnknownKeyError
|
97
|
+
fid = res[0]
|
98
|
+
sql = "SELECT devid FROM file_on WHERE fid = '#{@my.quote(fid)}'"
|
99
|
+
query(sql).each do |devid,|
|
100
|
+
unless devinfo = devices[devid.to_i]
|
101
|
+
devices = refresh_device(true)
|
102
|
+
devinfo = devices[devid.to_i] or next
|
103
|
+
end
|
104
|
+
|
105
|
+
port = devinfo[:http_get_port]
|
106
|
+
host = zone && zone == 'alt' ? devinfo[:altip] : devinfo[:hostip]
|
107
|
+
nfid = '%010u' % fid
|
108
|
+
b, mmm, ttt = /(\d)(\d{3})(\d{3})(?:\d{3})/.match(nfid)[1..3]
|
109
|
+
uri = "/dev#{devid}/#{b}/#{mmm}/#{ttt}/#{nfid}.fid"
|
110
|
+
urls << "http://#{host}:#{port}#{uri}"
|
111
|
+
end
|
112
|
+
urls
|
113
|
+
end
|
114
|
+
|
115
|
+
def sleep(params); Kernel.sleep(params[:duration] || 10); {}; end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
unless defined? GET_DEVICES
|
120
|
+
GET_DOMAINS = 'SELECT dmid,namespace FROM domain'.freeze
|
121
|
+
|
122
|
+
GET_DEVICES = <<-EOS
|
123
|
+
SELECT d.devid, h.hostip, h.altip, h.http_port, h.http_get_port
|
124
|
+
FROM device d
|
125
|
+
LEFT JOIN host h ON d.hostid = h.hostid
|
126
|
+
WHERE d.status IN ('alive','readonly','drain');
|
127
|
+
EOS
|
128
|
+
GET_DEVICES.freeze
|
129
|
+
end
|
130
|
+
|
131
|
+
def query(sql)
|
132
|
+
@my.send(@query_method, sql)
|
133
|
+
end
|
134
|
+
|
135
|
+
def refresh_device(force = false)
|
136
|
+
return @cache_device if ! force && ((Time.now - @last_update_device) < 60)
|
137
|
+
tmp = {}
|
138
|
+
res = query(GET_DEVICES)
|
139
|
+
res.each do |devid, hostip, altip, http_port, http_get_port|
|
140
|
+
http_port = http_port ? http_port.to_i : 80
|
141
|
+
tmp[devid.to_i] = {
|
142
|
+
:hostip => hostip.freeze,
|
143
|
+
:altip => (altip || hostip).freeze,
|
144
|
+
:http_port => http_port,
|
145
|
+
:http_get_port => http_get_port ? http_get_port.to_i : http_port,
|
146
|
+
}.freeze
|
147
|
+
end
|
148
|
+
@last_update_device = Time.now
|
149
|
+
@cache_device = tmp.freeze
|
150
|
+
end
|
151
|
+
|
152
|
+
def refresh_domain(force = false)
|
153
|
+
return @cache_domain if ! force && ((Time.now - @last_update_domain) < 5)
|
154
|
+
tmp = {}
|
155
|
+
res = query(GET_DOMAINS)
|
156
|
+
res.each { |dmid,namespace| tmp[namespace] = dmid.to_i }
|
157
|
+
@last_update_domain = Time.now
|
158
|
+
@cache_domain = tmp.freeze
|
159
|
+
end
|
160
|
+
|
161
|
+
def get_dmid(domain)
|
162
|
+
refresh_domain[domain] || refresh_domain(true)[domain] or \
|
163
|
+
raise MogileFS::Backend::DomainNotFoundError, domain
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|