LCOV - code coverage report
Current view: top level - pageserver/src/tenant/secondary - heatmap.rs (source / functions) Coverage Total Hit
Test: 09e7485004805bd42b53a0c369170b3228136512.info Lines: 35.4 % 48 17
Test Date: 2024-11-21 18:36:18 Functions: 5.1 % 39 2

            Line data    Source code
       1              : use std::time::SystemTime;
       2              : 
       3              : use crate::tenant::{remote_timeline_client::index::LayerFileMetadata, storage_layer::LayerName};
       4              : 
       5              : use serde::{Deserialize, Serialize};
       6              : use serde_with::{serde_as, DisplayFromStr, TimestampSeconds};
       7              : 
       8              : use utils::{generation::Generation, id::TimelineId};
       9              : 
      10            0 : #[derive(Serialize, Deserialize)]
      11              : pub(super) struct HeatMapTenant {
      12              :     /// Generation of the attached location that uploaded the heatmap: this is not required
      13              :     /// for correctness, but acts as a hint to secondary locations in order to detect thrashing
      14              :     /// in the unlikely event that two attached locations are both uploading conflicting heatmaps.
      15              :     pub(super) generation: Generation,
      16              : 
      17              :     pub(super) timelines: Vec<HeatMapTimeline>,
      18              : 
      19              :     /// Uploaders provide their own upload period in the heatmap, as a hint to downloaders
      20              :     /// of how frequently it is worthwhile to check for updates.
      21              :     ///
      22              :     /// This is optional for backward compat, and because we sometimes might upload
      23              :     /// a heatmap explicitly via API for a tenant that has no periodic upload configured.
      24              :     #[serde(default)]
      25              :     pub(super) upload_period_ms: Option<u128>,
      26              : }
      27              : 
      28              : #[serde_as]
      29            0 : #[derive(Serialize, Deserialize)]
      30              : pub(crate) struct HeatMapTimeline {
      31              :     #[serde_as(as = "DisplayFromStr")]
      32              :     pub(crate) timeline_id: TimelineId,
      33              : 
      34              :     pub(crate) layers: Vec<HeatMapLayer>,
      35              : }
      36              : 
      37              : #[serde_as]
      38            0 : #[derive(Serialize, Deserialize)]
      39              : pub(crate) struct HeatMapLayer {
      40              :     pub(crate) name: LayerName,
      41              :     pub(crate) metadata: LayerFileMetadata,
      42              : 
      43              :     #[serde_as(as = "TimestampSeconds<i64>")]
      44              :     pub(super) access_time: SystemTime,
      45              :     // TODO: an actual 'heat' score that would let secondary locations prioritize downloading
      46              :     // the hottest layers, rather than trying to simply mirror whatever layers are on-disk on the primary.
      47              : }
      48              : 
      49              : impl HeatMapLayer {
      50            8 :     pub(crate) fn new(
      51            8 :         name: LayerName,
      52            8 :         metadata: LayerFileMetadata,
      53            8 :         access_time: SystemTime,
      54            8 :     ) -> Self {
      55            8 :         Self {
      56            8 :             name,
      57            8 :             metadata,
      58            8 :             access_time,
      59            8 :         }
      60            8 :     }
      61              : }
      62              : 
      63              : impl HeatMapTimeline {
      64            2 :     pub(crate) fn new(timeline_id: TimelineId, layers: Vec<HeatMapLayer>) -> Self {
      65            2 :         Self {
      66            2 :             timeline_id,
      67            2 :             layers,
      68            2 :         }
      69            2 :     }
      70              : }
      71              : 
      72              : pub(crate) struct HeatMapStats {
      73              :     pub(crate) bytes: u64,
      74              :     pub(crate) layers: usize,
      75              : }
      76              : 
      77              : impl HeatMapTenant {
      78            0 :     pub(crate) fn get_stats(&self) -> HeatMapStats {
      79            0 :         let mut stats = HeatMapStats {
      80            0 :             bytes: 0,
      81            0 :             layers: 0,
      82            0 :         };
      83            0 :         for timeline in &self.timelines {
      84            0 :             for layer in &timeline.layers {
      85            0 :                 stats.layers += 1;
      86            0 :                 stats.bytes += layer.metadata.file_size;
      87            0 :             }
      88              :         }
      89              : 
      90            0 :         stats
      91            0 :     }
      92              : 
      93            0 :     pub(crate) fn strip_atimes(self) -> Self {
      94            0 :         Self {
      95            0 :             timelines: self
      96            0 :                 .timelines
      97            0 :                 .into_iter()
      98            0 :                 .map(|mut tl| {
      99            0 :                     for layer in &mut tl.layers {
     100            0 :                         layer.access_time = SystemTime::UNIX_EPOCH;
     101            0 :                     }
     102            0 :                     tl
     103            0 :                 })
     104            0 :                 .collect(),
     105            0 :             generation: self.generation,
     106            0 :             upload_period_ms: self.upload_period_ms,
     107            0 :         }
     108            0 :     }
     109              : }
        

Generated by: LCOV version 2.1-beta