cuboid 0.0.0 → 0.0.1alpha

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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -0
  3. data/Gemfile +20 -5
  4. data/LICENSE.md +22 -0
  5. data/README.md +158 -19
  6. data/Rakefile +56 -3
  7. data/config/paths.yml +15 -0
  8. data/cuboid.gemspec +61 -23
  9. data/lib/cuboid.rb +96 -4
  10. data/lib/cuboid/application.rb +326 -0
  11. data/lib/cuboid/application/parts/data.rb +18 -0
  12. data/lib/cuboid/application/parts/report.rb +29 -0
  13. data/lib/cuboid/application/parts/state.rb +274 -0
  14. data/lib/cuboid/application/runtime.rb +25 -0
  15. data/lib/cuboid/banner.rb +13 -0
  16. data/lib/cuboid/data.rb +86 -0
  17. data/lib/cuboid/data/application.rb +52 -0
  18. data/lib/cuboid/error.rb +9 -0
  19. data/lib/cuboid/option_group.rb +129 -0
  20. data/lib/cuboid/option_groups.rb +8 -0
  21. data/lib/cuboid/option_groups/datastore.rb +23 -0
  22. data/lib/cuboid/option_groups/dispatcher.rb +38 -0
  23. data/lib/cuboid/option_groups/output.rb +14 -0
  24. data/lib/cuboid/option_groups/paths.rb +184 -0
  25. data/lib/cuboid/option_groups/report.rb +39 -0
  26. data/lib/cuboid/option_groups/rpc.rb +105 -0
  27. data/lib/cuboid/option_groups/scheduler.rb +27 -0
  28. data/lib/cuboid/option_groups/snapshot.rb +13 -0
  29. data/lib/cuboid/option_groups/system.rb +10 -0
  30. data/lib/cuboid/options.rb +254 -0
  31. data/lib/cuboid/processes.rb +13 -0
  32. data/lib/cuboid/processes/dispatchers.rb +140 -0
  33. data/lib/cuboid/processes/executables/base.rb +54 -0
  34. data/lib/cuboid/processes/executables/dispatcher.rb +5 -0
  35. data/lib/cuboid/processes/executables/instance.rb +12 -0
  36. data/lib/cuboid/processes/executables/rest_service.rb +13 -0
  37. data/lib/cuboid/processes/executables/scheduler.rb +5 -0
  38. data/lib/cuboid/processes/helpers.rb +4 -0
  39. data/lib/cuboid/processes/helpers/dispatchers.rb +23 -0
  40. data/lib/cuboid/processes/helpers/instances.rb +39 -0
  41. data/lib/cuboid/processes/helpers/processes.rb +23 -0
  42. data/lib/cuboid/processes/helpers/schedulers.rb +23 -0
  43. data/lib/cuboid/processes/instances.rb +203 -0
  44. data/lib/cuboid/processes/manager.rb +262 -0
  45. data/lib/cuboid/processes/schedulers.rb +128 -0
  46. data/lib/cuboid/report.rb +220 -0
  47. data/lib/cuboid/rest/server.rb +165 -0
  48. data/lib/cuboid/rest/server/instance_helpers.rb +99 -0
  49. data/lib/cuboid/rest/server/routes/dispatcher.rb +41 -0
  50. data/lib/cuboid/rest/server/routes/grid.rb +41 -0
  51. data/lib/cuboid/rest/server/routes/instances.rb +131 -0
  52. data/lib/cuboid/rest/server/routes/scheduler.rb +140 -0
  53. data/lib/cuboid/rpc/client.rb +3 -0
  54. data/lib/cuboid/rpc/client/base.rb +58 -0
  55. data/lib/cuboid/rpc/client/dispatcher.rb +58 -0
  56. data/lib/cuboid/rpc/client/instance.rb +100 -0
  57. data/lib/cuboid/rpc/client/instance/service.rb +37 -0
  58. data/lib/cuboid/rpc/client/scheduler.rb +46 -0
  59. data/lib/cuboid/rpc/serializer.rb +92 -0
  60. data/lib/cuboid/rpc/server/active_options.rb +38 -0
  61. data/lib/cuboid/rpc/server/application_wrapper.rb +138 -0
  62. data/lib/cuboid/rpc/server/base.rb +63 -0
  63. data/lib/cuboid/rpc/server/dispatcher.rb +317 -0
  64. data/lib/cuboid/rpc/server/dispatcher/node.rb +247 -0
  65. data/lib/cuboid/rpc/server/dispatcher/service.rb +145 -0
  66. data/lib/cuboid/rpc/server/instance.rb +338 -0
  67. data/lib/cuboid/rpc/server/output.rb +92 -0
  68. data/lib/cuboid/rpc/server/scheduler.rb +482 -0
  69. data/lib/cuboid/ruby.rb +4 -0
  70. data/lib/cuboid/ruby/array.rb +17 -0
  71. data/lib/cuboid/ruby/hash.rb +41 -0
  72. data/lib/cuboid/ruby/object.rb +32 -0
  73. data/lib/cuboid/snapshot.rb +186 -0
  74. data/lib/cuboid/state.rb +94 -0
  75. data/lib/cuboid/state/application.rb +309 -0
  76. data/lib/cuboid/state/options.rb +27 -0
  77. data/lib/cuboid/support.rb +11 -0
  78. data/lib/cuboid/support/buffer.rb +3 -0
  79. data/lib/cuboid/support/buffer/autoflush.rb +61 -0
  80. data/lib/cuboid/support/buffer/base.rb +91 -0
  81. data/lib/cuboid/support/cache.rb +7 -0
  82. data/lib/cuboid/support/cache/base.rb +226 -0
  83. data/lib/cuboid/support/cache/least_cost_replacement.rb +77 -0
  84. data/lib/cuboid/support/cache/least_recently_pushed.rb +21 -0
  85. data/lib/cuboid/support/cache/least_recently_used.rb +31 -0
  86. data/lib/cuboid/support/cache/preference.rb +31 -0
  87. data/lib/cuboid/support/cache/random_replacement.rb +20 -0
  88. data/lib/cuboid/support/crypto.rb +2 -0
  89. data/lib/cuboid/support/crypto/rsa_aes_cbc.rb +86 -0
  90. data/lib/cuboid/support/database.rb +5 -0
  91. data/lib/cuboid/support/database/base.rb +177 -0
  92. data/lib/cuboid/support/database/categorized_queue.rb +195 -0
  93. data/lib/cuboid/support/database/hash.rb +300 -0
  94. data/lib/cuboid/support/database/queue.rb +149 -0
  95. data/lib/cuboid/support/filter.rb +3 -0
  96. data/lib/cuboid/support/filter/base.rb +110 -0
  97. data/lib/cuboid/support/filter/set.rb +29 -0
  98. data/lib/cuboid/support/glob.rb +27 -0
  99. data/lib/cuboid/support/mixins.rb +8 -0
  100. data/lib/cuboid/support/mixins/observable.rb +99 -0
  101. data/lib/cuboid/support/mixins/parts.rb +20 -0
  102. data/lib/cuboid/support/mixins/profiler.rb +93 -0
  103. data/lib/cuboid/support/mixins/spec_instances.rb +65 -0
  104. data/lib/cuboid/support/mixins/terminal.rb +57 -0
  105. data/lib/cuboid/system.rb +119 -0
  106. data/lib/cuboid/system/platforms.rb +84 -0
  107. data/lib/cuboid/system/platforms/linux.rb +26 -0
  108. data/lib/cuboid/system/platforms/mixins/unix.rb +46 -0
  109. data/lib/cuboid/system/platforms/osx.rb +25 -0
  110. data/lib/cuboid/system/platforms/windows.rb +81 -0
  111. data/lib/cuboid/system/slots.rb +143 -0
  112. data/lib/cuboid/ui/output.rb +52 -0
  113. data/lib/cuboid/ui/output_interface.rb +43 -0
  114. data/lib/cuboid/ui/output_interface/abstract.rb +68 -0
  115. data/lib/cuboid/ui/output_interface/controls.rb +84 -0
  116. data/lib/cuboid/ui/output_interface/error_logging.rb +119 -0
  117. data/lib/cuboid/ui/output_interface/implemented.rb +58 -0
  118. data/lib/cuboid/ui/output_interface/personalization.rb +62 -0
  119. data/lib/cuboid/utilities.rb +155 -0
  120. data/lib/cuboid/version.rb +4 -3
  121. data/lib/version +1 -0
  122. data/logs/placeholder +0 -0
  123. data/spec/cuboid/application/parts/data_spec.rb +12 -0
  124. data/spec/cuboid/application/parts/report_spec.rb +6 -0
  125. data/spec/cuboid/application/parts/state_spec.rb +192 -0
  126. data/spec/cuboid/application/runtime_spec.rb +21 -0
  127. data/spec/cuboid/application_spec.rb +37 -0
  128. data/spec/cuboid/data/application_spec.rb +22 -0
  129. data/spec/cuboid/data_spec.rb +47 -0
  130. data/spec/cuboid/error_spec.rb +23 -0
  131. data/spec/cuboid/option_groups/datastore_spec.rb +54 -0
  132. data/spec/cuboid/option_groups/dispatcher_spec.rb +12 -0
  133. data/spec/cuboid/option_groups/output_spec.rb +11 -0
  134. data/spec/cuboid/option_groups/paths_spec.rb +184 -0
  135. data/spec/cuboid/option_groups/report_spec.rb +26 -0
  136. data/spec/cuboid/option_groups/rpc_spec.rb +53 -0
  137. data/spec/cuboid/option_groups/snapshot_spec.rb +26 -0
  138. data/spec/cuboid/option_groups/system.rb +12 -0
  139. data/spec/cuboid/options_spec.rb +218 -0
  140. data/spec/cuboid/report_spec.rb +221 -0
  141. data/spec/cuboid/rest/server_spec.rb +1205 -0
  142. data/spec/cuboid/rpc/client/base_spec.rb +151 -0
  143. data/spec/cuboid/rpc/client/dispatcher_spec.rb +13 -0
  144. data/spec/cuboid/rpc/client/instance_spec.rb +38 -0
  145. data/spec/cuboid/rpc/server/active_options_spec.rb +21 -0
  146. data/spec/cuboid/rpc/server/base_spec.rb +60 -0
  147. data/spec/cuboid/rpc/server/dispatcher/node_spec.rb +222 -0
  148. data/spec/cuboid/rpc/server/dispatcher/service_spec.rb +112 -0
  149. data/spec/cuboid/rpc/server/dispatcher_spec.rb +317 -0
  150. data/spec/cuboid/rpc/server/instance_spec.rb +307 -0
  151. data/spec/cuboid/rpc/server/output_spec.rb +32 -0
  152. data/spec/cuboid/rpc/server/scheduler_spec.rb +400 -0
  153. data/spec/cuboid/ruby/array_spec.rb +77 -0
  154. data/spec/cuboid/ruby/hash_spec.rb +63 -0
  155. data/spec/cuboid/ruby/object_spec.rb +22 -0
  156. data/spec/cuboid/snapshot_spec.rb +123 -0
  157. data/spec/cuboid/state/application_spec.rb +538 -0
  158. data/spec/cuboid/state/options_spec.rb +37 -0
  159. data/spec/cuboid/state_spec.rb +53 -0
  160. data/spec/cuboid/support/buffer/autoflush_spec.rb +78 -0
  161. data/spec/cuboid/support/buffer/base_spec.rb +193 -0
  162. data/spec/cuboid/support/cache/least_cost_replacement_spec.rb +61 -0
  163. data/spec/cuboid/support/cache/least_recently_pushed_spec.rb +90 -0
  164. data/spec/cuboid/support/cache/least_recently_used_spec.rb +80 -0
  165. data/spec/cuboid/support/cache/preference_spec.rb +37 -0
  166. data/spec/cuboid/support/cache/random_replacement_spec.rb +42 -0
  167. data/spec/cuboid/support/crypto/rsa_aes_cbc_spec.rb +28 -0
  168. data/spec/cuboid/support/database/categorized_queue_spec.rb +327 -0
  169. data/spec/cuboid/support/database/hash_spec.rb +204 -0
  170. data/spec/cuboid/support/database/scheduler_spec.rb +325 -0
  171. data/spec/cuboid/support/filter/set_spec.rb +19 -0
  172. data/spec/cuboid/support/glob_spec.rb +75 -0
  173. data/spec/cuboid/support/mixins/observable_spec.rb +95 -0
  174. data/spec/cuboid/system/platforms/linux_spec.rb +31 -0
  175. data/spec/cuboid/system/platforms/osx_spec.rb +32 -0
  176. data/spec/cuboid/system/platforms/windows_spec.rb +41 -0
  177. data/spec/cuboid/system/slots_spec.rb +202 -0
  178. data/spec/cuboid/system_spec.rb +105 -0
  179. data/spec/cuboid/utilities_spec.rb +131 -0
  180. data/spec/spec_helper.rb +46 -0
  181. data/spec/support/factories/placeholder +0 -0
  182. data/spec/support/factories/scan_report.rb +18 -0
  183. data/spec/support/fixtures/empty/placeholder +0 -0
  184. data/spec/support/fixtures/executables/node.rb +50 -0
  185. data/spec/support/fixtures/mock_app.rb +61 -0
  186. data/spec/support/fixtures/mock_app/test_service.rb +64 -0
  187. data/spec/support/fixtures/services/echo.rb +64 -0
  188. data/spec/support/helpers/framework.rb +3 -0
  189. data/spec/support/helpers/matchers.rb +5 -0
  190. data/spec/support/helpers/misc.rb +3 -0
  191. data/spec/support/helpers/paths.rb +15 -0
  192. data/spec/support/helpers/request_helpers.rb +38 -0
  193. data/spec/support/helpers/requires.rb +8 -0
  194. data/spec/support/helpers/resets.rb +52 -0
  195. data/spec/support/helpers/web_server.rb +15 -0
  196. data/spec/support/lib/factory.rb +107 -0
  197. data/spec/support/lib/web_server_client.rb +41 -0
  198. data/spec/support/lib/web_server_dispatcher.rb +25 -0
  199. data/spec/support/lib/web_server_manager.rb +118 -0
  200. data/spec/support/logs/placeholder +0 -0
  201. data/spec/support/pems/cacert.pem +37 -0
  202. data/spec/support/pems/client/cert.pem +37 -0
  203. data/spec/support/pems/client/foo-cert.pem +39 -0
  204. data/spec/support/pems/client/foo-key.pem +51 -0
  205. data/spec/support/pems/client/key.pem +51 -0
  206. data/spec/support/pems/server/cert.pem +37 -0
  207. data/spec/support/pems/server/key.pem +51 -0
  208. data/spec/support/reports/placeholder +0 -0
  209. data/spec/support/shared/application.rb +10 -0
  210. data/spec/support/shared/component.rb +31 -0
  211. data/spec/support/shared/component/options/base.rb +187 -0
  212. data/spec/support/shared/option_group.rb +98 -0
  213. data/spec/support/shared/support/cache.rb +419 -0
  214. data/spec/support/shared/support/filter.rb +143 -0
  215. data/spec/support/shared/system/platforms/base.rb +25 -0
  216. data/spec/support/shared/system/platforms/mixins/unix.rb +37 -0
  217. data/spec/support/snapshots/placeholder +0 -0
  218. metadata +566 -21
  219. data/.gitignore +0 -8
  220. data/bin/console +0 -15
  221. data/bin/setup +0 -8
@@ -0,0 +1,326 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'monitor'
5
+ require 'bundler/setup'
6
+
7
+ require_relative 'options'
8
+
9
+ module Cuboid
10
+
11
+ lib = Options.paths.lib
12
+ require lib + 'support/mixins/spec_instances'
13
+ require lib + 'system'
14
+ require lib + 'version'
15
+ require lib + 'support'
16
+ require lib + 'ruby'
17
+ require lib + 'error'
18
+ require lib + 'utilities'
19
+ require lib + 'snapshot'
20
+ require lib + 'report'
21
+ require lib + 'processes'
22
+ require lib + 'application/runtime'
23
+
24
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
25
+ class Application
26
+ include Singleton
27
+
28
+ module PrependMethods
29
+
30
+ def run
31
+ if !self.class.valid_options?( options )
32
+ fail ArgumentError, 'Invalid options!'
33
+ end
34
+
35
+ prepare
36
+ return if aborted? || suspended?
37
+
38
+ state.status = :running
39
+
40
+ super if defined? super
41
+
42
+ return if aborted? || suspended?
43
+
44
+ clean_up
45
+ state.status = :done
46
+
47
+ true
48
+ end
49
+
50
+ # Cleans up the framework; should be called after running the audit or
51
+ # after canceling a running scan.
52
+ def clean_up
53
+ return if @cleaned_up
54
+ @cleaned_up = true
55
+
56
+ state.resume
57
+
58
+ state.status = :cleanup
59
+
60
+ @finish_datetime = Time.now
61
+ @start_datetime ||= Time.now
62
+
63
+ state.running = false
64
+
65
+ super if defined? super
66
+
67
+ true
68
+ end
69
+
70
+ private
71
+
72
+ # @note Must be called before calling any audit methods.
73
+ #
74
+ # Prepares the framework for the audit.
75
+ #
76
+ # * Sets the status to `:preparing`.
77
+ # * Starts the clock.
78
+ def prepare
79
+ state.status = :preparing
80
+ state.running = true
81
+ @start_datetime = Time.now
82
+
83
+ super if defined? super
84
+ end
85
+
86
+ end
87
+
88
+ class <<self
89
+
90
+ def provision_cores( cores )
91
+ @max_cores = cores
92
+ end
93
+
94
+ def max_cores
95
+ @max_cores ||= 0
96
+ end
97
+
98
+ def provision_memory( ram )
99
+ @max_memory = ram
100
+ end
101
+
102
+ def max_memory
103
+ @max_memory ||= 0
104
+ end
105
+
106
+ def provision_disk( ram )
107
+ @max_disk = ram
108
+ end
109
+
110
+ def max_disk
111
+ @max_memory ||= 0
112
+ end
113
+
114
+ def instance_service_for(name, service )
115
+ instance_services[name] = service
116
+ end
117
+
118
+ def instance_services
119
+ @instance_services ||= {}
120
+ end
121
+
122
+ def rest_service_for( name, service )
123
+ rest_services[name] = service
124
+ end
125
+
126
+ def rest_services
127
+ @rest_services ||= {}
128
+ end
129
+
130
+ def dispatcher_service_for( name, service )
131
+ dispatcher_services[name] = service
132
+ end
133
+
134
+ def dispatcher_services
135
+ @dispatcher_services ||= {}
136
+ end
137
+
138
+ def handler_for( signal, handler )
139
+ signal_handlers[signal] = handler
140
+ end
141
+
142
+ def signal_handlers
143
+ @signal_handlers ||= {}
144
+ end
145
+
146
+ def serialize_with( serializer)
147
+ @serializer = serializer
148
+ end
149
+
150
+ def serializer
151
+ @serializer ||= nil
152
+ @serializer || RPC::Serializer
153
+ end
154
+
155
+ def validate_options_with( handler )
156
+ @validate_options_with = handler
157
+ end
158
+
159
+ def valid_options?( options )
160
+ @validate_options_with ||= nil
161
+ if @validate_options_with
162
+ return instance.method( @validate_options_with ).call( options )
163
+ end
164
+
165
+ true
166
+ end
167
+
168
+ def source_location
169
+ splits = self.to_s.split ( '::' )
170
+ app = splits.pop
171
+
172
+ last_const = Object
173
+ splits.each do |const_name|
174
+ last_const = last_const.const_get( const_name.to_sym )
175
+ end
176
+
177
+ last_const.const_source_location( app.to_sym ).first
178
+ end
179
+
180
+ def spawn( type, options = {}, &block )
181
+ const = nil
182
+
183
+ case type
184
+ when :instance
185
+ const = :Instances
186
+ when :dispatcher
187
+ const = :Dispatchers
188
+ when :scheduler
189
+ const = :Schedulers
190
+ when :rest
191
+ return Processes::Manager.spawn(
192
+ :rest_service,
193
+ options.merge( options: { paths: { application: source_location } } ),
194
+ &block
195
+ )
196
+ end
197
+
198
+ Processes.const_get( const ).spawn(
199
+ options.merge( application: source_location ),
200
+ &block
201
+ )
202
+ end
203
+
204
+ def connect( info )
205
+ info = info.my_symbolize_keys
206
+ Processes::Instances.connect( info[:url], info[:token] )
207
+ end
208
+
209
+ def inherited( application )
210
+ super
211
+
212
+ application.prepend PrependMethods
213
+ @application = application
214
+ end
215
+
216
+ def application
217
+ @application ||= nil
218
+ end
219
+
220
+ def method_missing( sym, *args, &block )
221
+ if instance.respond_to?( sym )
222
+ instance.send( sym, *args, &block )
223
+ else
224
+ super( sym, *args, &block )
225
+ end
226
+ end
227
+
228
+ def respond_to?( *args )
229
+ super || instance.respond_to?( *args )
230
+ end
231
+
232
+ end
233
+
234
+ include UI::Output
235
+ include Utilities
236
+
237
+ prepend Support::Mixins::SpecInstances
238
+ include Support::Mixins::Observable
239
+ include Support::Mixins::Parts
240
+
241
+ # {Framework} error namespace.
242
+ #
243
+ # All {Framework} errors inherit from and live under it.
244
+ #
245
+ # When I say Framework I mean the {Framework} class, not the entire Engine
246
+ # Framework.
247
+ #
248
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
249
+ class Error < Cuboid::Error
250
+ end
251
+
252
+ def initialize
253
+ super
254
+
255
+ @runtime = Runtime.new
256
+ end
257
+
258
+ def runtime
259
+ @runtime
260
+ end
261
+
262
+ def options=( opts )
263
+ Options.application = opts
264
+ end
265
+
266
+ def options
267
+ Options.application
268
+ end
269
+
270
+ # @return [Hash]
271
+ #
272
+ # Framework statistics:
273
+ #
274
+ # * `:runtime` -- Scan runtime in seconds.
275
+ def statistics
276
+ {
277
+ runtime: @start_datetime ? (@finish_datetime || Time.now) - @start_datetime : 0,
278
+ }
279
+ end
280
+
281
+ def inspect
282
+ stats = statistics
283
+
284
+ s = "#<#{self.class} (#{status}) "
285
+ s << "runtime=#{stats[:runtime]} "
286
+ s << '>'
287
+ end
288
+
289
+ # @return [String]
290
+ # Returns the version of the framework.
291
+ def version
292
+ Cuboid::VERSION
293
+ end
294
+
295
+ def self._spec_instance_cleanup( i )
296
+ # i.clean_up
297
+ i.reset
298
+ end
299
+
300
+ def unsafe
301
+ self
302
+ end
303
+
304
+ def application
305
+ Cuboid::Application.application
306
+ end
307
+
308
+ def serializer
309
+ self.class.serializer
310
+ end
311
+
312
+ def safe( &block )
313
+ raise ArgumentError, 'Missing block.' if !block_given?
314
+
315
+ begin
316
+ block.call self
317
+ ensure
318
+ clean_up
319
+ reset
320
+ end
321
+
322
+ nil
323
+ end
324
+ end
325
+
326
+ end
@@ -0,0 +1,18 @@
1
+ module Cuboid
2
+ class Application
3
+ module Parts
4
+ # Provides access to {Cuboid::Data::Framework} and helpers.
5
+ #
6
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
7
+ module Data
8
+
9
+ # @return [Data::Application]
10
+ def data
11
+ Cuboid::Data.application
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ module Cuboid
2
+ class Application
3
+ module Parts
4
+
5
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
6
+ module Report
7
+
8
+ def report( results )
9
+ data.report = results
10
+ end
11
+
12
+ # @return [Cuboid::Report]
13
+ # Scan results.
14
+ def generate_report
15
+ Cuboid::Report.new(
16
+ application: self.class,
17
+ status: state.status,
18
+ options: Options.application,
19
+ data: data.report,
20
+ start_datetime: @start_datetime,
21
+ finish_datetime: @finish_datetime
22
+ )
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,274 @@
1
+ module Cuboid
2
+ class Application
3
+ module Parts
4
+
5
+ # Provides access to {Cuboid::State::Application} and helpers.
6
+ #
7
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
8
+ module State
9
+
10
+ def self.included( base )
11
+ base.extend ClassMethods
12
+ end
13
+
14
+ module ClassMethods
15
+
16
+ # @param [String] ses
17
+ # Path to an `.ses.` (Cuboid Application Snapshot) file created by
18
+ # {#suspend}.
19
+ #
20
+ # @return [Application]
21
+ # Restored instance.
22
+ def restore!( ses, &block )
23
+ f = self.instance.restore!( ses )
24
+ block_given? ? f.safe( &block ) : f
25
+ end
26
+
27
+ # @note You should first reset {Cuboid::Options}.
28
+ #
29
+ # Resets everything and allows the framework environment to be re-used.
30
+ def reset
31
+ Cuboid::State.clear
32
+ Cuboid::Data.clear
33
+ Cuboid::Snapshot.reset
34
+
35
+ Cuboid::Support::Database::Base.reset
36
+ Cuboid::System.reset
37
+ end
38
+ end
39
+
40
+ def initialize
41
+ super
42
+
43
+ state.status = :ready
44
+ end
45
+
46
+ # @return [String]
47
+ # Provisioned {#suspend} dump file for this instance.
48
+ def snapshot_path
49
+ return @state_archive if @state_archive
50
+
51
+ default_filename =
52
+ "Cuboid #{Time.now.to_s.gsub( ':', '_' )} " <<
53
+ "#{generate_token}.#{Snapshot::EXTENSION}"
54
+
55
+ location = Cuboid::Options.snapshot.path
56
+
57
+ if !location
58
+ location = default_filename
59
+ elsif File.directory? location
60
+ location += "/#{default_filename}"
61
+ end
62
+
63
+ @state_archive ||= File.expand_path( location )
64
+ end
65
+
66
+ # @note Prefer this from {.reset} if you already have an instance.
67
+ # @note You should first reset {Cuboid::Options}.
68
+ #
69
+ # Resets everything and allows the framework to be re-used.
70
+ def reset
71
+ @state_archive = nil
72
+ @cleaned_up = false
73
+ @start_datetime = nil
74
+ @finish_datetime = nil
75
+
76
+ # This needs to happen before resetting the other components so they
77
+ # will be able to put in their hooks.
78
+ self.class.reset
79
+
80
+ clear_observers
81
+ end
82
+
83
+ # @return [State::Application]
84
+ def state
85
+ Cuboid::State.application
86
+ end
87
+
88
+ # @param [String] ses
89
+ # Path to an `.ses.` (Cuboid Application Snapshot) file created by {#suspend}.
90
+ #
91
+ # @return [Application]
92
+ # Restored instance.
93
+ def restore!( ses )
94
+ if handler = self.class.signal_handlers[:restore]
95
+ method( handler ).call
96
+ end
97
+
98
+ Snapshot.load ses
99
+
100
+ state.status = :restored
101
+
102
+ self
103
+ end
104
+
105
+ # @return [Array<String>]
106
+ # Messages providing more information about the current {#status} of
107
+ # the framework.
108
+ def status_messages
109
+ state.status_messages
110
+ end
111
+
112
+ # @return [Symbol]
113
+ # Status of the instance, possible values are (in order):
114
+ #
115
+ # * `:ready` -- {#initialize Initialised} and waiting for instructions.
116
+ # * `:preparing` -- Getting ready to start.
117
+ # * `:pausing` -- The instance is being {#pause paused} (if applicable).
118
+ # * `:paused` -- The instance has been {#pause paused} (if applicable).
119
+ # * `:suspending` -- The instance is being {#suspend suspended} (if applicable).
120
+ # * `:suspended` -- The instance has being {#suspend suspended} (if applicable).
121
+ # * `:cleanup` -- The instance is done and cleaning up.
122
+ # * `:aborted` -- The scan has been {Application::Parts::State#abort}, you can grab the
123
+ # report and shutdown.
124
+ # * `:done` -- The scan has completed, you can grab the report and shutdown.
125
+ # * `:timed_out` -- The scan was aborted due to a time-out..
126
+ def status
127
+ state.status
128
+ end
129
+
130
+ # @return [Bool]
131
+ # `true` if the framework is running, `false` otherwise. This is `true`
132
+ # even if the scan is {#paused?}.
133
+ def running?
134
+ state.running?
135
+ end
136
+
137
+ # @return [Bool]
138
+ # `true` if the framework is paused, `false` otherwise.
139
+ def paused?
140
+ state.paused?
141
+ end
142
+
143
+ # @return [Bool]
144
+ # `true` if the framework has been instructed to pause (i.e. is in the
145
+ # process of being paused or has been paused), `false` otherwise.
146
+ def pause?
147
+ state.pause?
148
+ end
149
+
150
+ # @return [Bool]
151
+ # `true` if the framework is in the process of pausing, `false` otherwise.
152
+ def pausing?
153
+ state.pausing?
154
+ end
155
+
156
+ # @return (see Cuboid::State::Application#done?)
157
+ def done?
158
+ state.done?
159
+ end
160
+
161
+ # @note Each call from a unique caller is counted as a pause request
162
+ # and in order for the system to resume **all** pause callers need to
163
+ # {#resume} it.
164
+ #
165
+ # Pauses the framework on a best effort basis.
166
+ #
167
+ # @return [Integer]
168
+ # ID identifying this pause request.
169
+ def pause!
170
+ state.pause
171
+
172
+ if handler = self.class.signal_handlers[:pause]
173
+ method( handler ).call
174
+ end
175
+
176
+ state.paused
177
+
178
+ nil
179
+ end
180
+
181
+ # @return [Bool]
182
+ # `true` if the {Application#run} has been aborted, `false` otherwise.
183
+ def aborted?
184
+ state.aborted?
185
+ end
186
+
187
+ # @return [Bool]
188
+ # `true` if the framework has been instructed to abort (i.e. is in the
189
+ # process of being aborted or has been aborted), `false` otherwise.
190
+ def abort?
191
+ state.abort?
192
+ end
193
+
194
+ # @return [Bool]
195
+ # `true` if the framework is in the process of aborting, `false` otherwise.
196
+ def aborting?
197
+ state.aborting?
198
+ end
199
+
200
+ # Aborts the {Application#run} on a best effort basis.
201
+ def abort!
202
+ state.abort
203
+
204
+ if handler = self.class.signal_handlers[:abort]
205
+ method( handler ).call
206
+ end
207
+
208
+ state.aborted
209
+ end
210
+
211
+ def resume!
212
+ state.resume
213
+
214
+ if handler = self.class.signal_handlers[:resume]
215
+ method( handler ).call
216
+ end
217
+
218
+ state.resumed
219
+ end
220
+
221
+ # Writes a {Snapshot.dump} to disk and aborts the scan.
222
+ #
223
+ # @return [String,nil]
224
+ # Path to the state file `wait` is `true`, `nil` otherwise.
225
+ def suspend!
226
+ state.suspend
227
+
228
+ if handler = self.class.signal_handlers[:suspend]
229
+ method( handler ).call
230
+ end
231
+
232
+ suspend_to_disk
233
+ state.suspended
234
+
235
+ snapshot_path
236
+ end
237
+
238
+ # @return [Bool]
239
+ # `true` if the system is in the process of being suspended, `false`
240
+ # otherwise.
241
+ def suspend?
242
+ state.suspend?
243
+ end
244
+
245
+ # @return [Bool]
246
+ # `true` if the system has been suspended, `false` otherwise.
247
+ def suspended?
248
+ state.suspended?
249
+ end
250
+
251
+ private
252
+
253
+ def wait_if_paused
254
+ state.paused if pause?
255
+ sleep 0.2 while pause? && !abort?
256
+ end
257
+
258
+ def suspend_to_disk
259
+ state.set_status_message :saving_snapshot, snapshot_path
260
+ Snapshot.dump( snapshot_path )
261
+ state.clear_status_messages
262
+
263
+ clean_up
264
+
265
+ state.set_status_message :snapshot_location, snapshot_path
266
+ print_info status_messages.first
267
+ state.suspended
268
+ end
269
+
270
+ end
271
+
272
+ end
273
+ end
274
+ end