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,114 @@
|
|
|
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
|
+
module Garcon
|
|
21
|
+
module Stash
|
|
22
|
+
# Database format serializer and deserializer. You can create your own
|
|
23
|
+
# implementation of this class and define your own database format!
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
class Format
|
|
27
|
+
# Read database header from input stream
|
|
28
|
+
#
|
|
29
|
+
# @param [#read] input
|
|
30
|
+
# the input stream
|
|
31
|
+
#
|
|
32
|
+
# @return void
|
|
33
|
+
#
|
|
34
|
+
def read_header(input)
|
|
35
|
+
raise 'Not a stash' if input.read(MAGIC.bytesize) != MAGIC
|
|
36
|
+
ver = input.read(2).unpack('n').first
|
|
37
|
+
raise "Expected stash version #{VERSION}, got #{ver}" if ver != VERSION
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Return database header as string
|
|
41
|
+
#
|
|
42
|
+
# @return [String] database file header
|
|
43
|
+
#
|
|
44
|
+
def header
|
|
45
|
+
MAGIC + [VERSION].pack('n')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Serialize record and return string.
|
|
49
|
+
#
|
|
50
|
+
# @param [Array] rec
|
|
51
|
+
# an array with [key, value] or [key] if the record is deleted
|
|
52
|
+
#
|
|
53
|
+
# @return [String] serialized record
|
|
54
|
+
#
|
|
55
|
+
def dump(rec)
|
|
56
|
+
data = if rec.size == 1
|
|
57
|
+
[rec[0].bytesize, DELETE].pack('NN') << rec[0]
|
|
58
|
+
else
|
|
59
|
+
[rec[0].bytesize, rec[1].bytesize].pack('NN') << rec[0] << rec[1]
|
|
60
|
+
end
|
|
61
|
+
data << crc32(data)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Deserialize records from buffer, and yield them.
|
|
65
|
+
#
|
|
66
|
+
# @param [String] buf
|
|
67
|
+
# the buffer to read from
|
|
68
|
+
#
|
|
69
|
+
# @yield [Array] block
|
|
70
|
+
# deserialized record [key, value] or [key] if the record is deleted
|
|
71
|
+
#
|
|
72
|
+
# @return [Fixnum] number of records
|
|
73
|
+
#
|
|
74
|
+
def parse(buf)
|
|
75
|
+
n, count = 0, 0
|
|
76
|
+
while n < buf.size
|
|
77
|
+
key_size, value_size = buf[n, 8].unpack('NN')
|
|
78
|
+
data_size = key_size + 8
|
|
79
|
+
data_size += value_size if value_size != DELETE
|
|
80
|
+
data = buf[n, data_size]
|
|
81
|
+
n += data_size
|
|
82
|
+
unless buf[n, 4] == crc32(data)
|
|
83
|
+
raise 'CRC mismatch: your stash might be corrupted!'
|
|
84
|
+
end
|
|
85
|
+
n += 4
|
|
86
|
+
yield(value_size == DELETE ? [data[8, key_size]] : [data[8, key_size], data[8 + key_size, value_size]])
|
|
87
|
+
count += 1
|
|
88
|
+
end
|
|
89
|
+
count
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
protected # A T T E N Z I O N E A R E A P R O T E T T A
|
|
93
|
+
|
|
94
|
+
# Magic string of the file header.
|
|
95
|
+
MAGIC = 'ABRACADABRA'
|
|
96
|
+
|
|
97
|
+
# Database file format version (it is a hash after all).
|
|
98
|
+
VERSION = 420
|
|
99
|
+
|
|
100
|
+
# Special value size used for deleted records
|
|
101
|
+
DELETE = (1 << 32) - 1
|
|
102
|
+
|
|
103
|
+
# Compute crc32 of string
|
|
104
|
+
#
|
|
105
|
+
# @param [String] s a string
|
|
106
|
+
#
|
|
107
|
+
# @return [Fixnum]
|
|
108
|
+
#
|
|
109
|
+
def crc32(s)
|
|
110
|
+
[Zlib.crc32(s, 0)].pack('N')
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,226 @@
|
|
|
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
|
+
module Garcon
|
|
21
|
+
module Stash
|
|
22
|
+
# Stash::Io handles background io, compaction and is the arbiter
|
|
23
|
+
# of multiprocess safety.
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
26
|
+
class Journal < Queue
|
|
27
|
+
attr_reader :size, :file
|
|
28
|
+
|
|
29
|
+
def initialize(file, format, serializer, &block)
|
|
30
|
+
super()
|
|
31
|
+
@file, @format, @serializer, @emit = file, format, serializer, block
|
|
32
|
+
open
|
|
33
|
+
@worker = Thread.new(&method(:worker))
|
|
34
|
+
@worker.priority = -1
|
|
35
|
+
load
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Is the journal closed?
|
|
39
|
+
#
|
|
40
|
+
def closed?
|
|
41
|
+
@fd.closed?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Clear the queue and close the file handler
|
|
45
|
+
#
|
|
46
|
+
def close
|
|
47
|
+
self << nil
|
|
48
|
+
@worker.join
|
|
49
|
+
@fd.close
|
|
50
|
+
super
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Load new journal entries
|
|
54
|
+
#
|
|
55
|
+
def load
|
|
56
|
+
flush
|
|
57
|
+
replay
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Lock the logfile across thread and process boundaries
|
|
61
|
+
#
|
|
62
|
+
def lock
|
|
63
|
+
flush
|
|
64
|
+
with_flock(File::LOCK_EX) do
|
|
65
|
+
replay
|
|
66
|
+
result = yield
|
|
67
|
+
flush
|
|
68
|
+
result
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Clear the database log and yield
|
|
73
|
+
#
|
|
74
|
+
def clear
|
|
75
|
+
flush
|
|
76
|
+
with_tmpfile do |path, file|
|
|
77
|
+
file.write(@format.header)
|
|
78
|
+
file.close
|
|
79
|
+
with_flock(File::LOCK_EX) do
|
|
80
|
+
File.rename(path, @file)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
open
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Compact the logfile to represent the in-memory state
|
|
87
|
+
#
|
|
88
|
+
def compact
|
|
89
|
+
load
|
|
90
|
+
with_tmpfile do |path, file|
|
|
91
|
+
# Compactified database has the same size -> return
|
|
92
|
+
return self if @pos == file.write(dump(yield, @format.header))
|
|
93
|
+
with_flock(File::LOCK_EX) do
|
|
94
|
+
if @pos != nil
|
|
95
|
+
file.write(read)
|
|
96
|
+
file.close
|
|
97
|
+
File.rename(path, @file)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
open
|
|
102
|
+
replay
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Return byte size of journal
|
|
106
|
+
#
|
|
107
|
+
def bytesize
|
|
108
|
+
@fd.stat.size
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
|
112
|
+
|
|
113
|
+
# Emit records as we parse them
|
|
114
|
+
def replay
|
|
115
|
+
buf = read
|
|
116
|
+
@size += @format.parse(buf, &@emit)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Open or reopen file
|
|
120
|
+
#
|
|
121
|
+
def open
|
|
122
|
+
@fd.close if @fd
|
|
123
|
+
@fd = File.open(@file, 'ab+')
|
|
124
|
+
@fd.advise(:sequential) if @fd.respond_to? :advise
|
|
125
|
+
stat = @fd.stat
|
|
126
|
+
@inode = stat.ino
|
|
127
|
+
write(@format.header) if stat.size == 0
|
|
128
|
+
@pos = nil
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Read new file content
|
|
132
|
+
#
|
|
133
|
+
def read
|
|
134
|
+
with_flock(File::LOCK_SH) do
|
|
135
|
+
unless @pos
|
|
136
|
+
@fd.pos = 0
|
|
137
|
+
@format.read_header(@fd)
|
|
138
|
+
@size = 0
|
|
139
|
+
@emit.call(nil)
|
|
140
|
+
else
|
|
141
|
+
@fd.pos = @pos
|
|
142
|
+
end
|
|
143
|
+
buf = @fd.read
|
|
144
|
+
@pos = @fd.pos
|
|
145
|
+
buf
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Return database dump as string
|
|
150
|
+
#
|
|
151
|
+
def dump(records, dump = '')
|
|
152
|
+
records.each do |record|
|
|
153
|
+
record[1] = @serializer.dump(record.last)
|
|
154
|
+
dump << @format.dump(record)
|
|
155
|
+
end
|
|
156
|
+
dump
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Worker thread
|
|
160
|
+
#
|
|
161
|
+
def worker
|
|
162
|
+
while (record = first)
|
|
163
|
+
tries = 0
|
|
164
|
+
begin
|
|
165
|
+
if Hash === record
|
|
166
|
+
write(dump(record))
|
|
167
|
+
@size += record.size
|
|
168
|
+
else
|
|
169
|
+
record[1] = @serializer.dump(record.last) if record.size > 1
|
|
170
|
+
write(@format.dump(record))
|
|
171
|
+
@size += 1
|
|
172
|
+
end
|
|
173
|
+
rescue Exception => e
|
|
174
|
+
tries += 1
|
|
175
|
+
warn "Stash worker, try #{tries}: #{e.message}"
|
|
176
|
+
tries <= 3 ? retry : raise
|
|
177
|
+
ensure
|
|
178
|
+
pop
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
rescue Exception => e
|
|
182
|
+
warn "Stash worker terminated: #{e.message}"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Write data to output stream and advance @pos
|
|
186
|
+
#
|
|
187
|
+
def write(dump)
|
|
188
|
+
with_flock(File::LOCK_EX) do
|
|
189
|
+
@fd.write(dump)
|
|
190
|
+
@fd.flush
|
|
191
|
+
end
|
|
192
|
+
@pos = @fd.pos if @pos && @fd.pos == @pos + dump.bytesize
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Block with file lock
|
|
196
|
+
#
|
|
197
|
+
def with_flock(mode)
|
|
198
|
+
return yield if @locked
|
|
199
|
+
begin
|
|
200
|
+
loop do
|
|
201
|
+
Thread.pass until @fd.flock(mode)
|
|
202
|
+
stat = @fd.stat
|
|
203
|
+
break if stat.nlink > 0 && stat.ino == @inode
|
|
204
|
+
open
|
|
205
|
+
end
|
|
206
|
+
@locked = true
|
|
207
|
+
yield
|
|
208
|
+
ensure
|
|
209
|
+
@fd.flock(File::LOCK_UN)
|
|
210
|
+
@locked = false
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Open temporary file and pass it to the block
|
|
215
|
+
#
|
|
216
|
+
def with_tmpfile
|
|
217
|
+
path = [@file, $$.to_s(36), Thread.current.object_id.to_s(36)].join
|
|
218
|
+
file = File.open(path, 'wb')
|
|
219
|
+
yield(path, file)
|
|
220
|
+
ensure
|
|
221
|
+
file.close unless file.closed?
|
|
222
|
+
File.unlink(path) if File.exists?(path)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
module Garcon
|
|
21
|
+
module Stash
|
|
22
|
+
class Queue
|
|
23
|
+
def initialize
|
|
24
|
+
@queue, @full, @empty = [], [], []
|
|
25
|
+
@stop = false
|
|
26
|
+
@heartbeat = Thread.new(&method(:heartbeat))
|
|
27
|
+
@heartbeat.priority = -9
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def <<(x)
|
|
31
|
+
@queue << x
|
|
32
|
+
thread = @full.first
|
|
33
|
+
thread.wakeup if thread
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def pop
|
|
37
|
+
@queue.shift
|
|
38
|
+
if @queue.empty?
|
|
39
|
+
thread = @empty.first
|
|
40
|
+
thread.wakeup if thread
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def first
|
|
45
|
+
while @queue.empty?
|
|
46
|
+
begin
|
|
47
|
+
@full << Thread.current
|
|
48
|
+
Thread.stop while @queue.empty?
|
|
49
|
+
ensure
|
|
50
|
+
@full.delete(Thread.current)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
@queue.first
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def flush
|
|
57
|
+
until @queue.empty?
|
|
58
|
+
begin
|
|
59
|
+
@empty << Thread.current
|
|
60
|
+
Thread.stop until @queue.empty?
|
|
61
|
+
ensure
|
|
62
|
+
@empty.delete(Thread.current)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def close
|
|
68
|
+
@stop = true
|
|
69
|
+
@heartbeat.join
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
|
73
|
+
|
|
74
|
+
def heartbeat
|
|
75
|
+
until @stop
|
|
76
|
+
@empty.each(&:wakeup)
|
|
77
|
+
@full.each(&:wakeup)
|
|
78
|
+
sleep 0.1
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
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
|
+
module Garcon
|
|
21
|
+
module Stash
|
|
22
|
+
module Serializer
|
|
23
|
+
# Serializer which only encodes key in binary
|
|
24
|
+
#
|
|
25
|
+
# @api public
|
|
26
|
+
class None
|
|
27
|
+
# (see Stash::Serializer::Default#key_for)
|
|
28
|
+
if ''.respond_to? :force_encoding
|
|
29
|
+
def key_for(key)
|
|
30
|
+
if key.encoding != Encoding::BINARY
|
|
31
|
+
key = key.dup if key.frozen?
|
|
32
|
+
key.force_encoding(Encoding::BINARY)
|
|
33
|
+
end
|
|
34
|
+
key
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
def key_for(key)
|
|
38
|
+
key
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# (see Stash::Serializer::Default#dump)
|
|
43
|
+
def dump(value)
|
|
44
|
+
value
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# (see Stash::Serializer::Default#load)
|
|
48
|
+
def load(value)
|
|
49
|
+
value
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Default serializer which converts keys to strings and marshalls values.
|
|
54
|
+
#
|
|
55
|
+
# @api public
|
|
56
|
+
class Default < None
|
|
57
|
+
# Transform the key to a string.
|
|
58
|
+
#
|
|
59
|
+
# @param [Object] key
|
|
60
|
+
# @return [String]
|
|
61
|
+
# The key transformed to string.
|
|
62
|
+
def key_for(key)
|
|
63
|
+
super(key.to_s)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Serialize a value.
|
|
67
|
+
#
|
|
68
|
+
# @param [Object] value
|
|
69
|
+
# @return [String]
|
|
70
|
+
# The value transformed to string.
|
|
71
|
+
def dump(value)
|
|
72
|
+
Marshal.dump(value)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Parse a value.
|
|
76
|
+
#
|
|
77
|
+
# @param [String] value
|
|
78
|
+
# @return [Object]
|
|
79
|
+
# The deserialized value.
|
|
80
|
+
def load(value)
|
|
81
|
+
Marshal.load(value)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|