File: socket.rb

package info (click to toggle)
ruby-god 0.12.1-1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 752 kB
  • sloc: ruby: 5,913; ansic: 217; makefile: 3
file content (107 lines) | stat: -rw-r--r-- 2,691 bytes parent folder | download | duplicates (2)
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