класс DRb::DRbServer
Class представляющий экземпляр сервера drb.
Сервер DRbServer должен работать в локальном процессе, прежде чем будут приняты любые входящие вызовы dRuby или локальные объекты могут быть переданы как ссылки dRuby в удаленные процессы, даже если эти локальные объекты никогда фактически не вызываются удаленно. Вам не нужно запускать DRbServer в локальном процессе, если вы только выполняете исходящие вызовы dRuby, передавая сериализованные параметры.
Если не используется несколько серверов, локальный DRbServer обычно запускается путем вызова DRb.start_service.
Константы
- INSECURE_METHOD
-
Список небезопасных методов.
Эти методы недоступны для вызова через dRuby.
Атрибуты
Настройка этого DRbServer.
Объект front объекта DRbServer.
Этот объект получает удалённые вызовы методов, сделанные на сервере, только по URI, с идентификатором объекта.
Основной поток этого DRbServer.
Это поток, который слушает и принимает подключения от клиентов, а не тот, который обрабатывает сессии запроса-ответа каждого клиента.
URI этого DRbServer.
Публичные методы класса
# File lib/drb/drb.rb, line 1374 def self.default_acl(acl) @@acl = acl end
Set список контроля доступа по умолчанию на acl. Список контроля доступа по умолчанию — nil.
См. также DRb::ACL и new()
# File lib/drb/drb.rb, line 1360 def self.default_argc_limit(argc) @@argc_limit = argc end
Set значение по умолчанию для параметра :argc_limit.
См. new(). Начальное значение по умолчанию — 256.
# File lib/drb/drb.rb, line 1367 def self.default_load_limit(sz) @@load_limit = sz end
Set значение по умолчанию для параметра :load_limit.
См. new(). Начальное значение по умолчанию — 25 МБ.
# File lib/drb/drb.rb, line 1450
def initialize(uri=nil, front=nil, config_or_acl=nil)
if Hash === config_or_acl
config = config_or_acl.dup
else
acl = config_or_acl || @@acl
config = {
:tcp_acl => acl
}
end
@config = self.class.make_config(config)
@protocol = DRbProtocol.open_server(uri, @config)
@uri = @protocol.uri
@exported_uri = [@uri]
@front = front
@idconv = @config[:idconv]
@grp = ThreadGroup.new
@thread = run
DRb.regist_server(self)
end Создать новый экземпляр DRbServer.
uri — URI для привязки. Обычно имеет вид 'druby://<hostname>:<port>', где <hostname> — имя хоста локальной машины. Если nil, то будет привязано к системному имени хоста на порте, выбранном системой; эти значения можно получить из атрибута uri. 'druby:' указывает на стандартный протокол dRuby: можно указать другой протокол, например 'drbunix:'.
front — объект front для сервера, то есть объект, которому будут передаваться удалённые вызовы методов на сервере. Если nil, то сервер не будет принимать удалённые вызовы методов.
Если config_or_acl — хэш, это конфигурация для использования на этом сервере. Признаются следующие параметры:
- :idconv
-
объект преобразования id-в-объект. По умолчанию — экземпляр класса
DRb::DRbIdConv. - :verbose
-
если true, все неуспешные удалённые вызовы методов объектов на сервере будут регистрироваться в $stdout. По умолчанию false.
- :tcp_acl
-
список контроля доступа для этого сервера. См. класс
ACLиз основного дистрибутива dRuby. - :load_limit
-
максимальный размер сообщения в байтах, принимаемый сервером. По умолчанию 25 МБ (26214400).
- :argc_limit
-
максимальное количество аргументов удалённого метода, принимаемых сервером. По умолчанию 256.
Значения этих параметров по умолчанию можно изменить на уровне класса методами default_argc_limit, default_load_limit, default_acl, default_id_conv и verbose=
Если config_or_acl не хэш, но не nil, он считается списком контроля доступа для этого сервера. См. параметр :tcp_acl для получения подробностей.
Если ни один другой сервер не установлен в качестве основного сервера, этот сервер станет основным.
Сервер начнёт работать немедленно в собственном потоке.
# File lib/drb/drb.rb, line 1393 def self.verbose @@verbose end
Получить значение параметра :verbose по умолчанию.
# File lib/drb/drb.rb, line 1388 def self.verbose=(on) @@verbose = on end
Set значение параметра :verbose по умолчанию.
См. new(). Начальное значение по умолчанию — false.
Публичные методы экземпляра
# File lib/drb/drb.rb, line 1505 def alive? @thread.alive? end
Является ли этот сервер активным?
# File lib/drb/drb.rb, line 1593
def check_insecure_method(obj, msg_id)
return true if Proc === obj && msg_id == :__drb_yield
raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
case obj
when Object
if obj.private_methods.include?(msg_id)
desc = any_to_s(obj)
raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
elsif obj.protected_methods.include?(msg_id)
desc = any_to_s(obj)
raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
else
true
end
else
if Kernel.instance_method(:private_methods).bind(obj).call.include?(msg_id)
desc = any_to_s(obj)
raise NoMethodError, "private method `#{msg_id}' called for #{desc}"
elsif Kernel.instance_method(:protected_methods).bind(obj).call.include?(msg_id)
desc = any_to_s(obj)
raise NoMethodError, "protected method `#{msg_id}' called for #{desc}"
else
true
end
end
end Проверить, доступен ли метод для вызова через dRuby.
obj — объект, на котором мы хотим вызвать метод. msg_id — имя метода, как Symbol.
Если метод небезопасен (см. insecure_method?), вызывается SecurityError. Если метод является закрытым или не определён, вызывается NameError.
# File lib/drb/drb.rb, line 1510 def here?(uri) @exported_uri.include?(uri) end
Является ли uri URI для этого сервера?
# File lib/drb/drb.rb, line 1515
def stop_service
DRb.remove_server(self)
if Thread.current['DRb'] && Thread.current['DRb']['server'] == self
Thread.current['DRb']['stop_service'] = true
else
shutdown
end
end Остановить этот сервер.
# File lib/drb/drb.rb, line 1532 def to_id(obj) return nil if obj.__id__ == front.__id__ @idconv.to_id(obj) end
Преобразовать локальный объект в ссылку dRuby.
# File lib/drb/drb.rb, line 1525 def to_obj(ref) return front if ref.nil? return front[ref.to_s] if DRbURIOption === ref @idconv.to_obj(ref) end
Преобразовать ссылку dRuby в локальный объект, на который она ссылается.
# File lib/drb/drb.rb, line 1502 def verbose; @config[:verbose]; end
Получить режим подробного вывода сервера.
В режиме подробного вывода неудачные вызовы регистрируются в stdout.
# File lib/drb/drb.rb, line 1497 def verbose=(v); @config[:verbose]=v; end
Set режим подробного вывода.
В режиме подробного вывода неудачные вызовы регистрируются в stdout.
Методы частного экземпляра
# File lib/drb/drb.rb, line 1579
def any_to_s(obj)
"#{obj}:#{obj.class}"
rescue
Kernel.instance_method(:to_s).bind_call(obj)
end Преобразовать объект в строку, предоставив собственное представление, если для объекта не определен метод to_s.
# File lib/drb/drb.rb, line 1692
def error_print(exception)
exception.backtrace.inject(true) do |first, x|
if first
$stderr.puts "#{x}: #{exception} (#{exception.class})"
else
$stderr.puts "\tfrom #{x}"
end
false
end
end # File lib/drb/drb.rb, line 1573 def insecure_method?(msg_id) INSECURE_METHOD.include?(msg_id) end
Метод включён в список небезопасных методов?
# File lib/drb/drb.rb, line 1710
def main_loop
client0 = @protocol.accept
return nil if !client0
Thread.start(client0) do |client|
@grp.add Thread.current
Thread.current['DRb'] = { 'client' => client ,
'server' => self }
DRb.mutex.synchronize do
client_uri = client.uri
@exported_uri << client_uri unless @exported_uri.include?(client_uri)
end
loop do
begin
succ = false
invoke_method = InvokeMethod.new(self, client)
succ, result = invoke_method.perform
error_print(result) if !succ && verbose
unless DRbConnError === result && result.message == 'connection closed'
client.send_reply(succ, result)
end
rescue Exception => e
error_print(e) if verbose
ensure
client.close unless succ
if Thread.current['DRb']['stop_service']
shutdown
break
end
break unless succ
end
end
end
end Основной цикл, выполняемый внутренним потоком DRbServer.
Принимает подключение от клиента и запускает собственный поток для его обработки. Этот поток циклически получает запросы от клиента, вызывает их на локальном объекте и возвращает ответы до тех пор, пока клиент не закроет соединение или вызов локального метода не завершится ошибкой.
# File lib/drb/drb.rb, line 1554
def run
Thread.start do
begin
while main_loop
end
ensure
@protocol.close if @protocol
end
end
end Запускает основной цикл DRb в новом потоке.
# File lib/drb/drb.rb, line 1539
def shutdown
current = Thread.current
if @protocol.respond_to? :shutdown
@protocol.shutdown
else
[@thread, *@grp.list].each { |thread|
thread.kill unless thread == current # xxx: Thread#kill
}
end
@thread.join unless @thread == current
end
Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.