-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkey_server.rb
More file actions
119 lines (100 loc) · 2.44 KB
/
key_server.rb
File metadata and controls
119 lines (100 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
require 'set'
class KeyServer
attr_accessor :keys, :available_keys
attr_reader :deleted_keys
def initialize
@keys = {}
@available_keys = {}
@deleted_keys = Set.new
@mutex = Mutex.new
end
# Util function to generate a random key
def random_key
o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
(0...8).map { o[rand(o.length)] }.join
end
# Generate keys
def generate_key(length)
while @available_keys.size < length
key = random_key
next if @available_keys.key?(key) || @deleted_keys.include?(key)
@mutex.synchronize do
ts= Time.now.to_i
@keys[key] = { :ct => ts, :st => ts}
@available_keys[key] = true
end
end
@available_keys.keys
end
# get an available key
def get_key
return nil if @available_keys.empty?
key = -1
@mutex.synchronize do
key = @available_keys.shift[0]
@keys[key][:ct] = Time.now.to_i
end
key
end
# unblocks the given key
def unblock_key(key)
return false unless @keys.key? key
@mutex.synchronize do
@keys[key][:ct] = @keys[key][:st]
@available_keys[key] = true
end
true
end
# deletes the given key
def delete_key(key)
return false unless @keys.key? key
@mutex.synchronize do
@keys.delete(key)
@available_keys.delete(key)
end
@deleted_keys.add key
puts "Deleted Key: #{key}"
true
end
# keep alive functionality for keys
def keep_alive_key(key)
return false unless @keys.key? key
@mutex.synchronize do
@keys[key][:st] = Time.now.to_i
puts "Keep Alive called for Key: #{key}"
end
true
end
# Validate if the key expired in the given time
def expired_kalive?(key, time)
if !@keys.key?(key)
return false
end
if Time.now.to_i - @keys[key][:st] > time
puts "Expired key due to not received keepalive within #{time} seconds : #{key}"
return true
end
false
end
def expired_unlocked?(key, time)
if !@keys.key?(key) || @available_keys.key?(key)
return false
end
if Time.now.to_i - @keys[key][:ct] > time
puts "Expired key (condition of unblocked met) : #{key}"
return true
end
false
end
#performs cleanup of the required keys
def cleanup
@keys.each { |key, time|
if expired_kalive?(key, 300)
delete_key(key)
end
if expired_unlocked?(key, 60)
unblock_key(key)
end
}
end
end