opm 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2007-07-26
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 FIXME full name
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/opm.rb
7
+ lib/opm/version.rb
8
+ setup.rb
@@ -0,0 +1,3 @@
1
+ README for opm
2
+ ==============
3
+
@@ -0,0 +1,123 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+
12
+ include FileUtils
13
+ require File.join(File.dirname(__FILE__), 'lib', 'opm', 'version')
14
+
15
+ AUTHOR = 'Papp Laszlo' # can also be an array of Authors
16
+ EMAIL = "pappl@inf.elte.hu"
17
+ DESCRIPTION = "OPM support for Ruby"
18
+ GEM_NAME = 'opm' # what ppl will type to install your gem
19
+
20
+ @config_file = "~/.rubyforge/user-config.yml"
21
+ @config = nil
22
+ def rubyforge_username
23
+ unless @config
24
+ begin
25
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
26
+ rescue
27
+ puts <<-EOS
28
+ ERROR: No rubyforge config file found: #{@config_file}"
29
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
30
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
31
+ EOS
32
+ exit
33
+ end
34
+ end
35
+ @rubyforge_username ||= @config["username"]
36
+ end
37
+
38
+ RUBYFORGE_PROJECT = 'opm' # The unix name for your project
39
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
40
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
41
+
42
+ NAME = "opm"
43
+ REV = nil
44
+ # UNCOMMENT IF REQUIRED:
45
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
46
+ VERS = Opm::VERSION::STRING + (REV ? ".#{REV}" : "")
47
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
48
+ RDOC_OPTS = ['--quiet', '--title', 'opm documentation',
49
+ "--opname", "index.html",
50
+ "--line-numbers",
51
+ "--main", "README",
52
+ "--inline-source"]
53
+
54
+ class Hoe
55
+ def extra_deps
56
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
57
+ end
58
+ end
59
+
60
+ # Generate all the Rake tasks
61
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
62
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
63
+ p.author = AUTHOR
64
+ p.description = DESCRIPTION
65
+ p.email = EMAIL
66
+ p.summary = DESCRIPTION
67
+ p.url = HOMEPATH
68
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
69
+ p.test_globs = ["test/**/test_*.rb"]
70
+ p.clean_globs |= CLEAN #An array of file patterns to delete on clean.
71
+
72
+ # == Optional
73
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
74
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
75
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
76
+ end
77
+
78
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\n\n")
79
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
80
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
81
+
82
+ desc 'Generate website files'
83
+ task :website_generate do
84
+ Dir['website/**/*.txt'].each do |txt|
85
+ sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
86
+ end
87
+ end
88
+
89
+ desc 'Upload website files to rubyforge'
90
+ task :website_upload do
91
+ host = "#{rubyforge_username}@rubyforge.org"
92
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
93
+ local_dir = 'website'
94
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
95
+ end
96
+
97
+ desc 'Generate and upload website files'
98
+ task :website => [:website_generate, :website_upload, :publish_docs]
99
+
100
+ desc 'Release the website and new gem version'
101
+ task :deploy => [:check_version, :website, :release] do
102
+ puts "Remember to create SVN tag:"
103
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
104
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
105
+ puts "Suggested comment:"
106
+ puts "Tagging release #{CHANGES}"
107
+ end
108
+
109
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
110
+ task :local_deploy => [:website_generate, :install_gem]
111
+
112
+ task :check_version do
113
+ unless ENV['VERSION']
114
+ puts 'Must pass a VERSION=x.y.z release version'
115
+ exit
116
+ end
117
+ unless ENV['VERSION'] == VERS
118
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
119
+ exit
120
+ end
121
+ end
122
+
123
+
@@ -0,0 +1,379 @@
1
+ #
2
+ # Copyright (c) 2007 Papp Laszlo (pappl@inf.elte.hu)
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ require 'opm/version'
22
+ require 'thread'
23
+ require 'drb'
24
+
25
+ module Opm
26
+
27
+ # A Temporary Object, if the process is working while we want reach the instance variable,
28
+ # it attaches the running process, and variable name for in the future we can get the value.
29
+ class TemporaryProcessObject
30
+
31
+ # The process, which working on the object
32
+ attr_reader :process
33
+
34
+ # Name of the object
35
+ attr_reader :variable
36
+
37
+ def initialize( process, var )
38
+ @process = process
39
+ @variable = var
40
+ end
41
+ end
42
+
43
+ module OpmException
44
+
45
+ class ProcessException < Exception
46
+ attr_reader :process
47
+
48
+ def initialize(process)
49
+ @process = process
50
+ end
51
+
52
+ end
53
+
54
+ class NoInput < ProcessException
55
+ end
56
+
57
+ class BeforeFilterFailed < ProcessException
58
+ end
59
+
60
+ class AfterFilterFailed < ProcessException
61
+ end
62
+
63
+ end
64
+
65
+ # For OPM States.. It contains only states, and only one active
66
+ #
67
+ # class LoggedIn < OpmStatus
68
+ # states :logged, :logout
69
+ # end
70
+ #
71
+ # stat = LoggedIn.status :logged
72
+ # stat.status #:logged
73
+ #
74
+ # stat.logout
75
+ # stat.status #:logout
76
+ #
77
+ class OpmStatus
78
+ class << self
79
+ #attr_accessor :statuses
80
+ end
81
+
82
+ protected
83
+ def self.states(*args)
84
+ @statuses ||= []
85
+ @statuses += args
86
+ end
87
+
88
+ public
89
+
90
+ # For generate a status object
91
+ # @param status: The initializer status
92
+ def self.status( status )
93
+ object = new(status)
94
+ @statuses.each do |stat|
95
+ class_eval %(class << object
96
+ def #{stat}
97
+ @status = :#{stat}
98
+ end
99
+ end
100
+ )
101
+ end
102
+ return object
103
+ end
104
+
105
+ private
106
+
107
+ def self.inherited(subclass)
108
+ begin
109
+ self.statuses.each do |stat|
110
+ subclass.states(stat)
111
+ end
112
+ rescue
113
+ end
114
+ end
115
+
116
+ protected
117
+ def initialize(status)
118
+ @status = status
119
+ end
120
+
121
+ public
122
+ # The current status. Returns symbol!
123
+ def status
124
+ return @status
125
+ end
126
+
127
+ # The same as status method.
128
+ def to_s
129
+ return @status
130
+ end
131
+ end
132
+
133
+ # Main process class
134
+ #
135
+ # class Sum < OpmProcess
136
+ # input :input1, :input2
137
+ # output :output1
138
+ #
139
+ # def run
140
+ # @output1 = @input1 + @input2
141
+ # end
142
+ # end
143
+ #
144
+ # proc = Sum.process :input1 => 1, :input2 => 12
145
+ # proc.wait
146
+ # puts proc.output1 # 13
147
+ class OpmProcess
148
+
149
+ class << self
150
+ #attr_accessor :input_arguments
151
+ #attr_accessor :output_arguments
152
+ #attr_accessor :remote
153
+ end
154
+
155
+ public
156
+
157
+ # Define input variables. In the process if you use
158
+ #
159
+ # include :foo, :bar
160
+ #
161
+ # then you can use them as @foo, @bar
162
+ #
163
+ def self.input(*args)
164
+ @input_arguments ||= []
165
+ @input_arguments += args
166
+ args.each do |arg|
167
+ instance_variable_set("@#{arg}", nil)
168
+ end
169
+ end
170
+
171
+ # Outputs of the process
172
+ #
173
+ # class SampleProcess < OpmProcess
174
+ # input :input
175
+ # output :foo
176
+ # ...
177
+ # end
178
+ #
179
+ # bar = SampleProcess.process :input => "something"
180
+ # puts bar.foo
181
+ #
182
+ def self.output(*args)
183
+ @output_arguments ||= []
184
+ @output_arguments += args
185
+ args.each do |arg|
186
+ instance_variable_set("@#{arg}", nil)
187
+ class_eval %(class << self; attr_reader :#{arg} end)
188
+ end
189
+ end
190
+
191
+ def self.remote(args) #:nodoc:
192
+ @remote = args
193
+ end
194
+
195
+ # Start the process
196
+ # @args => Parameters for input variables
197
+ #
198
+ def self.process(args={})
199
+
200
+ if @remote != nil
201
+ #It's not okay yet
202
+ object = DRb::DRbObject.new object, "druby://#{@remote[:host]}:#{@remote[:port]}"
203
+ else
204
+ object = new
205
+ end
206
+
207
+ @input_arguments.each do |arg|
208
+ # throw OpmException::NoInput.new(object) unless args.has_key? arg
209
+ if args[arg].class == TemporaryProcessObject
210
+ object.underProcessing = [arg, args[arg]]
211
+ next
212
+ end
213
+ object.instance_variable_set("@#{arg}", args[arg])
214
+ end
215
+
216
+ @output_arguments.each do |arg|
217
+ object.instance_variable_set("@#{arg}", args[arg])
218
+ object.outputsForWait = arg
219
+ class_eval %( class << object; def #{arg}
220
+ return @#{arg} unless running?
221
+ return TemporaryProcessObject.new(self, "#{arg}")
222
+ end
223
+ end
224
+ )
225
+ end
226
+ object.start_process
227
+ return object
228
+ end
229
+
230
+
231
+ # Inherits from base class the input arguments
232
+ #
233
+ private
234
+ def self.inherited(subclass)
235
+ begin
236
+ self.input_arguments.each do |arg|
237
+ subclass.input(arg)
238
+ end
239
+
240
+ self.output_arguments.each do |arg|
241
+ subclass.output(arg)
242
+ end
243
+ rescue
244
+ # This branch is running when @input_arguments == nil
245
+ end
246
+ end
247
+
248
+ protected
249
+ def initialize
250
+ @underProcessing = []
251
+ @outputsForWait = []
252
+
253
+ @thread = Thread.new do
254
+ Thread.stop
255
+ @underProcessing.each do |p|
256
+ while p[1].process.running?
257
+ end
258
+ instance_variable_set("@#{p[0]}", p[1].process.instance_eval("@#{p[1].variable}"))
259
+ end
260
+
261
+ begin
262
+
263
+ if not before
264
+ @error = OpmException::BeforeFilterFailed.new(self)
265
+ raise @error
266
+ end
267
+
268
+ # Run the body of the process
269
+ run
270
+
271
+ if not after
272
+ @error = OpmException::AfterFilterFailed.new(self)
273
+ raise @error
274
+ end
275
+
276
+ # Wait for the outputs become active
277
+ wait_output_done
278
+ rescue OpmException::BeforeFilterFailed => before
279
+ onBeforeError
280
+ Thread.exit
281
+ rescue OpmException::AfterFilterFailed => after
282
+ onAfterError
283
+ Thread.exit
284
+ end
285
+ end
286
+ end
287
+
288
+ public
289
+ # Before filter for process. It's a logical function. If the function returns fault,
290
+ # the process calls the onBeforeError, where we can set the parameters. For more
291
+ # information about the cause of the error, use @error variable in onBeforeError.
292
+ #
293
+ def before
294
+ true
295
+ end
296
+
297
+ # Similar to before, but this is checking the result of the process
298
+ #
299
+ def after
300
+ true
301
+ end
302
+
303
+ # Callback function. It will signaled if before is false
304
+ #
305
+ def onBeforeError
306
+ end
307
+
308
+ # Look: onBeforeError.
309
+ #
310
+ def onAfterError
311
+ end
312
+
313
+ # Secure only one process be running in a block.
314
+ #
315
+ def onlyOne(args, &block)
316
+ @@Mutex ||= Hash.new
317
+ @@Mutex[args] = Mutex.new if @@Mutex[args] == nil
318
+ @@Mutex[args].synchronize do
319
+ yield
320
+ end
321
+ end
322
+
323
+ def underProcessing=( val ) #:nodoc:
324
+ @underProcessing << val
325
+ end
326
+
327
+
328
+ # For set the output attributes, for wait_output_done
329
+ def outputsForWait=( val ) #:nodoc:
330
+ @outputsForWait << val
331
+ end
332
+
333
+ def start_process #:nodoc:
334
+ @thread.run
335
+ end
336
+
337
+ private
338
+ # If a process contains another one, then the main process have to wait
339
+ # the inner process, because the output will be incosistent
340
+ #
341
+ def wait_output_done
342
+ # For all output arguments
343
+ @outputsForWait.each do |val|
344
+ # Get the value
345
+ output = instance_variable_get("@#{val}")
346
+
347
+ # We use exception handler, if output is not TemporaryProcessObject
348
+ begin
349
+ # While not active the object
350
+ #while output.process.running?
351
+ #end
352
+ output.process.wait
353
+
354
+ # Get the new value of the output
355
+ var = eval("output.process.#{val}")
356
+
357
+ # Set the instance variable
358
+ instance_variable_set("@#{val}", var)
359
+ rescue
360
+ # if output.process not defined, because output is not a TemporaryProcessObject
361
+ end
362
+ end
363
+ end
364
+
365
+ public
366
+
367
+ # Check thread is running
368
+ def running?
369
+ return @thread.alive?
370
+ end
371
+
372
+ def wait
373
+ @thread.join
374
+ end
375
+
376
+ end
377
+ end
378
+
379
+