rutty 2.3.2 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rutty/helpers.rb CHANGED
@@ -2,7 +2,7 @@ require 'rutty/errors'
2
2
  require 'rutty/version'
3
3
 
4
4
  module Rutty
5
-
5
+
6
6
  ##
7
7
  # Simple mixin module for miscellaneous methods that don't fit in elsewhere.
8
8
  #
@@ -17,10 +17,10 @@ module Rutty
17
17
  def check_installed!
18
18
  unless File.exists? self.config_dir
19
19
  raise Rutty::NotInstalledError.new %Q(Can't find conf directory at #{self.config_dir}.
20
- Run `rutty init' first. (Or rutty --help for usage))
20
+ Run `rutty init' first. (Or rutty --help for usage))
21
21
  end
22
22
  end
23
-
23
+
24
24
  ##
25
25
  # Returns the version string contained in {Rutty::Version::STRING}. Used by the rutty bin.
26
26
  #
@@ -29,5 +29,35 @@ module Rutty
29
29
  def self.get_version
30
30
  Rutty::Version::STRING
31
31
  end
32
+
33
+ ##
34
+ # Returns a string formatted to a more human-readable representation of a time difference in seconds.
35
+ #
36
+ # @since 2.4.0
37
+ #
38
+ # @param [Float] seconds_total The number of seconds to convert
39
+ # @return [String] The formatted string
40
+ def seconds_in_words seconds_total
41
+ hours = seconds_total / 3600
42
+ minutes = (seconds_total - (3600 * hours)) / 60
43
+ seconds = (seconds_total % (hours >= 1 ? (3600 * hours) : 60)) % 60
44
+
45
+ out = ''
46
+
47
+ unless hours < 1
48
+ out << hours.to_s
49
+ out << ((hours > 1) ? " hours " : " hour ")
50
+ end
51
+
52
+ unless minutes < 1
53
+ out << minutes.to_s
54
+ out << ((minutes > 1) ? " minutes " : " minute ")
55
+ end
56
+
57
+ out << seconds.to_s
58
+ out << ((seconds > 1) ? " seconds" : " second")
59
+
60
+ out.strip
61
+ end
32
62
  end
33
63
  end
data/lib/rutty/node.rb CHANGED
@@ -9,6 +9,18 @@ module Rutty
9
9
  # @author Josh Lindsey
10
10
  # @since 2.0.0
11
11
  class Node < Config
12
+ class << self
13
+ ##
14
+ # Override the inherited {Rutty::Config.load_config} method, raising an exception
15
+ # to indicate improper usage.
16
+ #
17
+ # @since 2.3.3
18
+ # @raise [RuntimeError] On call, as this class has no use for this method
19
+ def load_config dir
20
+ raise "Unable to call load_config on Node objects."
21
+ end
22
+ end
23
+
12
24
  ##
13
25
  # Initialize a new {Rutty::Node} instance by merging the user-provided data with
14
26
  # the configured defaults.
@@ -54,4 +66,4 @@ module Rutty
54
66
  self.tags == other.tags
55
67
  end
56
68
  end
57
- end
69
+ end
@@ -0,0 +1,80 @@
1
+ require 'thread'
2
+ require 'fastthread'
3
+ require 'rutty/thread_pool/worker'
4
+
5
+ module Rutty
6
+
7
+ ##
8
+ # A thread pool implementation using the work queue pattern. Shamelessly stolen from a StackOverflow question.
9
+ #
10
+ # @see http://stackoverflow.com/questions/81788/deadlock-in-threadpool/82777#82777
11
+ # @since 2.4.0
12
+ class ThreadPool
13
+ ## @return [Integer] The maximum number of concurrent {Worker} threads
14
+ attr_accessor :max_size
15
+
16
+ ##
17
+ # Creates a new {ThreadPool} instance with a maximum number of {Worker} threads.
18
+ def initialize max_size = 10
19
+ Thread.abort_on_exception = true
20
+
21
+ @max_size = max_size
22
+ @queue = Queue.new
23
+ @workers = []
24
+ end
25
+
26
+ ##
27
+ # The current size of the <tt>@workers</tt> array.
28
+ #
29
+ # @return [Integer] The current number of {Worker} threads
30
+ def current_size
31
+ @workers.size
32
+ end
33
+
34
+ ##
35
+ # Whether any {Worker} threads are currently executing, determined by
36
+ # comparing the sizes of the <tt>@workers</tt> array and the <tt>@queue</tt>.
37
+ #
38
+ # @return [Boolean] Any currently executing workers?
39
+ def busy?
40
+ @queue.size < current_size
41
+ end
42
+
43
+ ##
44
+ # Loops over every {Worker} and calls {Worker#stop}, then clears the <tt>@workers</tt> array.
45
+ def shutdown
46
+ @workers.each { |w| w.stop }
47
+ @workers = []
48
+ end
49
+
50
+ alias :join :shutdown
51
+
52
+ ##
53
+ # Gets a free worker and passes it the specified closure.
54
+ #
55
+ # @see #get_worker
56
+ # @param [Proc, Lambda, #call] block An instance of any class that responds to <tt>#call</tt>
57
+ def process block = nil, &blk
58
+ block = blk if block_given?
59
+ get_worker.set_block block
60
+ end
61
+
62
+ private
63
+
64
+ ##
65
+ # Gets a free {Worker}. If the {#max_size} has been reached and the <tt>@queue</tt> isn't empty,
66
+ # pops an existing {Worker} from there. Otherwise spins up a new {Worker} and adds it to the <tt>@workers</tt>
67
+ # array.
68
+ #
69
+ # @return [Rutty::Worker] A {Worker} ready for a new job
70
+ def get_worker
71
+ if !@queue.empty? or current_size == @max_size
72
+ return @queue.pop
73
+ else
74
+ worker = Rutty::Worker.new @queue
75
+ @workers << worker
76
+ worker
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,103 @@
1
+ require 'thread'
2
+ require 'fastthread'
3
+
4
+ module Rutty
5
+
6
+ ##
7
+ # The {ThreadPool} Thread wrapper, representing a single thread of execution in the pool.
8
+ #
9
+ # @since 2.4.0
10
+ class Worker
11
+
12
+ ##
13
+ # Initialize a new {Worker}. Sets up the initial state of this instance, then spins out its thread. The thread will
14
+ # wait until it's signaled (by being passed a new closure to execute, or being told to die, etc.), then resume execution
15
+ # of its task. The Thread is wrapped in a <tt>while @running</tt> loop, allowing for easy termination from {#shutdown}.
16
+ #
17
+ # @param [Queue] thread_queue The thread queue from the {ThreadPool} instance to add this worker to
18
+ # @return [Worker] The new, available Worker object.
19
+ def initialize thread_queue
20
+ @mutex = Mutex.new
21
+ @cv = ConditionVariable.new
22
+ @queue = thread_queue
23
+ @running = true
24
+
25
+ @thread = Thread.new do
26
+ @mutex.synchronize do
27
+ while @running
28
+ @cv.wait @mutex
29
+ block = get_block
30
+
31
+ if block
32
+ @mutex.unlock
33
+ block.call
34
+ @mutex.lock
35
+ reset_block
36
+ end
37
+
38
+ @queue << self
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ ##
45
+ # Returns the evaluation of <tt>@thread.inspect</tt>.
46
+ #
47
+ # @return [String] This thread's name
48
+ def name
49
+ @thread.inspect
50
+ end
51
+
52
+ ##
53
+ # Returns the value of <tt>@block</tt>.
54
+ #
55
+ # @return [Proc, Lambda, #call] The <tt>@block</tt> object previously passed.
56
+ def get_block
57
+ @block
58
+ end
59
+
60
+ ##
61
+ # Sets a new closure as the task for this worker. Signals the Thread to wakeup after assignment.
62
+ #
63
+ # @param (see Rutty::ThreadPool#process)
64
+ # @raise [RuntimeError] If the thread is currently busy when called.
65
+ def set_block block
66
+ @mutex.synchronize do
67
+ raise RuntimeError, "Thread already busy." if @block
68
+ @block = block
69
+ # Signal the thread in this class, that there's a job to be done
70
+ @cv.signal
71
+ end
72
+ end
73
+
74
+ ##
75
+ # Sets the <tt>@block</tt> to <tt>nil</tt>. Called after the Thread has finished execution of a task to
76
+ # ready itself for the next one.
77
+ def reset_block
78
+ @block = nil
79
+ end
80
+
81
+ ##
82
+ # Whether or not this Thread is currently executing. Determined by whether <tt>@block</tt> is <tt>nil</tt>.
83
+ #
84
+ # @return [Boolean] Is this Thread executing?
85
+ def busy?
86
+ @mutex.synchronize { !@block.nil? }
87
+ end
88
+
89
+ ##
90
+ # Sets <tt>@running</tt> to <tt>false</tt>, causing the Thread to finish after the current loop. Signals
91
+ # the Thread to wake and resume, then calls <tt>#join</tt>.
92
+ #
93
+ # @see #initialize
94
+ def stop
95
+ @mutex.synchronize do
96
+ @running = false
97
+ @cv.signal
98
+ end
99
+
100
+ @thread.join
101
+ end
102
+ end
103
+ end
data/lib/rutty/version.rb CHANGED
@@ -8,8 +8,8 @@ module Rutty
8
8
  # @see http://semver.org
9
9
  module Version
10
10
  MAJOR = 2
11
- MINOR = 3
12
- PATCH = 2
11
+ MINOR = 4
12
+ PATCH = 0
13
13
  BUILD = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
data/rutty.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rutty}
8
- s.version = "2.3.2"
8
+ s.version = "2.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Josh Lindsey"]
12
- s.date = %q{2010-11-15}
12
+ s.date = %q{2010-11-24}
13
13
  s.default_executable = %q{rutty}
14
14
  s.description = %q{
15
15
  RuTTY is a DSH (distributed / dancer's shell) written in Ruby. It's used to run commands
@@ -20,63 +20,66 @@ Gem::Specification.new do |s|
20
20
  s.executables = ["rutty"]
21
21
  s.extra_rdoc_files = [
22
22
  "LICENSE",
23
- "README.md"
23
+ "README.md"
24
24
  ]
25
25
  s.files = [
26
- ".gitignore",
27
- ".yardopts",
28
- "Gemfile",
29
- "Gemfile.lock",
30
- "LICENSE",
31
- "README.md",
32
- "Rakefile",
33
- "VERSION",
34
- "bin/rutty",
35
- "lib/rutty.rb",
36
- "lib/rutty/actions.rb",
37
- "lib/rutty/config.rb",
38
- "lib/rutty/consts.rb",
39
- "lib/rutty/errors.rb",
40
- "lib/rutty/helpers.rb",
41
- "lib/rutty/node.rb",
42
- "lib/rutty/nodes.rb",
43
- "lib/rutty/proc_classes.rb",
44
- "lib/rutty/treetop/syntax_nodes.rb",
45
- "lib/rutty/treetop/tag_query.rb",
46
- "lib/rutty/treetop/tag_query.treetop",
47
- "lib/rutty/version.rb",
48
- "rutty.gemspec",
49
- "test/helper.rb",
50
- "test/test_action_add_node.rb",
51
- "test/test_action_dsh.rb",
52
- "test/test_action_init.rb",
53
- "test/test_action_list_nodes.rb",
54
- "test/test_actions.rb",
55
- "test/test_config.rb",
56
- "test/test_consts.rb",
57
- "test/test_helpers.rb",
58
- "test/test_node.rb",
59
- "test/test_nodes.rb",
60
- "test/test_runner.rb"
26
+ ".yardopts",
27
+ "Gemfile",
28
+ "Gemfile.lock",
29
+ "LICENSE",
30
+ "README.md",
31
+ "Rakefile",
32
+ "VERSION",
33
+ "bin/rutty",
34
+ "lib/rutty.rb",
35
+ "lib/rutty/actions.rb",
36
+ "lib/rutty/config.rb",
37
+ "lib/rutty/consts.rb",
38
+ "lib/rutty/errors.rb",
39
+ "lib/rutty/helpers.rb",
40
+ "lib/rutty/node.rb",
41
+ "lib/rutty/nodes.rb",
42
+ "lib/rutty/proc_classes.rb",
43
+ "lib/rutty/thread_pool/pool.rb",
44
+ "lib/rutty/thread_pool/worker.rb",
45
+ "lib/rutty/treetop/syntax_nodes.rb",
46
+ "lib/rutty/treetop/tag_query.rb",
47
+ "lib/rutty/treetop/tag_query.treetop",
48
+ "lib/rutty/version.rb",
49
+ "rutty.gemspec",
50
+ "test/helper.rb",
51
+ "test/test_action_add_node.rb",
52
+ "test/test_action_dsh.rb",
53
+ "test/test_action_init.rb",
54
+ "test/test_action_list_nodes.rb",
55
+ "test/test_action_scp.rb",
56
+ "test/test_actions.rb",
57
+ "test/test_config.rb",
58
+ "test/test_consts.rb",
59
+ "test/test_helpers.rb",
60
+ "test/test_node.rb",
61
+ "test/test_nodes.rb",
62
+ "test/test_runner.rb"
61
63
  ]
62
64
  s.homepage = %q{http://github.com/jlindsey/rutty}
63
- s.rdoc_options = ["--charset=UTF-8"]
65
+ s.licenses = ["MIT"]
64
66
  s.require_paths = ["lib"]
65
67
  s.rubygems_version = %q{1.3.7}
66
68
  s.summary = %q{A DSH implementation in Ruby}
67
69
  s.test_files = [
68
70
  "test/helper.rb",
69
- "test/test_action_add_node.rb",
70
- "test/test_action_dsh.rb",
71
- "test/test_action_init.rb",
72
- "test/test_action_list_nodes.rb",
73
- "test/test_actions.rb",
74
- "test/test_config.rb",
75
- "test/test_consts.rb",
76
- "test/test_helpers.rb",
77
- "test/test_node.rb",
78
- "test/test_nodes.rb",
79
- "test/test_runner.rb"
71
+ "test/test_action_add_node.rb",
72
+ "test/test_action_dsh.rb",
73
+ "test/test_action_init.rb",
74
+ "test/test_action_list_nodes.rb",
75
+ "test/test_action_scp.rb",
76
+ "test/test_actions.rb",
77
+ "test/test_config.rb",
78
+ "test/test_consts.rb",
79
+ "test/test_helpers.rb",
80
+ "test/test_node.rb",
81
+ "test/test_nodes.rb",
82
+ "test/test_runner.rb"
80
83
  ]
81
84
 
82
85
  if s.respond_to? :specification_version then
@@ -84,39 +87,87 @@ Gem::Specification.new do |s|
84
87
  s.specification_version = 3
85
88
 
86
89
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
90
+ s.add_runtime_dependency(%q<commander>, ["~> 4.0.3"])
91
+ s.add_runtime_dependency(%q<terminal-table>, ["~> 1.4.2"])
92
+ s.add_runtime_dependency(%q<json>, ["~> 1.4.6"])
93
+ s.add_runtime_dependency(%q<net-ssh>, ["~> 2.0.23"])
94
+ s.add_runtime_dependency(%q<net-scp>, ["~> 1.0.4"])
95
+ s.add_runtime_dependency(%q<builder>, ["~> 2.1.2"])
96
+ s.add_runtime_dependency(%q<treetop>, ["~> 1.4.8"])
97
+ s.add_runtime_dependency(%q<fastthread>, ["~> 1.0.7"])
98
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
99
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
100
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
101
+ s.add_development_dependency(%q<rcov>, [">= 0"])
102
+ s.add_development_dependency(%q<xml-simple>, ["~> 1.0.12"])
103
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
87
104
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
88
- s.add_development_dependency(%q<jeweler>, [">= 1.4.0"])
105
+ s.add_development_dependency(%q<jeweler>, [">= 1.5.1"])
89
106
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
90
107
  s.add_development_dependency(%q<xml-simple>, [">= 1.0.12"])
91
108
  s.add_runtime_dependency(%q<commander>, [">= 4.0.3"])
92
109
  s.add_runtime_dependency(%q<terminal-table>, [">= 1.4.2"])
110
+ s.add_runtime_dependency(%q<json>, [">= 1.4.6"])
93
111
  s.add_runtime_dependency(%q<net-ssh>, [">= 2.0.23"])
94
112
  s.add_runtime_dependency(%q<net-scp>, [">= 1.0.4"])
95
113
  s.add_runtime_dependency(%q<builder>, [">= 2.1.2"])
96
114
  s.add_runtime_dependency(%q<treetop>, [">= 1.4.8"])
115
+ s.add_runtime_dependency(%q<fastthread>, [">= 1.0.7"])
97
116
  else
117
+ s.add_dependency(%q<commander>, ["~> 4.0.3"])
118
+ s.add_dependency(%q<terminal-table>, ["~> 1.4.2"])
119
+ s.add_dependency(%q<json>, ["~> 1.4.6"])
120
+ s.add_dependency(%q<net-ssh>, ["~> 2.0.23"])
121
+ s.add_dependency(%q<net-scp>, ["~> 1.0.4"])
122
+ s.add_dependency(%q<builder>, ["~> 2.1.2"])
123
+ s.add_dependency(%q<treetop>, ["~> 1.4.8"])
124
+ s.add_dependency(%q<fastthread>, ["~> 1.0.7"])
125
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
126
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
127
+ s.add_dependency(%q<shoulda>, [">= 0"])
128
+ s.add_dependency(%q<rcov>, [">= 0"])
129
+ s.add_dependency(%q<xml-simple>, ["~> 1.0.12"])
130
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
98
131
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
99
- s.add_dependency(%q<jeweler>, [">= 1.4.0"])
132
+ s.add_dependency(%q<jeweler>, [">= 1.5.1"])
100
133
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
101
134
  s.add_dependency(%q<xml-simple>, [">= 1.0.12"])
102
135
  s.add_dependency(%q<commander>, [">= 4.0.3"])
103
136
  s.add_dependency(%q<terminal-table>, [">= 1.4.2"])
137
+ s.add_dependency(%q<json>, [">= 1.4.6"])
104
138
  s.add_dependency(%q<net-ssh>, [">= 2.0.23"])
105
139
  s.add_dependency(%q<net-scp>, [">= 1.0.4"])
106
140
  s.add_dependency(%q<builder>, [">= 2.1.2"])
107
141
  s.add_dependency(%q<treetop>, [">= 1.4.8"])
142
+ s.add_dependency(%q<fastthread>, [">= 1.0.7"])
108
143
  end
109
144
  else
145
+ s.add_dependency(%q<commander>, ["~> 4.0.3"])
146
+ s.add_dependency(%q<terminal-table>, ["~> 1.4.2"])
147
+ s.add_dependency(%q<json>, ["~> 1.4.6"])
148
+ s.add_dependency(%q<net-ssh>, ["~> 2.0.23"])
149
+ s.add_dependency(%q<net-scp>, ["~> 1.0.4"])
150
+ s.add_dependency(%q<builder>, ["~> 2.1.2"])
151
+ s.add_dependency(%q<treetop>, ["~> 1.4.8"])
152
+ s.add_dependency(%q<fastthread>, ["~> 1.0.7"])
153
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
154
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
155
+ s.add_dependency(%q<shoulda>, [">= 0"])
156
+ s.add_dependency(%q<rcov>, [">= 0"])
157
+ s.add_dependency(%q<xml-simple>, ["~> 1.0.12"])
158
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
110
159
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
111
- s.add_dependency(%q<jeweler>, [">= 1.4.0"])
160
+ s.add_dependency(%q<jeweler>, [">= 1.5.1"])
112
161
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
113
162
  s.add_dependency(%q<xml-simple>, [">= 1.0.12"])
114
163
  s.add_dependency(%q<commander>, [">= 4.0.3"])
115
164
  s.add_dependency(%q<terminal-table>, [">= 1.4.2"])
165
+ s.add_dependency(%q<json>, [">= 1.4.6"])
116
166
  s.add_dependency(%q<net-ssh>, [">= 2.0.23"])
117
167
  s.add_dependency(%q<net-scp>, [">= 1.0.4"])
118
168
  s.add_dependency(%q<builder>, [">= 2.1.2"])
119
169
  s.add_dependency(%q<treetop>, [">= 1.4.8"])
170
+ s.add_dependency(%q<fastthread>, [">= 1.0.7"])
120
171
  end
121
172
  end
122
173