garcun 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitattributes +17 -0
- data/.gitignore +197 -0
- data/.rspec +2 -0
- data/Gemfile +22 -0
- data/LICENSE +201 -0
- data/README.md +521 -0
- data/Rakefile +47 -0
- data/garcun.gemspec +83 -0
- data/lib/garcon.rb +290 -0
- data/lib/garcon/chef/chef_helpers.rb +343 -0
- data/lib/garcon/chef/coerce/coercer.rb +134 -0
- data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
- data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
- data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
- data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
- data/lib/garcon/chef/handler/devreporter.rb +127 -0
- data/lib/garcon/chef/log.rb +64 -0
- data/lib/garcon/chef/node.rb +100 -0
- data/lib/garcon/chef/provider/civilize.rb +209 -0
- data/lib/garcon/chef/provider/development.rb +159 -0
- data/lib/garcon/chef/provider/download.rb +420 -0
- data/lib/garcon/chef/provider/house_keeping.rb +265 -0
- data/lib/garcon/chef/provider/node_cache.rb +31 -0
- data/lib/garcon/chef/provider/partial.rb +183 -0
- data/lib/garcon/chef/provider/recovery.rb +80 -0
- data/lib/garcon/chef/provider/zip_file.rb +271 -0
- data/lib/garcon/chef/resource/attribute.rb +52 -0
- data/lib/garcon/chef/resource/base_dsl.rb +174 -0
- data/lib/garcon/chef/resource/blender.rb +140 -0
- data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
- data/lib/garcon/chef/resource/resource_name.rb +109 -0
- data/lib/garcon/chef/secret_bag.rb +204 -0
- data/lib/garcon/chef/validations.rb +76 -0
- data/lib/garcon/chef_inclusions.rb +151 -0
- data/lib/garcon/configuration.rb +138 -0
- data/lib/garcon/core_ext.rb +39 -0
- data/lib/garcon/core_ext/array.rb +27 -0
- data/lib/garcon/core_ext/binding.rb +64 -0
- data/lib/garcon/core_ext/boolean.rb +66 -0
- data/lib/garcon/core_ext/duration.rb +271 -0
- data/lib/garcon/core_ext/enumerable.rb +34 -0
- data/lib/garcon/core_ext/file.rb +127 -0
- data/lib/garcon/core_ext/filetest.rb +62 -0
- data/lib/garcon/core_ext/hash.rb +279 -0
- data/lib/garcon/core_ext/kernel.rb +159 -0
- data/lib/garcon/core_ext/lazy.rb +222 -0
- data/lib/garcon/core_ext/method_access.rb +243 -0
- data/lib/garcon/core_ext/module.rb +92 -0
- data/lib/garcon/core_ext/nil.rb +53 -0
- data/lib/garcon/core_ext/numeric.rb +44 -0
- data/lib/garcon/core_ext/object.rb +342 -0
- data/lib/garcon/core_ext/pathname.rb +152 -0
- data/lib/garcon/core_ext/process.rb +41 -0
- data/lib/garcon/core_ext/random.rb +497 -0
- data/lib/garcon/core_ext/string.rb +312 -0
- data/lib/garcon/core_ext/struct.rb +49 -0
- data/lib/garcon/core_ext/symbol.rb +170 -0
- data/lib/garcon/core_ext/time.rb +234 -0
- data/lib/garcon/exceptions.rb +101 -0
- data/lib/garcon/inflections.rb +237 -0
- data/lib/garcon/inflections/defaults.rb +79 -0
- data/lib/garcon/inflections/inflections.rb +182 -0
- data/lib/garcon/inflections/rules_collection.rb +37 -0
- data/lib/garcon/secret.rb +271 -0
- data/lib/garcon/stash/format.rb +114 -0
- data/lib/garcon/stash/journal.rb +226 -0
- data/lib/garcon/stash/queue.rb +83 -0
- data/lib/garcon/stash/serializer.rb +86 -0
- data/lib/garcon/stash/store.rb +435 -0
- data/lib/garcon/task.rb +31 -0
- data/lib/garcon/task/atomic.rb +151 -0
- data/lib/garcon/task/atomic_boolean.rb +127 -0
- data/lib/garcon/task/condition.rb +99 -0
- data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
- data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
- data/lib/garcon/task/count_down_latch.rb +92 -0
- data/lib/garcon/task/delay.rb +196 -0
- data/lib/garcon/task/dereferenceable.rb +144 -0
- data/lib/garcon/task/event.rb +119 -0
- data/lib/garcon/task/executor.rb +275 -0
- data/lib/garcon/task/executor_options.rb +59 -0
- data/lib/garcon/task/future.rb +107 -0
- data/lib/garcon/task/immediate_executor.rb +84 -0
- data/lib/garcon/task/ivar.rb +171 -0
- data/lib/garcon/task/lazy_reference.rb +74 -0
- data/lib/garcon/task/monotonic_time.rb +69 -0
- data/lib/garcon/task/obligation.rb +256 -0
- data/lib/garcon/task/observable.rb +101 -0
- data/lib/garcon/task/priority_queue.rb +234 -0
- data/lib/garcon/task/processor_count.rb +128 -0
- data/lib/garcon/task/read_write_lock.rb +304 -0
- data/lib/garcon/task/safe_task_executor.rb +58 -0
- data/lib/garcon/task/single_thread_executor.rb +97 -0
- data/lib/garcon/task/thread_pool/cached.rb +71 -0
- data/lib/garcon/task/thread_pool/executor.rb +294 -0
- data/lib/garcon/task/thread_pool/fixed.rb +61 -0
- data/lib/garcon/task/thread_pool/worker.rb +90 -0
- data/lib/garcon/task/timer.rb +44 -0
- data/lib/garcon/task/timer_set.rb +194 -0
- data/lib/garcon/task/timer_task.rb +377 -0
- data/lib/garcon/task/waitable_list.rb +58 -0
- data/lib/garcon/utility/ansi.rb +199 -0
- data/lib/garcon/utility/at_random.rb +77 -0
- data/lib/garcon/utility/crypto.rb +292 -0
- data/lib/garcon/utility/equalizer.rb +146 -0
- data/lib/garcon/utility/faker/extensions/array.rb +22 -0
- data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
- data/lib/garcon/utility/faker/faker.rb +164 -0
- data/lib/garcon/utility/faker/faker/company.rb +17 -0
- data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
- data/lib/garcon/utility/faker/faker/version.rb +3 -0
- data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
- data/lib/garcon/utility/faker/locales/en.yml +21 -0
- data/lib/garcon/utility/file_helper.rb +170 -0
- data/lib/garcon/utility/hookers.rb +178 -0
- data/lib/garcon/utility/interpolation.rb +90 -0
- data/lib/garcon/utility/memstash.rb +364 -0
- data/lib/garcon/utility/misc.rb +54 -0
- data/lib/garcon/utility/msg_from_god.rb +62 -0
- data/lib/garcon/utility/retry.rb +238 -0
- data/lib/garcon/utility/timeout.rb +58 -0
- data/lib/garcon/utility/uber/builder.rb +91 -0
- data/lib/garcon/utility/uber/callable.rb +7 -0
- data/lib/garcon/utility/uber/delegates.rb +13 -0
- data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
- data/lib/garcon/utility/uber/options.rb +101 -0
- data/lib/garcon/utility/uber/uber_version.rb +3 -0
- data/lib/garcon/utility/uber/version.rb +33 -0
- data/lib/garcon/utility/url_helper.rb +100 -0
- data/lib/garcon/utils.rb +29 -0
- data/lib/garcon/version.rb +62 -0
- data/lib/garcun.rb +24 -0
- metadata +680 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
#
|
|
5
|
+
# Copyright (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
require_relative '../core_ext/method_access'
|
|
21
|
+
|
|
22
|
+
module Garcon
|
|
23
|
+
# Hash that allows you to access keys of the hash via method calls This gives
|
|
24
|
+
# you an OStruct like way to access your hash's keys. It will recognize keys
|
|
25
|
+
# either as strings or symbols.
|
|
26
|
+
#
|
|
27
|
+
class StashCache < Hash
|
|
28
|
+
include Garcon::Extensions::MethodAccess
|
|
29
|
+
include Garcon::Extensions::PrettyInspect
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# In-process cache with least-recently used (LRU) and time-to-live (TTL)
|
|
33
|
+
# expiration semantics. This implementation is thread-safe. It does not use
|
|
34
|
+
# a thread to clean up expired values. Instead, an expiration check is
|
|
35
|
+
# performed:
|
|
36
|
+
#
|
|
37
|
+
# 1. Every time you retrieve a value, against that value. If the value has
|
|
38
|
+
# expired, it will be removed and `nil` will be returned.
|
|
39
|
+
#
|
|
40
|
+
# 2. Every `expire_interval` operations as the cache is used to remove all
|
|
41
|
+
# expired values up to that point.
|
|
42
|
+
#
|
|
43
|
+
# For manual expiration call {#expire!}.
|
|
44
|
+
#
|
|
45
|
+
class MemStash
|
|
46
|
+
# The maximum number of seconds an element can exist in the cache
|
|
47
|
+
# regardless of use. The element expires at this limit and will no longer
|
|
48
|
+
# be returned from the cache. The default value is 3600, or 1 hour. Setting
|
|
49
|
+
# A TTL value of 0 means no TTL eviction takes place (infinite lifetime).
|
|
50
|
+
DEFAULT_TTL_SECONDS = 3600
|
|
51
|
+
|
|
52
|
+
# The maximum number of seconds an element can exist in the cache without
|
|
53
|
+
# being accessed. The element expires at this limit and will no longer be
|
|
54
|
+
# returned from the cache. The default value is 3600, or 1 hour. Setting a
|
|
55
|
+
# TTI value of 0 means no TTI eviction takes place (infinite lifetime).
|
|
56
|
+
DEFAULT_TTI_SECONDS = 3600
|
|
57
|
+
|
|
58
|
+
# The maximum sum total number of elements (cache entries) allowed on the
|
|
59
|
+
# disk tier for the cache. If this target is exceeded, eviction occurs to
|
|
60
|
+
# bring the count within the allowed target. The default value is 1,000. A
|
|
61
|
+
# setting of 0 means that no eviction of the cache's entries takes place
|
|
62
|
+
# (infinite size is allowed), and consequently can cause the node to run
|
|
63
|
+
# out of disk space.
|
|
64
|
+
DEFAULT_MAX_ENTRIES = 1_000
|
|
65
|
+
|
|
66
|
+
# @!attribute [r] :stats
|
|
67
|
+
# @return [CacheStats] The Cache statistics.
|
|
68
|
+
attr_reader :stats
|
|
69
|
+
|
|
70
|
+
# @!attribute [r] :ttl (DEFAULT_TTL_SECONDS)
|
|
71
|
+
# @return [Integer] The time to live for an element before it expires.
|
|
72
|
+
attr_reader :ttl
|
|
73
|
+
|
|
74
|
+
# @!attribute [r] :tti (DEFAULT_TTI_SECONDS)
|
|
75
|
+
# @return [Integer] The time to idle for an element before it expires.
|
|
76
|
+
attr_reader :tti
|
|
77
|
+
|
|
78
|
+
# Initializes the cache.
|
|
79
|
+
#
|
|
80
|
+
# @param [Hash] opts
|
|
81
|
+
# The options to configure the cache.
|
|
82
|
+
#
|
|
83
|
+
# @option opts [Integer] :max_entries
|
|
84
|
+
# Maximum number of elements in the cache.
|
|
85
|
+
#
|
|
86
|
+
# @option opts [Numeric] :ttl
|
|
87
|
+
# Maximum time, in seconds, for a value to stay in the cache.
|
|
88
|
+
#
|
|
89
|
+
# @option opts [Numeric] :tti
|
|
90
|
+
# Maximum time, in seconds, for a value to stay in the cache without
|
|
91
|
+
# being accessed.
|
|
92
|
+
#
|
|
93
|
+
# @option opts [Integer] :interval
|
|
94
|
+
# Number of cache operations between calls to {#expire!}.
|
|
95
|
+
#
|
|
96
|
+
def initialize(opts = {})
|
|
97
|
+
@max_entries = opts.fetch(:max_entries, DEFAULT_MAX_ENTRIES)
|
|
98
|
+
@ttl_seconds = opts.fetch(:ttl_seconds, DEFAULT_TTL_SECONDS)
|
|
99
|
+
@tti_seconds = opts.fetch(:ttl_seconds, DEFAULT_TTI_SECONDS)
|
|
100
|
+
@interval = opts.fetch(:interval, 100)
|
|
101
|
+
@operations = 0
|
|
102
|
+
@monitor = Monitor.new
|
|
103
|
+
@stash = {}
|
|
104
|
+
@expires_at = {}
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Loads a hash of data into the stash.
|
|
108
|
+
#
|
|
109
|
+
# @param [Hash] data
|
|
110
|
+
# Hash of data with either String or Symbol keys.
|
|
111
|
+
#
|
|
112
|
+
# @return nothing.
|
|
113
|
+
#
|
|
114
|
+
def load(data)
|
|
115
|
+
@monitor.synchronize do
|
|
116
|
+
data.each do |key, value|
|
|
117
|
+
expire!
|
|
118
|
+
store(key, val)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Retrieves a value from the cache, if available and not expired, or yields
|
|
124
|
+
# to a block that calculates the value to be stored in the cache.
|
|
125
|
+
#
|
|
126
|
+
# @param [Object] key
|
|
127
|
+
# The key to look up or store at.
|
|
128
|
+
#
|
|
129
|
+
# @yield yields when the value is not present.
|
|
130
|
+
#
|
|
131
|
+
# @yieldreturn [Object]
|
|
132
|
+
# The value to store in the cache.
|
|
133
|
+
#
|
|
134
|
+
# @return [Object]
|
|
135
|
+
# The value at the key.
|
|
136
|
+
#
|
|
137
|
+
def fetch(key)
|
|
138
|
+
@monitor.synchronize do
|
|
139
|
+
found, value = get(key)
|
|
140
|
+
found ? value : store(key, yield)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Retrieves a value from the cache.
|
|
145
|
+
#
|
|
146
|
+
# @param [Object] key
|
|
147
|
+
# The key to look up.
|
|
148
|
+
#
|
|
149
|
+
# @return [Object, nil]
|
|
150
|
+
# The value at the key, when present, or `nil`.
|
|
151
|
+
#
|
|
152
|
+
def [](key)
|
|
153
|
+
@monitor.synchronize do
|
|
154
|
+
_, value = get(key)
|
|
155
|
+
value
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
alias_method :get, :[]
|
|
159
|
+
|
|
160
|
+
# Stores a value in the cache.
|
|
161
|
+
#
|
|
162
|
+
# @param [Object] key
|
|
163
|
+
# The key to store.
|
|
164
|
+
#
|
|
165
|
+
# @param val [Object]
|
|
166
|
+
# The value to store.
|
|
167
|
+
#
|
|
168
|
+
# @return [Object, nil]
|
|
169
|
+
# The value at the key.
|
|
170
|
+
#
|
|
171
|
+
def []=(key, val)
|
|
172
|
+
@monitor.synchronize do
|
|
173
|
+
expire!
|
|
174
|
+
store(key, val)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
alias_method :set, :[]=
|
|
178
|
+
|
|
179
|
+
# Removes a value from the cache.
|
|
180
|
+
#
|
|
181
|
+
# @param [Object] key
|
|
182
|
+
# The key to remove.
|
|
183
|
+
#
|
|
184
|
+
# @return [Object, nil]
|
|
185
|
+
# The value at the key, when present, or `nil`.
|
|
186
|
+
#
|
|
187
|
+
def delete(key)
|
|
188
|
+
@monitor.synchronize do
|
|
189
|
+
entry = @stash.delete(key)
|
|
190
|
+
if entry
|
|
191
|
+
@expires_at.delete(entry)
|
|
192
|
+
entry.value
|
|
193
|
+
else
|
|
194
|
+
nil
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Checks whether the cache is empty.
|
|
200
|
+
#
|
|
201
|
+
# @note calls to {#empty?} do not count against `expire_interval`.
|
|
202
|
+
#
|
|
203
|
+
# @return [Boolean]
|
|
204
|
+
#
|
|
205
|
+
def empty?
|
|
206
|
+
@monitor.synchronize { count == 0 }
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Clears the cache.
|
|
210
|
+
#
|
|
211
|
+
# @return [self]
|
|
212
|
+
#
|
|
213
|
+
def clear
|
|
214
|
+
@monitor.synchronize do
|
|
215
|
+
@stash.clear
|
|
216
|
+
@expires_at.clear
|
|
217
|
+
self
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Returns the number of elements in the cache.
|
|
222
|
+
#
|
|
223
|
+
# @note
|
|
224
|
+
# Calls to {#empty?} do not count against `expire_interval`. Therefore,
|
|
225
|
+
# the number of elements is that prior to any expiration.
|
|
226
|
+
#
|
|
227
|
+
# @return [Integer]
|
|
228
|
+
# Number of elements in the cache.
|
|
229
|
+
#
|
|
230
|
+
def count
|
|
231
|
+
@monitor.synchronize { @stash.count }
|
|
232
|
+
end
|
|
233
|
+
alias_method :size, :count
|
|
234
|
+
alias_method :length, :count
|
|
235
|
+
|
|
236
|
+
# Allows iteration over the items in the cache. Enumeration is stable: it
|
|
237
|
+
# is not affected by changes to the cache, including value expiration.
|
|
238
|
+
# Expired values are removed first.
|
|
239
|
+
#
|
|
240
|
+
# @note
|
|
241
|
+
# The returned values could have expired by the time the client code gets
|
|
242
|
+
# to accessing them.
|
|
243
|
+
#
|
|
244
|
+
# @note
|
|
245
|
+
# Because of its stability, this operation is very expensive. Use with
|
|
246
|
+
# caution.
|
|
247
|
+
#
|
|
248
|
+
# @yield [Array<key, value>]
|
|
249
|
+
# Key/value pairs, when a block is provided.
|
|
250
|
+
#
|
|
251
|
+
# @return [Enumerator, Array<key, value>]
|
|
252
|
+
# An Enumerator, when no block is provided, or array of key/value pairs.
|
|
253
|
+
#
|
|
254
|
+
def each(&block)
|
|
255
|
+
@monitor.synchronize do
|
|
256
|
+
expire!
|
|
257
|
+
@stash.map { |key, entry| [key, entry.value] }.each(&block)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Removes expired values from the cache.
|
|
262
|
+
#
|
|
263
|
+
# @return [self]
|
|
264
|
+
#
|
|
265
|
+
def expire!
|
|
266
|
+
@monitor.synchronize do
|
|
267
|
+
check_expired(Time.now.to_f)
|
|
268
|
+
self
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Return all keys in the store as an array.
|
|
273
|
+
#
|
|
274
|
+
# @return [Array<String, Symbol>] all the keys in store
|
|
275
|
+
#
|
|
276
|
+
def keys
|
|
277
|
+
@monitor.synchronize { @stash.keys }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Returns information about the number of objects in the cache, its
|
|
281
|
+
# maximum size and TTL.
|
|
282
|
+
#
|
|
283
|
+
# @return [String]
|
|
284
|
+
#
|
|
285
|
+
def inspect
|
|
286
|
+
@monitor.synchronize do
|
|
287
|
+
"<#{self.class.name} count=#{count} max_entries=#{@max_entries} " \
|
|
288
|
+
"ttl=#{@ttl_seconds}>"
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
|
293
|
+
|
|
294
|
+
# @private
|
|
295
|
+
class Entry
|
|
296
|
+
attr_reader :value
|
|
297
|
+
attr_reader :expires_at
|
|
298
|
+
|
|
299
|
+
def initialize(value, expires_at)
|
|
300
|
+
@value = value
|
|
301
|
+
@expires_at = expires_at
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def get(key)
|
|
306
|
+
@monitor.synchronize do
|
|
307
|
+
time = Time.now.to_f
|
|
308
|
+
check_expired(time)
|
|
309
|
+
found = true
|
|
310
|
+
entry = @stash.delete(key) { found = false }
|
|
311
|
+
if found
|
|
312
|
+
if entry.expires_at <= time
|
|
313
|
+
@expires_at.delete(entry)
|
|
314
|
+
return false, nil
|
|
315
|
+
else
|
|
316
|
+
@stash[key] = entry
|
|
317
|
+
return true, entry.value
|
|
318
|
+
end
|
|
319
|
+
else
|
|
320
|
+
return false, nil
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def store(key, val)
|
|
326
|
+
@monitor.synchronize do
|
|
327
|
+
expires_at = Time.now.to_f + @ttl_seconds
|
|
328
|
+
entry = Entry.new(val, expires_at)
|
|
329
|
+
store_entry(key, entry)
|
|
330
|
+
val
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def store_entry(key, entry)
|
|
335
|
+
@monitor.synchronize do
|
|
336
|
+
@stash.delete(key)
|
|
337
|
+
@stash[key] = entry
|
|
338
|
+
@expires_at[entry] = key
|
|
339
|
+
shrink_if_needed
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def shrink_if_needed
|
|
344
|
+
@monitor.synchronize do
|
|
345
|
+
if @stash.length > @max_entries
|
|
346
|
+
entry = delete(@stash.shift)
|
|
347
|
+
@expires_at.delete(entry)
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def check_expired(time)
|
|
353
|
+
@monitor.synchronize do
|
|
354
|
+
if (@operations += 1) % @interval == 0
|
|
355
|
+
while (key_value_pair = @expires_at.first) &&
|
|
356
|
+
(entry = key_value_pair.first).expires_at <= time
|
|
357
|
+
key = @expires_at.delete(entry)
|
|
358
|
+
@stash.delete(key)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Garcon
|
|
21
|
+
# Returns the columns and lines of the current tty.
|
|
22
|
+
#
|
|
23
|
+
# @return [Integer]
|
|
24
|
+
# Number of columns and lines of tty, returns [0, 0] if no tty is present.
|
|
25
|
+
#
|
|
26
|
+
def terminal_dimensions
|
|
27
|
+
[0, 0] unless STDOUT.tty?
|
|
28
|
+
[80, 40] if OS.windows?
|
|
29
|
+
|
|
30
|
+
if ENV['COLUMNS'] && ENV['LINES']
|
|
31
|
+
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
|
32
|
+
elsif ENV['TERM'] && command_in_path?('tput')
|
|
33
|
+
[`tput cols`.to_i, `tput lines`.to_i]
|
|
34
|
+
elsif command_in_path?('stty')
|
|
35
|
+
`stty size`.scan(/\d+/).map {|s| s.to_i }
|
|
36
|
+
else
|
|
37
|
+
[0, 0]
|
|
38
|
+
end
|
|
39
|
+
rescue
|
|
40
|
+
[0, 0]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class GarconHash < Hash
|
|
45
|
+
def method_missing(method_name, *args)
|
|
46
|
+
return super unless respond_to?(method_name)
|
|
47
|
+
self[method_name].to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def respond_to?(symbol, include_private=false)
|
|
51
|
+
return true if key?(symbol.to_s)
|
|
52
|
+
super
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
# God speaks in Ruby, not Python!! MsgFromGod is an implementation of a
|
|
3
|
+
# Higher-Order-Message. Essentally, a MsgFromGod can vary its behavior
|
|
4
|
+
# accorrding to the operation applied to it.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# g = MsgFromGod.new { |op, x| x.send(op, x) }
|
|
8
|
+
# (g + 1) # => 2
|
|
9
|
+
# (g + 2) # => 4
|
|
10
|
+
# (g + 3) # => 6
|
|
11
|
+
# (g * 1) # => 1
|
|
12
|
+
# (g * 2) # => 4
|
|
13
|
+
# (g * 3) # => 9
|
|
14
|
+
#
|
|
15
|
+
class MsgFromGod
|
|
16
|
+
|
|
17
|
+
# MsgFromGod can be somewhat inefficient if a new MsgFromGod is frequently
|
|
18
|
+
# recreated for the same use. So this cache can be used to speed things up.
|
|
19
|
+
#
|
|
20
|
+
# The key will always be an array, wich makes it easier to cache MsgFromGod
|
|
21
|
+
# for multiple factors.
|
|
22
|
+
#
|
|
23
|
+
def self.cache(*key, &function)
|
|
24
|
+
@cache ||= {}
|
|
25
|
+
if function
|
|
26
|
+
@cache[key] = new(&function)
|
|
27
|
+
else
|
|
28
|
+
@cache[key]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
EXCEPTIONS = [:binding, :inspect, :object_id]
|
|
33
|
+
if defined?(::BasicObject)
|
|
34
|
+
EXCEPTIONS.concat(::BasicObject.instance_methods)
|
|
35
|
+
EXCEPTIONS.uniq!
|
|
36
|
+
EXCEPTIONS.map! { |m| m.to_sym }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias :__class__ :class
|
|
40
|
+
|
|
41
|
+
# Privatize all methods except vital methods and #binding.
|
|
42
|
+
instance_methods(true).each do |m|
|
|
43
|
+
next if m.to_s =~ /^__/
|
|
44
|
+
next if EXCEPTIONS.include?(m.to_sym)
|
|
45
|
+
undef_method(m)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def initialize(&function)
|
|
49
|
+
@function = function
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_proc
|
|
53
|
+
@function
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
|
57
|
+
|
|
58
|
+
# Any action against the MsgFromGod is processesd by the function.
|
|
59
|
+
def method_missing(op, *args, &blk)
|
|
60
|
+
@function.call(op, *args, &blk)
|
|
61
|
+
end
|
|
62
|
+
end
|