ruby-watchcat 1.0.0 → 1.0.1
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.
- data/README +64 -0
- data/examples/example.rb +4 -0
- data/ext/extconf.rb +1 -0
- data/ext/watchcat.c +136 -85
- metadata +43 -32
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/
|
data/examples/example.rb
CHANGED
@@ -4,6 +4,8 @@ require 'watchcat'
|
|
4
4
|
cat = Watchcat.new(:timeout => 5, :signal => 'KILL', :info => 'rubykill!')
|
5
5
|
loop do
|
6
6
|
# Do something that might be slow.
|
7
|
+
sleep 4 + rand(3)
|
8
|
+
puts 'survived'
|
7
9
|
cat.heartbeat
|
8
10
|
end
|
9
11
|
cat.close # clean cat's litter box.
|
@@ -12,6 +14,8 @@ cat.close # clean cat's litter box.
|
|
12
14
|
Watchcat.new do |cat|
|
13
15
|
loop do
|
14
16
|
# Do something that might be slow.
|
17
|
+
sleep 4 + rand(3)
|
18
|
+
puts 'survived'
|
15
19
|
cat.heartbeat
|
16
20
|
end
|
17
21
|
end
|
data/ext/extconf.rb
CHANGED
data/ext/watchcat.c
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
* Copyright (c) 2006 Andre Nathan <andre@digirati.com.br>
|
1
|
+
/*--
|
2
|
+
* Copyright (c) 2006, 2007, 2008 Andre Nathan <andre@digirati.com.br>
|
3
3
|
*
|
4
4
|
* Permission to use, copy, modify, and distribute this software for any
|
5
5
|
* purpose with or without fee is hereby granted, provided that the above
|
@@ -13,111 +13,162 @@
|
|
13
13
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
14
14
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
15
15
|
*
|
16
|
-
* $Id: watchcat.c
|
16
|
+
* $Id: watchcat.c 21 2008-08-04 14:04:04Z andre $
|
17
|
+
*++
|
18
|
+
*/
|
19
|
+
|
20
|
+
/*
|
21
|
+
* Document-class: Watchcat
|
22
|
+
*
|
23
|
+
* == Overview
|
24
|
+
*
|
25
|
+
* Ruby/Watchcat is a library for the development of watchcatd-aware
|
26
|
+
* applications. It requires watchcatd to be installed and running, and
|
27
|
+
* communicates with it via UNIX sockets.
|
17
28
|
*
|
18
29
|
*/
|
30
|
+
|
19
31
|
#include <ruby.h>
|
20
32
|
#include <watchcat.h>
|
21
33
|
|
34
|
+
#define SYMBOL(s) ID2SYM(rb_intern(s))
|
35
|
+
|
36
|
+
/*
|
37
|
+
* call-seq:
|
38
|
+
* Watchcat.new([options]) => watchcat_obj
|
39
|
+
* Watchcat.new([options]) { |watchcat| block } => watchcat_obj
|
40
|
+
*
|
41
|
+
* Create a new Watchcat object. The parameter hash may have the following
|
42
|
+
* symbols:
|
43
|
+
* +timeout+::
|
44
|
+
* If watchcatd doesn't receive a heartbeat after this period (in seconds),
|
45
|
+
* it will signal the process. (default: 60)
|
46
|
+
* +signal+::
|
47
|
+
* Defines which signal will be sent to the process after the timeout
|
48
|
+
* expires. Can be a string like 'HUP' or 'SIGHUP' or an integer like 9.
|
49
|
+
* (default: 9)
|
50
|
+
* +info+::
|
51
|
+
* Should be a string which is added to the log generated by watchcatd
|
52
|
+
* when it signals a process. (default: nil)
|
53
|
+
* +device+::
|
54
|
+
* The watchcat device. (default: +/dev/watchcat+). Use for debugging
|
55
|
+
* purposes.
|
56
|
+
*
|
57
|
+
* If a block is given, the Watchcat object will be yielded and automatically
|
58
|
+
* closed on block termination.
|
59
|
+
*/
|
22
60
|
static VALUE
|
23
61
|
rb_wcat_open(int argc, VALUE *argv, VALUE self)
|
24
62
|
{
|
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
|
-
|
63
|
+
int sock, timeout, signal;
|
64
|
+
char *signame;
|
65
|
+
const char *info;
|
66
|
+
VALUE opt, vtimeout, vsignal, vinfo, vdevice, vsiglist, mSignal;
|
67
|
+
|
68
|
+
rb_scan_args(argc, argv, "01", &opt);
|
69
|
+
if (NIL_P(opt)) {
|
70
|
+
sock = cat_open();
|
71
|
+
if (sock == -1)
|
72
|
+
rb_sys_fail("cat_open");
|
73
|
+
rb_iv_set(self, "@sock", INT2NUM(sock));
|
74
|
+
return(self);
|
75
|
+
}
|
76
|
+
|
77
|
+
/* Defaults. */
|
78
|
+
timeout = 60;
|
79
|
+
signal = SIGKILL;
|
80
|
+
info = NULL;
|
81
|
+
|
82
|
+
vtimeout = rb_hash_aref(opt, SYMBOL("timeout"));
|
83
|
+
if (!NIL_P(vtimeout)) {
|
84
|
+
if (FIXNUM_P(vtimeout))
|
85
|
+
timeout = NUM2INT(vtimeout);
|
86
|
+
else
|
87
|
+
rb_raise(rb_eArgError, "timeout must be an integer");
|
88
|
+
}
|
89
|
+
|
90
|
+
vsignal = rb_hash_aref(opt, SYMBOL("signal"));
|
91
|
+
if (!NIL_P(vsignal)) {
|
92
|
+
switch (TYPE(vsignal)) {
|
93
|
+
case T_FIXNUM:
|
94
|
+
signal = NUM2INT(vsignal);
|
95
|
+
break;
|
96
|
+
case T_STRING:
|
97
|
+
signame = StringValuePtr(vsignal);
|
98
|
+
if (strncmp("SIG", signame, 3) == 0) {
|
99
|
+
signame += 3;
|
100
|
+
vsignal = rb_str_new2(signame);
|
101
|
+
}
|
102
|
+
mSignal = rb_const_get(rb_cObject, rb_intern("Signal"));
|
103
|
+
vsiglist = rb_funcall(mSignal, rb_intern("list"), 0);
|
104
|
+
vsignal = rb_hash_aref(vsiglist, vsignal);
|
105
|
+
if (NIL_P(vsignal))
|
106
|
+
rb_raise(rb_eArgError, "invalid signal name");
|
107
|
+
else
|
108
|
+
signal = NUM2INT(vsignal);
|
109
|
+
break;
|
110
|
+
default:
|
111
|
+
rb_raise(rb_eArgError, "signal must be an integer or a string");
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
vinfo = rb_hash_aref(opt, SYMBOL("info"));
|
116
|
+
if (!NIL_P(vinfo))
|
117
|
+
info = StringValuePtr(vinfo);
|
118
|
+
|
119
|
+
vdevice = rb_hash_aref(opt, SYMBOL("device"));
|
120
|
+
if (!NIL_P(vdevice))
|
121
|
+
cat_set_device(StringValuePtr(vdevice));
|
122
|
+
|
123
|
+
sock = cat_open1(timeout, signal, info);
|
124
|
+
if (sock == -1)
|
125
|
+
rb_sys_fail("cat_open");
|
126
|
+
|
127
|
+
rb_iv_set(self, "@sock", INT2NUM(sock));
|
128
|
+
|
129
|
+
if (rb_block_given_p())
|
130
|
+
rb_ensure(rb_yield, self, (void *)cat_close, sock);
|
131
|
+
|
132
|
+
return(self);
|
94
133
|
}
|
95
134
|
|
135
|
+
/*
|
136
|
+
* call-seq:
|
137
|
+
* cat.heartbeat
|
138
|
+
*
|
139
|
+
* Send a heartbeat to watchcatd, telling it we're still alive.
|
140
|
+
*/
|
96
141
|
static VALUE
|
97
142
|
rb_wcat_heartbeat(VALUE self)
|
98
143
|
{
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
144
|
+
VALUE sock = rb_iv_get(self, "@sock");
|
145
|
+
if (cat_heartbeat(NUM2INT(sock)) == -1)
|
146
|
+
rb_sys_fail("cat_heartbeat");
|
147
|
+
return(Qnil);
|
103
148
|
}
|
104
149
|
|
150
|
+
/*
|
151
|
+
* call-seq:
|
152
|
+
* cat.close
|
153
|
+
*
|
154
|
+
* Close communication with watchcatd.
|
155
|
+
*/
|
105
156
|
static VALUE
|
106
157
|
rb_wcat_close(VALUE self)
|
107
158
|
{
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
159
|
+
VALUE sock = rb_iv_get(self, "@sock");
|
160
|
+
if (cat_close(NUM2INT(sock)) == -1)
|
161
|
+
rb_sys_fail("cat_close");
|
162
|
+
return(Qnil);
|
112
163
|
}
|
113
164
|
|
114
165
|
void
|
115
166
|
Init_watchcat(void)
|
116
167
|
{
|
117
|
-
|
168
|
+
VALUE cWCat = rb_define_class("Watchcat", rb_cObject);
|
118
169
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
170
|
+
rb_define_method(cWCat, "initialize", rb_wcat_open, -1);
|
171
|
+
rb_define_alias(cWCat, "open", "initialize");
|
172
|
+
rb_define_method(cWCat, "heartbeat", rb_wcat_heartbeat, 0);
|
173
|
+
rb_define_method(cWCat, "close", rb_wcat_close, 0);
|
123
174
|
}
|
metadata
CHANGED
@@ -1,47 +1,58 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.11
|
3
|
-
specification_version: 1
|
4
2
|
name: ruby-watchcat
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0.
|
7
|
-
date: 2006-04-20 00:00:00 -03:00
|
8
|
-
summary: A Ruby extension for libwatchcat
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: andre@digirati.com.br
|
12
|
-
homepage: http://watchcat.rubyforge.org
|
13
|
-
rubyforge_project: ruby-watchcat
|
14
|
-
description: Ruby/Watchcat is an extension for the Ruby programming language for the development of watchcatd-aware applications.
|
15
|
-
autorequire: watchcat
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: false
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 1.0.1
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
6
|
authors:
|
29
7
|
- Andre Nathan
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
- examples/example.rb
|
34
|
-
test_files: []
|
35
|
-
|
36
|
-
rdoc_options: []
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
37
11
|
|
38
|
-
|
12
|
+
date: 2008-08-06 00:00:00 -03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
39
15
|
|
16
|
+
description: Ruby/Watchcat is an extension for the Ruby programming language for the development of watchcatd-aware applications.
|
17
|
+
email: andre@digirati.com.br
|
40
18
|
executables: []
|
41
19
|
|
42
20
|
extensions:
|
43
21
|
- ext/extconf.rb
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- ext/watchcat.c
|
27
|
+
- ext/extconf.rb
|
28
|
+
- examples/example.rb
|
29
|
+
has_rdoc: true
|
30
|
+
homepage: http://watchcat.rubyforge.org
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options:
|
33
|
+
- --title
|
34
|
+
- Ruby/Watchcat--main
|
35
|
+
- README
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: "0"
|
43
|
+
version:
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
44
50
|
requirements:
|
45
51
|
- libwcat and watchcatd.
|
46
|
-
|
52
|
+
rubyforge_project: ruby-watchcat
|
53
|
+
rubygems_version: 1.0.0
|
54
|
+
signing_key:
|
55
|
+
specification_version: 2
|
56
|
+
summary: A Ruby extension for libwatchcat
|
57
|
+
test_files: []
|
47
58
|
|