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,300 @@
1
+ require 'digest/sha1'
2
+
3
+ module Cuboid
4
+ module Support::Database
5
+
6
+ # Flat-file Hash implementation
7
+ #
8
+ # Behaves pretty much like a Ruby Hash however it transparently serializes and
9
+ # saves its values to the file-system under the OS's temp directory.
10
+ #
11
+ # It's not interchangeable with Ruby's Hash as it lacks a lot of the
12
+ # stdlib methods.
13
+ #
14
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
15
+ # @version 0.1
16
+ class Hash < Base
17
+
18
+ # @see Cuboid::Database::Base#initialize
19
+ def initialize( *args )
20
+ super( *args )
21
+
22
+ # holds the internal representation of the Hash
23
+ # same keys as self but the values are actually pointing to filepaths
24
+ # where the real values are being stores
25
+ @h = ::Hash.new
26
+
27
+ # holds a key-value pair of self with digests as values
28
+ # in order to allow comparisons without requiring to load
29
+ # the actual values from their files.
30
+ @eql_h = ::Hash.new
31
+ end
32
+
33
+ # Associates the given value with the given key.
34
+ #
35
+ # @param [Object] k
36
+ # Key.
37
+ # @param [Object] v
38
+ # Value.
39
+ #
40
+ # @return [Object]
41
+ # `v`.
42
+ def []=( k, v )
43
+ @h[k] = dump( v ) do |serialized|
44
+ @eql_h[k] = eql_hash( serialized )
45
+ end
46
+ end
47
+ alias :store :[]=
48
+
49
+ # @param [Obj] k key
50
+ #
51
+ # @return [Object]
52
+ # Object corresponding to the key object, `nil` otherwise.
53
+ def []( k )
54
+ load( @h[k] ) if @h[k]
55
+ end
56
+
57
+ # @param [Object] k
58
+ # Key.
59
+ #
60
+ # @return [Array]
61
+ # Array containing the given key and its value.
62
+ def assoc( k )
63
+ return if !@h[k]
64
+ [ k, self[k] ]
65
+ end
66
+
67
+ # @param [Object] v
68
+ # Value.
69
+ #
70
+ # @return [Array]
71
+ # Array containing the key for the given value and that value.
72
+ def rassoc( v )
73
+ return if !value?( v )
74
+ [ key( v ), v ]
75
+ end
76
+
77
+ # Removes an entry by key and returns its value.
78
+ #
79
+ # If the key doesn't exist and a block has been provided it's passed
80
+ # the key and the method returns the result of that block.
81
+ #
82
+ # @param [Object] k
83
+ # Key.
84
+ #
85
+ # @return [Object]
86
+ def delete( k, &block )
87
+ if @h[k]
88
+ obj = load_and_delete_file( @h[k] )
89
+ @h.delete( k )
90
+ @eql_h.delete( k )
91
+ return obj
92
+ else
93
+ block.call( k ) if block_given?
94
+ end
95
+ end
96
+
97
+ # Removes the first key-value pair from the hash and returns it as a array,
98
+ #
99
+ # @return [Array]
100
+ def shift
101
+ k, v = @h.first
102
+ [ k, delete( k ) ]
103
+ end
104
+
105
+ # Calls block with each key-value pair.
106
+ #
107
+ # If a block has been given it retuns self.
108
+ # If no block has been given it returns an enumerator.
109
+ #
110
+ # @param [Proc] block
111
+ def each( &block )
112
+ if block_given?
113
+ @h.each { |k, v| block.call( [ k, self[k] ] ) }
114
+ self
115
+ else
116
+ enum_for( :each )
117
+ end
118
+ end
119
+ alias :each_pair :each
120
+
121
+ # Calls block with each key.
122
+ #
123
+ # If a block has been given it returns self.
124
+ # If no block has been given it returns an enumerator.
125
+ #
126
+ # @param [Proc] block
127
+ def each_key( &block )
128
+ if block_given?
129
+ @h.each_key( &block )
130
+ self
131
+ else
132
+ enum_for( :each_key )
133
+ end
134
+ end
135
+
136
+ # Calls block with each value.
137
+ #
138
+ # If a block has been given it returns `self`.
139
+ # If no block has been given it returns an enumerator.
140
+ #
141
+ # @param [Proc] block
142
+ def each_value( &block )
143
+ if block_given?
144
+ @h.keys.each { |k| block.call( self[k] ) }
145
+ self
146
+ else
147
+ enum_for( :each_value )
148
+ end
149
+ end
150
+
151
+ # @return [Array]
152
+ # Keys.
153
+ def keys
154
+ @h.keys
155
+ end
156
+
157
+ # @param [Object] val
158
+ #
159
+ # @return [Object] key
160
+ # key for the given value.
161
+ def key( val )
162
+ return if !value?( val )
163
+ each { |k, v| return k if val == self[k] }
164
+ nil
165
+ end
166
+
167
+ # @return [Array]
168
+ # Values.
169
+ def values
170
+ each_value.to_a
171
+ end
172
+
173
+ # @return [Bool]
174
+ # `true` if the given key exists in the hash, `false` otherwise.
175
+ def include?( k )
176
+ @h.include?( k )
177
+ end
178
+ alias :member? :include?
179
+ alias :key? :include?
180
+ alias :has_key? :include?
181
+
182
+ # @return [Bool]
183
+ # `true` if the given value exists in the hash, `false` otherwise.
184
+ def value?( v )
185
+ each_value { |val| return true if val == v }
186
+ false
187
+ end
188
+
189
+ # Merges the contents of self with the contents of the given hash and
190
+ # returns them in a new object.
191
+ #
192
+ # @param [Hash] h
193
+ #
194
+ # @return [Cuboid::Database::Set]
195
+ def merge( h )
196
+ self.class.new( @options ).merge!( self ).merge!( h )
197
+ end
198
+
199
+ # Merges self with the contents of the given hash and returns self.
200
+ #
201
+ # If the given Hash is of the same type as self then the values will
202
+ # not be loaded during the merge in order to keep memory usage down.
203
+ #
204
+ # If the given Hash is any other kind of object it will be coerced
205
+ # to a Hash by calling 'to_hash' on it and the merging it with self.
206
+ #
207
+ # @param [Hash] h
208
+ def merge!( h )
209
+ if !h.is_a?( self.class )
210
+ h.to_hash.each do |k, v|
211
+ delete( k ) if @h.include?( k )
212
+ self[k] = v
213
+ end
214
+ else
215
+ h._internal.each do |k, v|
216
+ delete( k ) if @h.include?( k )
217
+ @h[k] = v
218
+ end
219
+ @eql_h.merge!( h._eql_h )
220
+ end
221
+ self
222
+ end
223
+ alias :update :merge!
224
+
225
+ # @return [Hash]
226
+ # `self` as Ruby Hash
227
+ def to_hash
228
+ h = {}
229
+ each { |k, v| h[k] = v }
230
+ h
231
+ end
232
+ alias :to_h :to_hash
233
+
234
+ # @return [Array]
235
+ # `self` as a Ruby Array.
236
+ def to_a
237
+ to_hash.to_a
238
+ end
239
+
240
+ # @return [Integer]
241
+ # Number of objects.
242
+ def size
243
+ @h.size
244
+ end
245
+ alias :length :size
246
+
247
+ # @return [Bool]
248
+ # `true` if the Hash if empty, `false` otherwise.
249
+ def empty?
250
+ @h.empty?
251
+ end
252
+
253
+ # Removes all objects.
254
+ def clear
255
+ @h.values.each { |filepath| delete_file( filepath ) }
256
+ @h.clear
257
+ end
258
+
259
+ # @note If the given hash is not of the same type as self it will be coerced
260
+ # to a Ruby Hash by calling 'to_hash' on it.
261
+ #
262
+ # @return [Bool]
263
+ # `true` if self and the given hash contain the same key-pair values.
264
+ def ==( h )
265
+ if !h.is_a?( self.class )
266
+ eql = {}
267
+ h.to_hash.each { |k, v| eql[k] = eql_hash( serialize( v ) ) }
268
+ @eql_h == eql
269
+ else
270
+ @eql_h == h._eql_h
271
+ end
272
+ end
273
+ alias :eql? :==
274
+
275
+ # It will return a Ruby Hash with the same values as self but
276
+ # with filepaths as values (pointing to the files that store them).
277
+ #
278
+ # This is used for efficient merging, i.e. without requiring to load
279
+ # the actual values when merging 2 objects.
280
+ #
281
+ # @return [Hash]
282
+ # Internal representation of `self`.
283
+ def _internal
284
+ @h.dup
285
+ end
286
+
287
+ def _eql_h
288
+ @eql_h.dup
289
+ end
290
+
291
+ private
292
+
293
+ def eql_hash( str )
294
+ Digest::SHA1.hexdigest( str )
295
+ end
296
+
297
+ end
298
+
299
+ end
300
+ end
@@ -0,0 +1,149 @@
1
+ module Cuboid
2
+ module Support::Database
3
+
4
+ # Flat-file Scheduler implementation
5
+ #
6
+ # Behaves pretty much like a Ruby Scheduler however it transparently serializes and
7
+ # saves its entries to the file-system under the OS's temp directory **after**
8
+ # a specified {#max_buffer_size} (for in-memory entries) has been exceeded.
9
+ #
10
+ # It's pretty useful when you want to reduce memory footprint without
11
+ # having to refactor any code since it behaves just like a Ruby Scheduler
12
+ # implementation.
13
+ #
14
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
15
+ class Queue < Base
16
+
17
+ # Default {#max_buffer_size}.
18
+ DEFAULT_MAX_BUFFER_SIZE = 100
19
+
20
+ # @return [Integer]
21
+ # How many entries to keep in memory before starting to off-load to disk.
22
+ attr_accessor :max_buffer_size
23
+
24
+ # @return [Array<Object>]
25
+ # Objects stored in the memory buffer.
26
+ attr_reader :buffer
27
+
28
+ # @return [Array<String>]
29
+ # Paths to files stored to disk.
30
+ attr_reader :disk
31
+
32
+ # @see Cuboid::Database::Base#initialize
33
+ def initialize( options = {} )
34
+ super( options )
35
+
36
+ @max_buffer_size = options[:max_buffer_size] || DEFAULT_MAX_BUFFER_SIZE
37
+
38
+ @disk = []
39
+ @buffer = []
40
+ @waiting = []
41
+ @mutex = Mutex.new
42
+ end
43
+
44
+ # @note Defaults to {DEFAULT_MAX_BUFFER_SIZE}.
45
+ #
46
+ # @return [Integer]
47
+ # How many entries to keep in memory before starting to off-load to disk.
48
+ def max_buffer_size
49
+ @max_buffer_size
50
+ end
51
+
52
+ # @param [Object] obj
53
+ # Object to add to the queue.
54
+ def <<( obj )
55
+ synchronize do
56
+ if @buffer.size < max_buffer_size
57
+ @buffer << obj
58
+ else
59
+ @disk << dump( obj )
60
+ end
61
+
62
+ begin
63
+ t = @waiting.shift
64
+ t.wakeup if t
65
+ rescue ThreadError
66
+ retry
67
+ end
68
+ end
69
+ end
70
+ alias :push :<<
71
+ alias :enq :<<
72
+
73
+ # @return [Object]
74
+ # Removes an object from the queue and returns it.
75
+ def pop( non_block = false )
76
+ synchronize do
77
+ loop do
78
+ if internal_empty?
79
+ raise ThreadError, 'queue empty' if non_block
80
+ @waiting.push Thread.current
81
+ @mutex.sleep
82
+ else
83
+ return @buffer.shift if !@buffer.empty?
84
+ return load_and_delete_file( @disk.shift )
85
+ end
86
+ end
87
+ end
88
+ end
89
+ alias :deq :pop
90
+ alias :shift :pop
91
+
92
+ # @return [Integer]
93
+ # Size of the queue, the number of objects it currently holds.
94
+ def size
95
+ buffer_size + disk_size
96
+ end
97
+ alias :length :size
98
+
99
+ def free_buffer_size
100
+ max_buffer_size - buffer_size
101
+ end
102
+
103
+ def buffer_size
104
+ @buffer.size
105
+ end
106
+
107
+ def disk_size
108
+ @disk.size
109
+ end
110
+
111
+ # @return [Bool]
112
+ # `true` if the queue if empty, `false` otherwise.
113
+ def empty?
114
+ synchronize do
115
+ internal_empty?
116
+ end
117
+ end
118
+
119
+ # Removes all objects from the queue.
120
+ def clear
121
+ synchronize do
122
+ @buffer.clear
123
+
124
+ while !@disk.empty?
125
+ path = @disk.pop
126
+ next if !path
127
+ delete_file path
128
+ end
129
+ end
130
+ end
131
+
132
+ def num_waiting
133
+ @waiting.size
134
+ end
135
+
136
+ private
137
+
138
+ def internal_empty?
139
+ @buffer.empty? && @disk.empty?
140
+ end
141
+
142
+ def synchronize( &block )
143
+ @mutex.synchronize( &block )
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+ end
@@ -0,0 +1,3 @@
1
+ lib = Cuboid::Options.paths.support + 'filter/'
2
+ require lib + 'base'
3
+ require lib + 'set'