ruby-watchcat 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +64 -0
  2. data/examples/example.rb +4 -0
  3. data/ext/extconf.rb +1 -0
  4. data/ext/watchcat.c +136 -85
  5. 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
@@ -1,5 +1,6 @@
1
1
  require 'mkmf'
2
2
 
3
3
  if find_library('wcat', 'cat_open') and have_header('watchcat.h')
4
+ $CFLAGS += " -Wall #{ENV['CFLAGS']}"
4
5
  create_makefile('watchcat')
5
6
  end
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 6 2006-04-21 02:19:26Z andre $
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
- int cat, id, timeout, signal;
26
- char *signame;
27
- const char *info;
28
- VALUE opt, vtimeout, vsignal, vinfo, vsiglist, mSignal;
29
-
30
- rb_scan_args(argc, argv, "01", &opt);
31
- if (NIL_P(opt)) {
32
- cat = cat_open();
33
- if (cat == -1)
34
- rb_sys_fail("cat_open");
35
- rb_iv_set(self, "@cat", INT2NUM(cat));
36
- return(self);
37
- }
38
-
39
- /* Defaults. */
40
- timeout = 60;
41
- signal = SIGKILL;
42
- info = NULL;
43
-
44
- vtimeout = rb_hash_aref(opt, ID2SYM(rb_intern("timeout")));
45
- if (!NIL_P(vtimeout)) {
46
- if (FIXNUM_P(vtimeout))
47
- timeout = NUM2INT(vtimeout);
48
- else
49
- rb_raise(rb_eTypeError, "timeout must be an integer");
50
- }
51
-
52
- vsignal = rb_hash_aref(opt, ID2SYM(rb_intern("signal")));
53
- if (!NIL_P(vsignal)) {
54
- switch (TYPE(vsignal)) {
55
- case T_FIXNUM:
56
- signal = NUM2INT(vsignal);
57
- break;
58
- case T_STRING:
59
- signame = StringValuePtr(vsignal);
60
- if (strncmp("SIG", signame, 3) == 0) {
61
- signame += 3;
62
- vsignal = rb_str_new2(signame);
63
- }
64
- id = rb_intern("Signal");
65
- mSignal = rb_const_get(rb_cObject, id);
66
- id = rb_intern("list");
67
- vsiglist = rb_funcall(mSignal, id, 0);
68
- id = rb_intern("fetch");
69
- vsignal = rb_funcall(vsiglist, id, 1, vsignal);
70
- signal = NUM2INT(vsignal);
71
- break;
72
- default:
73
- rb_raise(rb_eTypeError,
74
- "signal must be an integer or a string");
75
- }
76
- }
77
-
78
- vinfo = rb_hash_aref(opt, ID2SYM(rb_intern("info")));
79
- if (!NIL_P(vinfo))
80
- info = StringValuePtr(vinfo);
81
-
82
- cat = cat_open1(timeout, signal, info);
83
- if (cat == -1)
84
- rb_sys_fail("cat_open");
85
-
86
- rb_iv_set(self, "@cat", INT2NUM(cat));
87
-
88
- if (rb_block_given_p()) {
89
- rb_yield(self);
90
- cat_close(cat);
91
- }
92
-
93
- return(self);
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
- VALUE cCat = rb_iv_get(self, "@cat");
100
- if (cat_heartbeat(NUM2INT(cCat)) == -1)
101
- rb_sys_fail("cat_heartbeat");
102
- return(Qnil);
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
- VALUE cCat = rb_iv_get(self, "@cat");
109
- if (cat_close(NUM2INT(cCat)) == -1)
110
- rb_sys_fail("cat_close");
111
- return(Qnil);
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
- VALUE cWCat = rb_define_class("Watchcat", rb_cObject);
168
+ VALUE cWCat = rb_define_class("Watchcat", rb_cObject);
118
169
 
119
- rb_define_method(cWCat, "initialize", rb_wcat_open, -1);
120
- rb_define_alias(cWCat, "open", "initialize");
121
- rb_define_method(cWCat, "heartbeat", rb_wcat_heartbeat, 0);
122
- rb_define_method(cWCat, "close", rb_wcat_close, 0);
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.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
- files:
31
- - ext/watchcat.c
32
- - ext/extconf.rb
33
- - examples/example.rb
34
- test_files: []
35
-
36
- rdoc_options: []
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
37
11
 
38
- extra_rdoc_files: []
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
- dependencies: []
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