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.
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