1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
require 'drb'
module God
# The God::Server oversees the DRb server which dishes out info on this God daemon.
class Socket
attr_reader :port
# The location of the socket for a given port
# +port+ is the port number
#
# Returns String (file location)
def self.socket_file(port)
"/tmp/god.#{port}.sock"
end
# The address of the socket for a given port
# +port+ is the port number
#
# Returns String (drb address)
def self.socket(port)
"drbunix://#{self.socket_file(port)}"
end
# The location of the socket for this Server
#
# Returns String (file location)
def socket_file
self.class.socket_file(@port)
end
# The address of the socket for this Server
#
# Returns String (drb address)
def socket
self.class.socket(@port)
end
# Create a new Server and star the DRb server
# +port+ is the port on which to start the DRb service (default nil)
def initialize(port = nil, user = nil, group = nil, perm = nil)
@port = port
@user = user
@group = group
@perm = perm
start
end
# Returns true
def ping
true
end
# Forward API calls to God
#
# Returns whatever the forwarded call returns
def method_missing(*args, &block)
God.send(*args, &block)
end
# Stop the DRb server and delete the socket file
#
# Returns nothing
def stop
DRb.stop_service
FileUtils.rm_f(self.socket_file)
end
private
# Start the DRb server. Abort if there is already a running god instance
# on the socket.
#
# Returns nothing
def start
begin
@drb ||= DRb.start_service(self.socket, self)
applog(nil, :info, "Started on #{DRb.uri}")
rescue Errno::EADDRINUSE
applog(nil, :info, "Socket already in use")
DRb.start_service
server = DRbObject.new(nil, self.socket)
begin
Timeout.timeout(5) do
server.ping
end
abort "Socket #{self.socket} already in use by another instance of god"
rescue StandardError, Timeout::Error
applog(nil, :info, "Socket is stale, reopening")
File.delete(self.socket_file) rescue nil
@drb ||= DRb.start_service(self.socket, self)
applog(nil, :info, "Started on #{DRb.uri}")
end
end
if File.exists?(self.socket_file)
uid = Etc.getpwnam(@user).uid if @user
gid = Etc.getgrnam(@group).gid if @group
File.chmod(Integer(@perm), socket_file) if @perm
File.chown(uid, gid, socket_file) if uid or gid
end
end
end
end
|