Class: OsCtld::GarbageCollector
- Inherits:
-
Object
- Object
- OsCtld::GarbageCollector
show all
- Includes:
- OsCtl::Lib::Utils::File, OsCtl::Lib::Utils::Log, Lockable
- Defined in:
- lib/osctld/garbage_collector.rb
Overview
Ensures that temporary datasets are moved to trash after they’re not needed
It can be used to tie datasets to specific container runs. Add dataset using #add_container_run_dataset and it will be kept as long as the same run configuration is active. When the container is stopped, restarted, or #free_container_run_dataset is called, the dataset is moved to the trash bin.
Defined Under Namespace
Classes: ContainerRunDataset
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Lockable
#exclusively, included, #inclusively, #init_lock, #lock, #unlock
Constructor Details
Returns a new instance of GarbageCollector.
72
73
74
75
76
77
78
79
80
|
# File 'lib/osctld/garbage_collector.rb', line 72
def initialize(pool)
init_lock
@pool = pool
@config_path = File.join(pool.conf_path, 'pool', 'garbage-collector.yml')
@queue = OsCtl::Lib::Queue.new
@stop = false
load_config
end
|
Instance Attribute Details
69
70
71
|
# File 'lib/osctld/garbage_collector.rb', line 69
def pool
@pool
end
|
Class Method Details
.add_container_run_dataset(run_conf, dataset) ⇒ Object
54
55
56
|
# File 'lib/osctld/garbage_collector.rb', line 54
def self.add_container_run_dataset(run_conf, dataset)
run_conf.pool.garbage_collector.add_container_run_dataset(run_conf, dataset)
end
|
.free_container_run_dataset(run_conf, dataset) ⇒ Object
60
61
62
|
# File 'lib/osctld/garbage_collector.rb', line 60
def self.free_container_run_dataset(run_conf, dataset)
run_conf.pool.garbage_collector.free_container_run_dataset(run_conf, dataset)
end
|
Instance Method Details
#add_container_run_dataset(run_conf, dataset) ⇒ Object
114
115
116
117
118
119
|
# File 'lib/osctld/garbage_collector.rb', line 114
def add_container_run_dataset(run_conf, dataset)
exclusively do
@container_run_datasets << ContainerRunDataset.new(run_conf.run_id, dataset)
save_config
end
end
|
#assets(add) ⇒ Object
82
83
84
85
86
87
88
|
# File 'lib/osctld/garbage_collector.rb', line 82
def assets(add)
add.file(
@config_path,
desc: 'Configuration file for garbage collector',
optional: true
)
end
|
#container_run_dataset_in_use?(ct_run_ds) ⇒ Boolean
210
211
212
213
214
215
216
217
218
219
|
# File 'lib/osctld/garbage_collector.rb', line 210
def container_run_dataset_in_use?(ct_run_ds)
ct = DB::Containers.find(ct_run_ds.container_id, ct_run_ds.pool_name)
return false if ct.nil?
run_conf = ct.run_conf
next_run_conf = ct.next_run_conf
(run_conf && run_conf.run_id == ct_run_ds.run_id) \
|| (next_run_conf && next_run_conf.run_id == ct_run_ds.run_id)
end
|
#do_free_container_run_dataset(ct_run_ds) ⇒ Object
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/osctld/garbage_collector.rb', line 196
def do_free_container_run_dataset(ct_run_ds)
log(:info, "Moving #{ct_run_ds.dataset} to trash")
return unless trash_dataset(ct_run_ds.dataset)
exclusively do
@container_run_datasets.delete(ct_run_ds)
save_config
end
end
|
#free_container_run_dataset(run_conf, dataset) ⇒ Object
123
124
125
|
# File 'lib/osctld/garbage_collector.rb', line 123
def free_container_run_dataset(run_conf, dataset)
@queue << [:free_container_run_dataset, ContainerRunDataset.new(run_conf.run_id, dataset)]
end
|
#load_config ⇒ Object
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# File 'lib/osctld/garbage_collector.rb', line 133
def load_config
@container_run_datasets = []
begin
cfg = OsCtl::Lib::ConfigFile.load_yaml_file(@config_path)
rescue Errno::ENOENT
return
end
@container_run_datasets = cfg.fetch('container_run_datasets', []).map do |ct_run_ds_cfg|
ContainerRunDataset.load(ct_run_ds_cfg)
end
end
|
#log_type ⇒ Object
127
128
129
|
# File 'lib/osctld/garbage_collector.rb', line 127
def log_type
"#{pool.name}:gc"
end
|
#prune ⇒ Object
108
109
110
|
# File 'lib/osctld/garbage_collector.rb', line 108
def prune
@queue << :prune
end
|
#prune_container_run_datasets ⇒ Object
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/osctld/garbage_collector.rb', line 175
def prune_container_run_datasets
unused =
inclusively do
@container_run_datasets.reject do |ct_run_ds|
container_run_dataset_in_use?(ct_run_ds)
end
end
unused.each do |ct_run_ds|
break if @stop
log(:info, "Container dataset #{ct_run_ds.dataset} from run=#{ct_run_ds.run_id} is no longer in use, moving to trash")
next unless trash_dataset(ct_run_ds.dataset)
exclusively do
@container_run_datasets.delete(ct_run_ds)
save_config
end
end
end
|
#run_gc ⇒ Object
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
# File 'lib/osctld/garbage_collector.rb', line 157
def run_gc
loop do
v = @queue.pop(timeout: Daemon.get.config.garbage_collector.prune_interval)
case v
in :stop
return
in :prune | nil
log(:info, 'Pruning container run datasets')
prune_container_run_datasets
in [:free_container_run_dataset, ct_run_ds]
do_free_container_run_dataset(ct_run_ds)
end
end
end
|
#save_config ⇒ Object
147
148
149
150
151
152
153
154
155
|
# File 'lib/osctld/garbage_collector.rb', line 147
def save_config
exclusively do
regenerate_file(@config_path, 0o400) do |f|
f.write(OsCtl::Lib::ConfigFile.dump_yaml({
'container_run_datasets' => @container_run_datasets.map(&:dump)
}))
end
end
end
|
#start ⇒ Object
90
91
92
93
|
# File 'lib/osctld/garbage_collector.rb', line 90
def start
@stop = false
@thread = Thread.new { run_gc }
end
|
#started? ⇒ Boolean
104
105
106
|
# File 'lib/osctld/garbage_collector.rb', line 104
def started?
!@stop
end
|
#stop ⇒ Object
95
96
97
98
99
100
101
102
|
# File 'lib/osctld/garbage_collector.rb', line 95
def stop
return unless @thread
@stop = true
@queue << :stop
@thread.join
@thread = nil
end
|
#trash_dataset(dataset) ⇒ Boolean
Returns true if the dataset was moved to trash or if it doesn’t exist.
222
223
224
225
226
227
228
229
230
231
232
233
|
# File 'lib/osctld/garbage_collector.rb', line 222
def trash_dataset(dataset)
pool.trash_bin.add_dataset(dataset)
true
rescue SystemCommandFailed => e
if dataset.exist?
log(:warn, "Unable to trash dataset '#{dataset}': #{e.message}")
false
else
log(:warn, "Attempted to trash a non-existent dataset '#{dataset}' (original error: #{e.message})")
true
end
end
|