Line data Source code
1 : use std::collections::HashMap;
2 : use std::sync::Arc;
3 :
4 : use anyhow::{Context, bail, ensure};
5 : use itertools::Itertools;
6 : use pageserver_api::keyspace::KeySpace;
7 : use pageserver_api::shard::TenantShardId;
8 : use tokio_util::sync::CancellationToken;
9 : use tracing::trace;
10 : use utils::id::TimelineId;
11 : use utils::lsn::{AtomicLsn, Lsn};
12 :
13 : use super::{LayerFringe, ReadableLayer, TimelineWriterState};
14 : use crate::config::PageServerConf;
15 : use crate::context::RequestContext;
16 : use crate::metrics::TimelineMetrics;
17 : use crate::tenant::layer_map::{BatchedUpdates, LayerMap, SearchResult};
18 : use crate::tenant::storage_layer::{
19 : AsLayerDesc, InMemoryLayer, Layer, LayerVisibilityHint, PersistentLayerDesc,
20 : PersistentLayerKey, ReadableLayerWeak, ResidentLayer,
21 : };
22 :
23 : /// Provides semantic APIs to manipulate the layer map.
24 : pub(crate) enum LayerManager {
25 : /// Open as in not shutdown layer manager; we still have in-memory layers and we can manipulate
26 : /// the layers.
27 : Open(OpenLayerManager),
28 : /// Shutdown layer manager where there are no more in-memory layers and persistent layers are
29 : /// read-only.
30 : Closed {
31 : layers: HashMap<PersistentLayerKey, Layer>,
32 : },
33 : }
34 :
35 : impl Default for LayerManager {
36 2784 : fn default() -> Self {
37 2784 : LayerManager::Open(OpenLayerManager::default())
38 2784 : }
39 : }
40 :
41 : impl LayerManager {
42 5488046 : fn upgrade(&self, weak: ReadableLayerWeak) -> ReadableLayer {
43 5488046 : match weak {
44 1724779 : ReadableLayerWeak::PersistentLayer(desc) => {
45 1724779 : ReadableLayer::PersistentLayer(self.get_from_desc(&desc))
46 : }
47 3763267 : ReadableLayerWeak::InMemoryLayer(desc) => {
48 3763267 : let inmem = self
49 3763267 : .layer_map()
50 3763267 : .expect("no concurrent shutdown")
51 3763267 : .in_memory_layer(&desc);
52 3763267 : ReadableLayer::InMemoryLayer(inmem)
53 : }
54 : }
55 5488046 : }
56 :
57 1730551 : pub(crate) fn get_from_key(&self, key: &PersistentLayerKey) -> Layer {
58 1730551 : // The assumption for the `expect()` is that all code maintains the following invariant:
59 1730551 : // A layer's descriptor is present in the LayerMap => the LayerFileManager contains a layer for the descriptor.
60 1730551 : self.try_get_from_key(key)
61 1730551 : .with_context(|| format!("get layer from key: {key}"))
62 1730551 : .expect("not found")
63 1730551 : .clone()
64 1730551 : }
65 :
66 1730827 : pub(crate) fn try_get_from_key(&self, key: &PersistentLayerKey) -> Option<&Layer> {
67 1730827 : self.layers().get(key)
68 1730827 : }
69 :
70 1730419 : pub(crate) fn get_from_desc(&self, desc: &PersistentLayerDesc) -> Layer {
71 1730419 : self.get_from_key(&desc.key())
72 1730419 : }
73 :
74 : /// Get an immutable reference to the layer map.
75 : ///
76 : /// We expect users only to be able to get an immutable layer map. If users want to make modifications,
77 : /// they should use the below semantic APIs. This design makes us step closer to immutable storage state.
78 10515433 : pub(crate) fn layer_map(&self) -> Result<&LayerMap, Shutdown> {
79 : use LayerManager::*;
80 10515433 : match self {
81 10515433 : Open(OpenLayerManager { layer_map, .. }) => Ok(layer_map),
82 0 : Closed { .. } => Err(Shutdown),
83 : }
84 10515433 : }
85 :
86 30072 : pub(crate) fn open_mut(&mut self) -> Result<&mut OpenLayerManager, Shutdown> {
87 : use LayerManager::*;
88 :
89 30072 : match self {
90 30072 : Open(open) => Ok(open),
91 0 : Closed { .. } => Err(Shutdown),
92 : }
93 30072 : }
94 :
95 : /// LayerManager shutdown. The in-memory layers do cleanup on drop, so we must drop them in
96 : /// order to allow shutdown to complete.
97 : ///
98 : /// If there was a want to flush in-memory layers, it must have happened earlier.
99 60 : pub(crate) fn shutdown(&mut self, writer_state: &mut Option<TimelineWriterState>) {
100 : use LayerManager::*;
101 60 : match self {
102 : Open(OpenLayerManager {
103 60 : layer_map,
104 60 : layer_fmgr: LayerFileManager(hashmap),
105 60 : }) => {
106 60 : // NB: no need to decrement layer metrics; metrics are removed on timeline shutdown.
107 60 : let open = layer_map.open_layer.take();
108 60 : let frozen = layer_map.frozen_layers.len();
109 60 : let taken_writer_state = writer_state.take();
110 60 : tracing::info!(open = open.is_some(), frozen, "dropped inmemory layers");
111 60 : let layers = std::mem::take(hashmap);
112 60 : *self = Closed { layers };
113 60 : assert_eq!(open.is_some(), taken_writer_state.is_some());
114 : }
115 : Closed { .. } => {
116 0 : tracing::debug!("ignoring multiple shutdowns on layer manager")
117 : }
118 : }
119 60 : }
120 :
121 : /// Sum up the historic layer sizes
122 0 : pub(crate) fn layer_size_sum(&self) -> u64 {
123 0 : self.layers()
124 0 : .values()
125 0 : .map(|l| l.layer_desc().file_size)
126 0 : .sum()
127 0 : }
128 :
129 240 : pub(crate) fn likely_resident_layers(&self) -> impl Iterator<Item = &'_ Layer> + '_ {
130 679 : self.layers().values().filter(|l| l.is_likely_resident())
131 240 : }
132 :
133 0 : pub(crate) fn visible_layers(&self) -> impl Iterator<Item = &'_ Layer> + '_ {
134 0 : self.layers()
135 0 : .values()
136 0 : .filter(|l| l.visibility() == LayerVisibilityHint::Visible)
137 0 : }
138 :
139 1848 : pub(crate) fn contains(&self, layer: &Layer) -> bool {
140 1848 : self.contains_key(&layer.layer_desc().key())
141 1848 : }
142 :
143 2460 : pub(crate) fn contains_key(&self, key: &PersistentLayerKey) -> bool {
144 2460 : self.layers().contains_key(key)
145 2460 : }
146 :
147 0 : pub(crate) fn all_persistent_layers(&self) -> Vec<PersistentLayerKey> {
148 0 : self.layers().keys().cloned().collect_vec()
149 0 : }
150 :
151 : /// Update the [`LayerFringe`] of a read request
152 : ///
153 : /// Take a key space at a given LSN and query the layer map below each range
154 : /// of the key space to find the next layers to visit.
155 6736650 : pub(crate) fn update_search_fringe(
156 6736650 : &self,
157 6736650 : keyspace: &KeySpace,
158 6736650 : cont_lsn: Lsn,
159 6736650 : fringe: &mut LayerFringe,
160 6736650 : ) -> Result<(), Shutdown> {
161 6736650 : let map = self.layer_map()?;
162 :
163 6852942 : for range in keyspace.ranges.iter() {
164 6852942 : let results = map.range_search(range.clone(), cont_lsn);
165 6852942 : results
166 6852942 : .found
167 6852942 : .into_iter()
168 6852942 : .map(|(SearchResult { layer, lsn_floor }, keyspace_accum)| {
169 5488046 : (
170 5488046 : self.upgrade(layer),
171 5488046 : keyspace_accum.to_keyspace(),
172 5488046 : lsn_floor..cont_lsn,
173 5488046 : )
174 6852942 : })
175 6852942 : .for_each(|(layer, keyspace, lsn_range)| fringe.update(layer, keyspace, lsn_range));
176 6852942 : }
177 :
178 6736650 : Ok(())
179 6736650 : }
180 :
181 1733527 : fn layers(&self) -> &HashMap<PersistentLayerKey, Layer> {
182 : use LayerManager::*;
183 1733527 : match self {
184 1733527 : Open(OpenLayerManager { layer_fmgr, .. }) => &layer_fmgr.0,
185 0 : Closed { layers } => layers,
186 : }
187 1733527 : }
188 : }
189 :
190 : #[derive(Default)]
191 : pub(crate) struct OpenLayerManager {
192 : layer_map: LayerMap,
193 : layer_fmgr: LayerFileManager<Layer>,
194 : }
195 :
196 : impl std::fmt::Debug for OpenLayerManager {
197 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 0 : f.debug_struct("OpenLayerManager")
199 0 : .field("layer_count", &self.layer_fmgr.0.len())
200 0 : .finish()
201 0 : }
202 : }
203 :
204 : #[derive(Debug, thiserror::Error)]
205 : #[error("layer manager has been shutdown")]
206 : pub(crate) struct Shutdown;
207 :
208 : impl OpenLayerManager {
209 : /// Called from `load_layer_map`. Initialize the layer manager with:
210 : /// 1. all on-disk layers
211 : /// 2. next open layer (with disk disk_consistent_lsn LSN)
212 36 : pub(crate) fn initialize_local_layers(&mut self, layers: Vec<Layer>, next_open_layer_at: Lsn) {
213 36 : let mut updates = self.layer_map.batch_update();
214 132 : for layer in layers {
215 96 : Self::insert_historic_layer(layer, &mut updates, &mut self.layer_fmgr);
216 96 : }
217 36 : updates.flush();
218 36 : self.layer_map.next_open_layer_at = Some(next_open_layer_at);
219 36 : }
220 :
221 : /// Initialize when creating a new timeline, called in `init_empty_layer_map`.
222 2748 : pub(crate) fn initialize_empty(&mut self, next_open_layer_at: Lsn) {
223 2748 : self.layer_map.next_open_layer_at = Some(next_open_layer_at);
224 2748 : }
225 :
226 : /// Open a new writable layer to append data if there is no open layer, otherwise return the
227 : /// current open layer, called within `get_layer_for_write`.
228 : #[allow(clippy::too_many_arguments)]
229 7848 : pub(crate) async fn get_layer_for_write(
230 7848 : &mut self,
231 7848 : lsn: Lsn,
232 7848 : conf: &'static PageServerConf,
233 7848 : timeline_id: TimelineId,
234 7848 : tenant_shard_id: TenantShardId,
235 7848 : gate: &utils::sync::gate::Gate,
236 7848 : cancel: &CancellationToken,
237 7848 : ctx: &RequestContext,
238 7848 : ) -> anyhow::Result<Arc<InMemoryLayer>> {
239 7848 : ensure!(lsn.is_aligned());
240 :
241 : // Do we have a layer open for writing already?
242 7848 : let layer = if let Some(open_layer) = &self.layer_map.open_layer {
243 0 : if open_layer.get_lsn_range().start > lsn {
244 0 : bail!(
245 0 : "unexpected open layer in the future: open layers starts at {}, write lsn {}",
246 0 : open_layer.get_lsn_range().start,
247 0 : lsn
248 0 : );
249 0 : }
250 0 :
251 0 : Arc::clone(open_layer)
252 : } else {
253 : // No writeable layer yet. Create one.
254 7848 : let start_lsn = self
255 7848 : .layer_map
256 7848 : .next_open_layer_at
257 7848 : .context("No next open layer found")?;
258 :
259 7848 : trace!(
260 0 : "creating in-memory layer at {}/{} for record at {}",
261 : timeline_id, start_lsn, lsn
262 : );
263 :
264 7848 : let new_layer = InMemoryLayer::create(
265 7848 : conf,
266 7848 : timeline_id,
267 7848 : tenant_shard_id,
268 7848 : start_lsn,
269 7848 : gate,
270 7848 : cancel,
271 7848 : ctx,
272 7848 : )
273 7848 : .await?;
274 7848 : let layer = Arc::new(new_layer);
275 7848 :
276 7848 : self.layer_map.open_layer = Some(layer.clone());
277 7848 : self.layer_map.next_open_layer_at = None;
278 7848 :
279 7848 : layer
280 : };
281 :
282 7848 : Ok(layer)
283 7848 : }
284 :
285 : /// Tries to freeze an open layer and also manages clearing the TimelineWriterState.
286 : ///
287 : /// Returns true if anything was frozen.
288 7272 : pub(super) async fn try_freeze_in_memory_layer(
289 7272 : &mut self,
290 7272 : lsn: Lsn,
291 7272 : last_freeze_at: &AtomicLsn,
292 7272 : write_lock: &mut tokio::sync::MutexGuard<'_, Option<TimelineWriterState>>,
293 7272 : metrics: &TimelineMetrics,
294 7272 : ) -> bool {
295 7272 : let Lsn(last_record_lsn) = lsn;
296 7272 : let end_lsn = Lsn(last_record_lsn + 1);
297 :
298 7272 : let froze = if let Some(open_layer) = &self.layer_map.open_layer {
299 7104 : let open_layer_rc = Arc::clone(open_layer);
300 7104 : open_layer.freeze(end_lsn).await;
301 :
302 : // Increment the frozen layer metrics. This is decremented in `finish_flush_l0_layer()`.
303 : // TODO: It would be nicer to do this via `InMemoryLayer::drop()`, but it requires a
304 : // reference to the timeline metrics. Other methods use a metrics borrow as well.
305 7104 : metrics.inc_frozen_layer(open_layer);
306 7104 :
307 7104 : // The layer is no longer open, update the layer map to reflect this.
308 7104 : // We will replace it with on-disk historics below.
309 7104 : self.layer_map.frozen_layers.push_back(open_layer_rc);
310 7104 : self.layer_map.open_layer = None;
311 7104 : self.layer_map.next_open_layer_at = Some(end_lsn);
312 7104 :
313 7104 : true
314 : } else {
315 168 : false
316 : };
317 :
318 : // Even if there was no layer to freeze, advance last_freeze_at to last_record_lsn+1: this
319 : // accounts for regions in the LSN range where we might have ingested no data due to sharding.
320 7272 : last_freeze_at.store(end_lsn);
321 7272 :
322 7272 : // the writer state must no longer have a reference to the frozen layer
323 7272 : let taken = write_lock.take();
324 7272 : assert_eq!(
325 7272 : froze,
326 7272 : taken.is_some(),
327 0 : "should only had frozen a layer when TimelineWriterState existed"
328 : );
329 :
330 7272 : froze
331 7272 : }
332 :
333 : /// Add image layers to the layer map, called from [`super::Timeline::create_image_layers`].
334 3480 : pub(crate) fn track_new_image_layers(
335 3480 : &mut self,
336 3480 : image_layers: &[ResidentLayer],
337 3480 : metrics: &TimelineMetrics,
338 3480 : ) {
339 3480 : let mut updates = self.layer_map.batch_update();
340 5004 : for layer in image_layers {
341 1524 : Self::insert_historic_layer(layer.as_ref().clone(), &mut updates, &mut self.layer_fmgr);
342 1524 :
343 1524 : // record these here instead of Layer::finish_creating because otherwise partial
344 1524 : // failure with create_image_layers would balloon up the physical size gauge. downside
345 1524 : // is that all layers need to be created before metrics are updated.
346 1524 : metrics.record_new_file_metrics(layer.layer_desc().file_size);
347 1524 : }
348 3480 : updates.flush();
349 3480 : }
350 :
351 : /// Flush a frozen layer and add the written delta layer to the layer map.
352 7104 : pub(crate) fn finish_flush_l0_layer(
353 7104 : &mut self,
354 7104 : delta_layer: Option<&ResidentLayer>,
355 7104 : frozen_layer_for_check: &Arc<InMemoryLayer>,
356 7104 : metrics: &TimelineMetrics,
357 7104 : ) {
358 7104 : let inmem = self
359 7104 : .layer_map
360 7104 : .frozen_layers
361 7104 : .pop_front()
362 7104 : .expect("there must be a inmem layer to flush");
363 7104 : metrics.dec_frozen_layer(&inmem);
364 7104 :
365 7104 : // Only one task may call this function at a time (for this
366 7104 : // timeline). If two tasks tried to flush the same frozen
367 7104 : // layer to disk at the same time, that would not work.
368 7104 : assert_eq!(Arc::as_ptr(&inmem), Arc::as_ptr(frozen_layer_for_check));
369 :
370 7104 : if let Some(l) = delta_layer {
371 5808 : let mut updates = self.layer_map.batch_update();
372 5808 : Self::insert_historic_layer(l.as_ref().clone(), &mut updates, &mut self.layer_fmgr);
373 5808 : metrics.record_new_file_metrics(l.layer_desc().file_size);
374 5808 : updates.flush();
375 5808 : }
376 7104 : }
377 :
378 : /// Called when compaction is completed.
379 168 : pub(crate) fn finish_compact_l0(
380 168 : &mut self,
381 168 : compact_from: &[Layer],
382 168 : compact_to: &[ResidentLayer],
383 168 : metrics: &TimelineMetrics,
384 168 : ) {
385 168 : let mut updates = self.layer_map.batch_update();
386 2016 : for l in compact_to {
387 1848 : Self::insert_historic_layer(l.as_ref().clone(), &mut updates, &mut self.layer_fmgr);
388 1848 : metrics.record_new_file_metrics(l.layer_desc().file_size);
389 1848 : }
390 2580 : for l in compact_from {
391 2412 : Self::delete_historic_layer(l, &mut updates, &mut self.layer_fmgr);
392 2412 : }
393 168 : updates.flush();
394 168 : }
395 :
396 : /// Called when a GC-compaction is completed.
397 288 : pub(crate) fn finish_gc_compaction(
398 288 : &mut self,
399 288 : compact_from: &[Layer],
400 288 : compact_to: &[ResidentLayer],
401 288 : metrics: &TimelineMetrics,
402 288 : ) {
403 288 : // gc-compaction could contain layer rewrites. We need to delete the old layers and insert the new ones.
404 288 :
405 288 : // Match the old layers with the new layers
406 288 : let mut add_layers = HashMap::new();
407 288 : let mut rewrite_layers = HashMap::new();
408 288 : let mut drop_layers = HashMap::new();
409 912 : for layer in compact_from {
410 624 : drop_layers.insert(layer.layer_desc().key(), layer.clone());
411 624 : }
412 612 : for layer in compact_to {
413 324 : if let Some(old_layer) = drop_layers.remove(&layer.layer_desc().key()) {
414 0 : rewrite_layers.insert(layer.layer_desc().key(), (old_layer.clone(), layer.clone()));
415 324 : } else {
416 324 : add_layers.insert(layer.layer_desc().key(), layer.clone());
417 324 : }
418 : }
419 288 : let add_layers = add_layers.values().cloned().collect::<Vec<_>>();
420 288 : let drop_layers = drop_layers.values().cloned().collect::<Vec<_>>();
421 288 : let rewrite_layers = rewrite_layers.values().cloned().collect::<Vec<_>>();
422 288 :
423 288 : self.rewrite_layers_inner(&rewrite_layers, &drop_layers, &add_layers, metrics);
424 288 : }
425 :
426 : /// Called post-compaction when some previous generation image layers were trimmed.
427 0 : pub fn rewrite_layers(
428 0 : &mut self,
429 0 : rewrite_layers: &[(Layer, ResidentLayer)],
430 0 : drop_layers: &[Layer],
431 0 : metrics: &TimelineMetrics,
432 0 : ) {
433 0 : self.rewrite_layers_inner(rewrite_layers, drop_layers, &[], metrics);
434 0 : }
435 :
436 288 : fn rewrite_layers_inner(
437 288 : &mut self,
438 288 : rewrite_layers: &[(Layer, ResidentLayer)],
439 288 : drop_layers: &[Layer],
440 288 : add_layers: &[ResidentLayer],
441 288 : metrics: &TimelineMetrics,
442 288 : ) {
443 288 : let mut updates = self.layer_map.batch_update();
444 288 : for (old_layer, new_layer) in rewrite_layers {
445 0 : debug_assert_eq!(
446 0 : old_layer.layer_desc().key_range,
447 0 : new_layer.layer_desc().key_range
448 : );
449 0 : debug_assert_eq!(
450 0 : old_layer.layer_desc().lsn_range,
451 0 : new_layer.layer_desc().lsn_range
452 : );
453 :
454 : // Transfer visibility hint from old to new layer, since the new layer covers the same key space. This is not guaranteed to
455 : // be accurate (as the new layer may cover a different subset of the key range), but is a sensible default, and prevents
456 : // always marking rewritten layers as visible.
457 0 : new_layer.as_ref().set_visibility(old_layer.visibility());
458 0 :
459 0 : // Safety: we may never rewrite the same file in-place. Callers are responsible
460 0 : // for ensuring that they only rewrite layers after something changes the path,
461 0 : // such as an increment in the generation number.
462 0 : assert_ne!(old_layer.local_path(), new_layer.local_path());
463 :
464 0 : Self::delete_historic_layer(old_layer, &mut updates, &mut self.layer_fmgr);
465 0 :
466 0 : Self::insert_historic_layer(
467 0 : new_layer.as_ref().clone(),
468 0 : &mut updates,
469 0 : &mut self.layer_fmgr,
470 0 : );
471 0 :
472 0 : metrics.record_new_file_metrics(new_layer.layer_desc().file_size);
473 : }
474 912 : for l in drop_layers {
475 624 : Self::delete_historic_layer(l, &mut updates, &mut self.layer_fmgr);
476 624 : }
477 612 : for l in add_layers {
478 324 : Self::insert_historic_layer(l.as_ref().clone(), &mut updates, &mut self.layer_fmgr);
479 324 : metrics.record_new_file_metrics(l.layer_desc().file_size);
480 324 : }
481 288 : updates.flush();
482 288 : }
483 :
484 : /// Called when garbage collect has selected the layers to be removed.
485 48 : pub(crate) fn finish_gc_timeline(&mut self, gc_layers: &[Layer]) {
486 48 : let mut updates = self.layer_map.batch_update();
487 108 : for doomed_layer in gc_layers {
488 60 : Self::delete_historic_layer(doomed_layer, &mut updates, &mut self.layer_fmgr);
489 60 : }
490 48 : updates.flush()
491 48 : }
492 :
493 : #[cfg(test)]
494 1032 : pub(crate) fn force_insert_layer(&mut self, layer: ResidentLayer) {
495 1032 : let mut updates = self.layer_map.batch_update();
496 1032 : Self::insert_historic_layer(layer.as_ref().clone(), &mut updates, &mut self.layer_fmgr);
497 1032 : updates.flush()
498 1032 : }
499 :
500 : /// Helper function to insert a layer into the layer map and file manager.
501 10632 : fn insert_historic_layer(
502 10632 : layer: Layer,
503 10632 : updates: &mut BatchedUpdates<'_>,
504 10632 : mapping: &mut LayerFileManager<Layer>,
505 10632 : ) {
506 10632 : updates.insert_historic(layer.layer_desc().clone());
507 10632 : mapping.insert(layer);
508 10632 : }
509 :
510 : /// Removes the layer from local FS (if present) and from memory.
511 : /// Remote storage is not affected by this operation.
512 3096 : fn delete_historic_layer(
513 3096 : // we cannot remove layers otherwise, since gc and compaction will race
514 3096 : layer: &Layer,
515 3096 : updates: &mut BatchedUpdates<'_>,
516 3096 : mapping: &mut LayerFileManager<Layer>,
517 3096 : ) {
518 3096 : let desc = layer.layer_desc();
519 3096 :
520 3096 : // TODO Removing from the bottom of the layer map is expensive.
521 3096 : // Maybe instead discard all layer map historic versions that
522 3096 : // won't be needed for page reconstruction for this timeline,
523 3096 : // and mark what we can't delete yet as deleted from the layer
524 3096 : // map index without actually rebuilding the index.
525 3096 : updates.remove_historic(desc);
526 3096 : mapping.remove(layer);
527 3096 : layer.delete_on_drop();
528 3096 : }
529 :
530 : #[cfg(test)]
531 48 : pub(crate) fn force_insert_in_memory_layer(&mut self, layer: Arc<InMemoryLayer>) {
532 : use pageserver_api::models::InMemoryLayerInfo;
533 :
534 48 : match layer.info() {
535 : InMemoryLayerInfo::Open { .. } => {
536 12 : assert!(self.layer_map.open_layer.is_none());
537 12 : self.layer_map.open_layer = Some(layer);
538 : }
539 36 : InMemoryLayerInfo::Frozen { lsn_start, .. } => {
540 36 : if let Some(last) = self.layer_map.frozen_layers.back() {
541 12 : assert!(last.get_lsn_range().end <= lsn_start);
542 24 : }
543 :
544 36 : self.layer_map.frozen_layers.push_back(layer);
545 : }
546 : }
547 48 : }
548 : }
549 :
550 : pub(crate) struct LayerFileManager<T>(HashMap<PersistentLayerKey, T>);
551 :
552 : impl<T> Default for LayerFileManager<T> {
553 2784 : fn default() -> Self {
554 2784 : Self(HashMap::default())
555 2784 : }
556 : }
557 :
558 : impl<T: AsLayerDesc + Clone> LayerFileManager<T> {
559 10632 : pub(crate) fn insert(&mut self, layer: T) {
560 10632 : let present = self.0.insert(layer.layer_desc().key(), layer.clone());
561 10632 : if present.is_some() && cfg!(debug_assertions) {
562 0 : panic!("overwriting a layer: {:?}", layer.layer_desc())
563 10632 : }
564 10632 : }
565 :
566 3096 : pub(crate) fn remove(&mut self, layer: &T) {
567 3096 : let present = self.0.remove(&layer.layer_desc().key());
568 3096 : if present.is_none() && cfg!(debug_assertions) {
569 0 : panic!(
570 0 : "removing layer that is not present in layer mapping: {:?}",
571 0 : layer.layer_desc()
572 0 : )
573 3096 : }
574 3096 : }
575 : }
|