slave 0.2.0 → 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.
data/README CHANGED
@@ -12,49 +12,49 @@ SYNOPSIS
12
12
 
13
13
  obj = AnyClass::new
14
14
 
15
- slave = Slave::new obj
15
+ slave = Slave::new 'object' => obj
16
16
 
17
17
  p slave.object # handle on drb object
18
18
  p slave.uri # uri of the drb object
19
19
  p slave.socket # unix domain socket path for drb object
20
20
  p slave.psname # title shown in ps/top
21
21
 
22
- other usage:
23
-
24
- set the pulse_rate used for the Heartbeat
25
-
26
- slave = Slave::new MyClass::new, 'pulse_rate' => 10
22
+ slaves may be configured via the environment, the Slave class, or via the
23
+ ctor for object itself. attributes which may be configured include
27
24
 
28
- same
25
+ * socket_creation_attempts
26
+ * pulse_rate
27
+ * psname
28
+ * debug
29
+ * dumped
29
30
 
30
- Slave::pulse_rate = 10
31
- slave = Slave::new MyClass::new
31
+ URIS
32
32
 
33
- same
33
+ http://rubyforge.org/projects/codeforpeople/
34
+ http://codeforpeople.com/lib/ruby/slave
34
35
 
35
- ENV['SLAVE_PULSE_RATE'] = 10
36
- slave = Slave::new MyClass::new
36
+ HISTORY
37
37
 
38
- to avoid having a copy of the object in both the parent and child use the
39
- block form
38
+ THIS RELEASE IS !! NOT !! BACKWARD COMPATIBLE. NOTE NEW CTOR SYNTAX.
40
39
 
41
- slave = Slave::new{ Server::new } # copy only in child!
42
- server = slave.object
40
+ 1.0.0:
43
41
 
44
- if both an object AND a block are passed the object is passed to the block
45
- in the child process
42
+ - detach method also sets up at_exit handler. extra protection from
43
+ zombies.
46
44
 
47
- slave = Slave::new(Server::new){|server| p 'in child!' }
45
+ - ezra zygmuntowicz asked for a feature whereby a parent could be notified
46
+ when a child exited. obviously such a mechanism should be both async
47
+ and sync. to accomplish this the wait method was extended to support a
48
+ callback with is either sync or async
48
49
 
49
- slaves may be configured via the environment, the Slave class, or via the
50
- ctor for object itself. attributes which may be configured include
50
+ slave = Server.new{ Server.new }
51
51
 
52
- * socket_creation_attempts
53
- * pulse_rate
54
- * psname
55
- * debug
52
+ slave.wait and puts 'this is sync!'
56
53
 
57
- HISTORY
54
+ slave.wait(:non_block=>true){ 'this is async!' }
55
+
56
+ - patch to getval from skaar<skaar@waste.org>. the impl dropped opts
57
+ delgating to the class method from the instance one.
58
58
 
59
59
  0.2.0:
60
60
  incorporated joel vanderWerf's patch such that, if no object is passed the
@@ -77,3 +77,141 @@ HISTORY
77
77
 
78
78
  0.0.0:
79
79
  - initial version
80
+
81
+ SAMPLES
82
+
83
+ <========< samples/a.rb >========>
84
+
85
+ ~ > cat samples/a.rb
86
+
87
+ require 'slave'
88
+ #
89
+ # simple usage is simply to stand up a server object as a slave. you do not
90
+ # need to wait for the server, join it, etc. it will die when the parent
91
+ # process dies - even under 'kill -9' conditions
92
+ #
93
+ class Server
94
+ def add_two n
95
+ n + 2
96
+ end
97
+ end
98
+
99
+ slave = Slave.new :object => Server.new
100
+ server = slave.object
101
+
102
+ p server.add_two(40) #=> 42
103
+
104
+ ~ > ruby samples/a.rb
105
+
106
+ 42
107
+
108
+
109
+ <========< samples/b.rb >========>
110
+
111
+ ~ > cat samples/b.rb
112
+
113
+ require 'slave'
114
+ #
115
+ # if certain operations need to take place in the child only a block can be
116
+ # used
117
+ #
118
+ class Server
119
+ def connect_to_db
120
+ "we only want to do this in the child process!"
121
+ @connection = :postgresql
122
+ end
123
+ attr :connection
124
+ end
125
+
126
+ slave = Slave.new('object' => Server.new){|s| s.connect_to_db}
127
+
128
+ server = slave.object
129
+
130
+ p server.connection #=> :postgresql
131
+ #
132
+ # errors in the child are detected and raised in the parent
133
+ #
134
+ slave = Slave.new('object' => Server.new){|s| s.typo} #=> raises an error!
135
+
136
+ ~ > ruby samples/b.rb
137
+
138
+ :postgresql
139
+ ./lib/slave.rb:276:in `initialize': undefined method `typo' for #<Server:0xb7573350> (NoMethodError)
140
+ from samples/b.rb:22:in `new'
141
+ from samples/b.rb:22
142
+
143
+
144
+ <========< samples/c.rb >========>
145
+
146
+ ~ > cat samples/c.rb
147
+
148
+ require 'slave'
149
+ #
150
+ # if no slave object is given the block itself is used to contruct it
151
+ #
152
+ class Server
153
+ def initialize
154
+ "this is run only in the child"
155
+ @pid = Process.pid
156
+ end
157
+ attr 'pid'
158
+ end
159
+
160
+ slave = Slave.new{ Server.new }
161
+ server = slave.object
162
+
163
+ p Process.pid
164
+ p server.pid # not going to be the same as parents!
165
+ #
166
+ # errors are still detected though
167
+ #
168
+ slave = Slave.new{ fubar } # raises error in parent
169
+
170
+ ~ > ruby samples/c.rb
171
+
172
+ 12244
173
+ 12245
174
+ ./lib/slave.rb:276:in `initialize': undefined local variable or method `fubar' for main:Object (NameError)
175
+ from samples/c.rb:21:in `new'
176
+ from samples/c.rb:21
177
+
178
+
179
+ <========< samples/d.rb >========>
180
+
181
+ ~ > cat samples/d.rb
182
+
183
+ require 'slave'
184
+ #
185
+ # at_exit hanlders are handled correctly in both child and parent
186
+ #
187
+ at_exit{ p 'parent' }
188
+ slave = Slave.new{ at_exit{ p 'child' }; 'the server is this string' }
189
+ #
190
+ # this will print 'child', then 'parent'
191
+ #
192
+
193
+ ~ > ruby samples/d.rb
194
+
195
+ "parent"
196
+
197
+
198
+ <========< samples/e.rb >========>
199
+
200
+ ~ > cat samples/e.rb
201
+
202
+ require 'slave'
203
+ #
204
+ # slaves never outlive their parent. if the parent exits, even under kill -9,
205
+ # the child will die.
206
+ #
207
+ slave = Slave.new{ at_exit{ p 'child' }; 'the server is this string' }
208
+
209
+ Process.kill brutal=9, the_parent_pid=Process.pid
210
+ #
211
+ # even though parent dies a nasty death the child will still print 'child'
212
+ #
213
+
214
+ ~ > ruby samples/e.rb
215
+
216
+ "child"
217
+
data/README.tmpl ADDED
@@ -0,0 +1,83 @@
1
+ SYNOPSIS
2
+
3
+ the Slave class forks a process and starts a drb server in the child using
4
+ any object as the server. the process is detached so it is not required
5
+ (nor possible) to wait on the child pid. a Heartbeat is set up between the
6
+ parent and child processes so that the child will exit of the parent exits
7
+ for any reason - preventing orphaned slaves from running indefinitely. the
8
+ purpose of Slaves is to be able to easily set up a collection of objects
9
+ communicating via drb protocols instead of having to use IPC.
10
+
11
+ typical usage:
12
+
13
+ obj = AnyClass::new
14
+
15
+ slave = Slave::new 'object' => obj
16
+
17
+ p slave.object # handle on drb object
18
+ p slave.uri # uri of the drb object
19
+ p slave.socket # unix domain socket path for drb object
20
+ p slave.psname # title shown in ps/top
21
+
22
+ slaves may be configured via the environment, the Slave class, or via the
23
+ ctor for object itself. attributes which may be configured include
24
+
25
+ * socket_creation_attempts
26
+ * pulse_rate
27
+ * psname
28
+ * debug
29
+ * dumped
30
+
31
+ URIS
32
+
33
+ http://rubyforge.org/projects/codeforpeople/
34
+ http://codeforpeople.com/lib/ruby/slave
35
+
36
+ HISTORY
37
+
38
+ THIS RELEASE IS !! NOT !! BACKWARD COMPATIBLE. NOTE NEW CTOR SYNTAX.
39
+
40
+ 1.0.0:
41
+
42
+ - detach method also sets up at_exit handler. extra protection from
43
+ zombies.
44
+
45
+ - ezra zygmuntowicz asked for a feature whereby a parent could be notified
46
+ when a child exited. obviously such a mechanism should be both async
47
+ and sync. to accomplish this the wait method was extended to support a
48
+ callback with is either sync or async
49
+
50
+ slave = Server.new{ Server.new }
51
+
52
+ slave.wait and puts 'this is sync!'
53
+
54
+ slave.wait(:non_block=>true){ 'this is async!' }
55
+
56
+ - patch to getval from skaar<skaar@waste.org>. the impl dropped opts
57
+ delgating to the class method from the instance one.
58
+
59
+ 0.2.0:
60
+ incorporated joel vanderWerf's patch such that, if no object is passed the
61
+ block is used to create one ONLY in the child. this avoids having a copy
62
+ in both parent and child is that needs to be avoided due to, for instance,
63
+ resource consumption.
64
+
65
+
66
+ 0.0.1:
67
+ - patch from Logan Capaldo adds block form to slave new, block is run in the
68
+ child
69
+
70
+ - added a few more samples/*
71
+
72
+ - added Slave#wait
73
+
74
+ - added status information to slaves
75
+
76
+ - added close-on-exec flag to pipes in parent process
77
+
78
+ 0.0.0:
79
+ - initial version
80
+
81
+ SAMPLES
82
+
83
+ @samples
@@ -0,0 +1,117 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Class: (@object = Object.new)</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="classHeader">
50
+ <h1>(@object = Object.new) <sup class="type-note">(Class)</sup></h1>
51
+ <table class="header-table">
52
+ <tr class="top-aligned-row">
53
+ <td><strong>In:</strong></td>
54
+ <td>
55
+ <a href="../files/lib/slave_rb.html">
56
+ lib/slave.rb
57
+ </a>
58
+ <br />
59
+ </td>
60
+ </tr>
61
+
62
+ </table>
63
+ </div>
64
+ <!-- banner header -->
65
+
66
+ <div id="bodyContent">
67
+
68
+
69
+ <div id="contextContent">
70
+ <div id="diagram">
71
+ <map name="map">
72
+ <area shape="RECT" coords="27,98,99,50" href="Slave.html" alt="Slave">
73
+ <area shape="RECT" coords="16,108,205,16" href=".././classes" alt="(@object = Object.new).html (@object = Object.new)">
74
+ </map>
75
+ <img src="../dot/f_1.jpg" usemap="#map" border=0 alt="TopLevel">
76
+ </div>
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+ <div id="attribute-list">
85
+ <h2 class="section-bar">Attributes</h2>
86
+
87
+ <div class="name-list">
88
+ <table>
89
+ <tr class="top-aligned-row context-row">
90
+ <td class="context-item-name">__slave_object_failure__</td>
91
+ <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
92
+ <td class="context-item-desc"></td>
93
+ </tr>
94
+ </table>
95
+ </div>
96
+ </div>
97
+
98
+
99
+ </div>
100
+
101
+
102
+
103
+ <!-- if includes -->
104
+
105
+
106
+ <!-- if method_list -->
107
+
108
+
109
+ </div>
110
+
111
+
112
+ <div id="validator-badges">
113
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
114
+ </div>
115
+
116
+ </body>
117
+ </html>
@@ -0,0 +1,117 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Class: (o = Object.new)</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="classHeader">
50
+ <h1>(o = Object.new) <sup class="type-note">(Class)</sup></h1>
51
+ <table class="header-table">
52
+ <tr class="top-aligned-row">
53
+ <td><strong>In:</strong></td>
54
+ <td>
55
+ <a href="../files/lib/slave_rb.html">
56
+ lib/slave.rb
57
+ </a>
58
+ <br />
59
+ </td>
60
+ </tr>
61
+
62
+ </table>
63
+ </div>
64
+ <!-- banner header -->
65
+
66
+ <div id="bodyContent">
67
+
68
+
69
+ <div id="contextContent">
70
+ <div id="diagram">
71
+ <map name="map">
72
+ <area shape="RECT" coords="123,98,195,50" href="Slave.html" alt="Slave">
73
+ <area shape="RECT" coords="16,108,205,16" href=".././classes" alt="(o = Object.new).html (o = Object.new)">
74
+ </map>
75
+ <img src="../dot/f_1.jpg" usemap="#map" border=0 alt="TopLevel">
76
+ </div>
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+ <div id="attribute-list">
85
+ <h2 class="section-bar">Attributes</h2>
86
+
87
+ <div class="name-list">
88
+ <table>
89
+ <tr class="top-aligned-row context-row">
90
+ <td class="context-item-name">__slave_object_failure__</td>
91
+ <td class="context-item-value">&nbsp;[RW]&nbsp;</td>
92
+ <td class="context-item-desc"></td>
93
+ </tr>
94
+ </table>
95
+ </div>
96
+ </div>
97
+
98
+
99
+ </div>
100
+
101
+
102
+
103
+ <!-- if includes -->
104
+
105
+
106
+ <!-- if method_list -->
107
+
108
+
109
+ </div>
110
+
111
+
112
+ <div id="validator-badges">
113
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
114
+ </div>
115
+
116
+ </body>
117
+ </html>