ruby-watchcat-pure 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/README +64 -0
  2. data/examples/example.rb +21 -0
  3. data/lib/watchcat.rb +142 -0
  4. metadata +57 -0
data/README ADDED
@@ -0,0 +1,64 @@
1
+ == Introduction
2
+
3
+ Ruby/Watchcat allows the development of watchcatd-aware applications in
4
+ Ruby.
5
+
6
+ Watchcatd is a watchdog-like daemon in the sense that it takes actions
7
+ in situations where a machine is under heavy load and/or unresponsive.
8
+ However, watchcatd isn't as drastic as the usual watchdog systems, which
9
+ generally reboot the machine. Instead, all it does is sending a signal to
10
+ a registered process (which by default is SIGKILL) if the process doesn't
11
+ send it a heartbeat before a user-specified timeout.
12
+
13
+ Ruby/Watchcatd allows a Ruby application to register itself with watchcatd.
14
+
15
+
16
+ == Requirements
17
+
18
+ Ruby/Watchcatd was tested with Ruby versions >= 1.8.4 and requires watchcatd
19
+ version 1.1 and libwcat version 1.0 to be installed (see References below).
20
+
21
+
22
+ == Installation
23
+
24
+ The easiest way to install Ruby/Watchcat is to use rubygems:
25
+
26
+ * For the C extension:
27
+ gem install ruby-watchcat
28
+
29
+ * For the pure-Ruby version:
30
+ gem install ruby-watchcat-pure
31
+
32
+ The C extension requires you to have the libwcat development package
33
+ installed.
34
+
35
+ == License
36
+
37
+ Copyright (c) 2006, 2007, 2008 Andre Nathan <andre@digirati.com.br>
38
+
39
+ Permission to use, copy, modify, and distribute this software for any
40
+ purpose with or without fee is hereby granted, provided that the above
41
+ copyright notice and this permission notice appear in all copies.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
44
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
45
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
46
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
47
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
48
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
49
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
50
+
51
+
52
+ == Author
53
+
54
+ Ruby/Watchcat was developed by Andre Nathan.
55
+
56
+
57
+ == References
58
+
59
+ * Ruby/Watchcat homepage:
60
+ http://oss.digirati.com.br/ruby-watchcat/
61
+ * Rubyforge project home:
62
+ http://www.rubyforge.org/projects/watchcat
63
+ * Watchcatd and libwcat:
64
+ http://oss.digirati.com.br/watchcatd/
@@ -0,0 +1,21 @@
1
+ require 'watchcat'
2
+
3
+ # Create a new cat.
4
+ cat = Watchcat.new(:timeout => 5, :signal => 'KILL', :info => 'rubykill!')
5
+ loop do
6
+ # Do something that might be slow.
7
+ sleep 4 + rand(3)
8
+ puts 'survived'
9
+ cat.heartbeat
10
+ end
11
+ cat.close # clean cat's litter box.
12
+
13
+ # If you call it with a block, the cat cleans its own litter box.
14
+ Watchcat.new do |cat|
15
+ loop do
16
+ # Do something that might be slow.
17
+ sleep 4 + rand(3)
18
+ puts 'survived'
19
+ cat.heartbeat
20
+ end
21
+ end
data/lib/watchcat.rb ADDED
@@ -0,0 +1,142 @@
1
+ #--
2
+ # Copyright (c) 2008 Andre Nathan <andre@digirati.com.br>
3
+ #
4
+ # Permission to use, copy, modify, and distribute this software for any
5
+ # purpose with or without fee is hereby granted, provided that the above
6
+ # copyright notice and this permission notice appear in all copies.
7
+ #
8
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ #
16
+ # $Id: watchcat.rb 24 2008-08-04 14:47:08Z andre $
17
+ #++
18
+
19
+ # Pure-ruby version of libwcat.
20
+
21
+ require 'fcntl'
22
+ require 'socket'
23
+
24
+ #
25
+ # == Overview
26
+ #
27
+ # Ruby/Watchcat is a library for the development of watchcatd-aware
28
+ # applications. It requires watchcatd to be installed and running, and
29
+ # communicates with it via UNIX sockets.
30
+ #
31
+ class Watchcat
32
+ DEFAULT_TIMEOUT = 60
33
+ DEFAULT_DEVICE = '/dev/watchcat'
34
+ DEFAULT_SIGNAL = Signal.list['KILL']
35
+
36
+ # Create a new Watchcat object. The parameter hash may have the following
37
+ # symbols:
38
+ # +timeout+::
39
+ # If watchcatd doesn't receive a heartbeat after this period (in seconds),
40
+ # it will signal the process. (default: 60)
41
+ # +signal+::
42
+ # Defines which signal will be sent to the process after the timeout
43
+ # expires. Can be a string like 'HUP' or 'SIGHUP' or an integer like 9.
44
+ # (default: 9)
45
+ # +info+::
46
+ # Should be a string which is added to the log generated by watchcatd
47
+ # when it signals a process. (default: nil)
48
+ # +device+::
49
+ # The watchcat device. (default: +/dev/watchcat+). Use for debugging
50
+ # purposes.
51
+ #
52
+ # If a block is given, the Watchcat object will be yielded and automatically
53
+ # closed on block termination.
54
+ def initialize(args = {}) # :yield:
55
+ timeout = args[:timeout] || DEFAULT_TIMEOUT
56
+ device = args[:device] || DEFAULT_DEVICE
57
+ info = args[:info] ? args[:info].to_s : ''
58
+
59
+ unless timeout.is_a? Fixnum
60
+ raise ArgumentError, 'timeout must be an integer'
61
+ end
62
+
63
+ case args[:signal]
64
+ when nil
65
+ signal = DEFAULT_SIGNAL
66
+ when String
67
+ signal = Signal.list[args[:signal].sub(/^SIG/, '')]
68
+ raise ArgumentError, "invalid signal name" if signal.nil?
69
+ when Fixnum
70
+ signal = args[:signal]
71
+ else
72
+ raise ArgumentError, "signal must be an integer or a string"
73
+ end
74
+
75
+ @sock = UNIXSocket.new(device)
76
+ if Fcntl.const_defined? :F_SETFD
77
+ @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
78
+ end
79
+
80
+ msg = "version: 1\ntimeout: #{timeout}\nsignal: #{signal}"
81
+ if info.nil?
82
+ msg << "\n\n"
83
+ else
84
+ info.gsub!(/\n/, '_')
85
+ msg << "\ninfo: #{info}\n\n"
86
+ end
87
+
88
+ safe_write(@sock, msg)
89
+ if safe_read(@sock, 256) == "ok\n"
90
+ if block_given?
91
+ begin
92
+ yield(self)
93
+ ensure
94
+ @sock.close
95
+ end
96
+ end
97
+ return self
98
+ else
99
+ @sock.close
100
+ # Probably not the best error, but it matches the C library.
101
+ raise Errno::EPERM
102
+ end
103
+ end
104
+
105
+ # Send a heartbeat to watchcatd, telling it we're still alive.
106
+ def heartbeat
107
+ safe_write(@sock, '.')
108
+ return nil
109
+ end
110
+
111
+ # Close communication with watchcatd.
112
+ def close
113
+ begin
114
+ @sock.close
115
+ rescue Errno::EINTR
116
+ retry
117
+ end
118
+ return nil
119
+ end
120
+
121
+ private
122
+
123
+ def safe_write(fd, buf)
124
+ act = Signal.trap('PIPE', 'IGN')
125
+ begin
126
+ fd.syswrite(buf)
127
+ rescue Errno::EINTR
128
+ retry
129
+ end
130
+ Signal.trap('PIPE', act)
131
+ end
132
+
133
+ def safe_read(fd, len)
134
+ buf = ''
135
+ begin
136
+ buf = fd.sysread(len)
137
+ rescue Errno::EINTR
138
+ retry
139
+ end
140
+ return buf
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-watchcat-pure
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andre Nathan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-06 00:00:00 -03:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Ruby/Watchcat-Pure is a pure-ruby implementation of libwatchcat for the development of watchcatd-aware applications.
17
+ email: andre@digirati.com.br
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - lib/watchcat.rb
27
+ - examples/example.rb
28
+ has_rdoc: true
29
+ homepage: http://watchcat.rubyforge.org
30
+ post_install_message:
31
+ rdoc_options:
32
+ - --title
33
+ - Ruby/Watchcat--main
34
+ - README
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements:
50
+ - watchcatd
51
+ rubyforge_project: ruby-watchcat
52
+ rubygems_version: 1.0.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: A pure-ruby implementation of libwatchcat
56
+ test_files: []
57
+