wasmer_journal/
snapshot.rs

1use std::fmt::Display;
2
3use wasmer_config::app::SnapshotTrigger as ConfigSnapshotTrigger;
4
5use super::*;
6
7/// Various triggers that will cause the runtime to take snapshot
8/// of the WASM state and store it in the snapshot file.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub enum SnapshotTrigger {
11    /// Triggered when all the threads in the process goes idle
12    Idle,
13    /// Triggered when a listen syscall is invoked on a socket for the first time
14    FirstListen,
15    /// Triggered on reading the environment variables for the first time
16    FirstEnviron,
17    /// Triggered when the process reads stdin for the first time
18    FirstStdin,
19    /// Issued on the first interrupt signal (Ctrl + C) the process receives, after that normal CTRL-C will apply.
20    FirstSigint,
21    /// Triggered periodically based on a interval (default 10 seconds) which can be specified using the `snapshot-interval` option
22    PeriodicInterval,
23    /// Issued if the user sends an interrupt signal (Ctrl + C).
24    Sigint,
25    /// Alarm clock signal (used for timers)
26    Sigalrm,
27    /// The SIGTSTP signal is sent to a process by its controlling terminal to request it to stop temporarily. It is commonly initiated by the user pressing Ctrl-Z.
28    Sigtstp,
29    /// The SIGSTOP signal instructs the operating system to stop a process for later resumption.
30    Sigstop,
31    /// When a non-determinstic call is made
32    NonDeterministicCall,
33    /// Bootstrapping process
34    Bootstrap,
35    /// Transaction
36    Transaction,
37    /// Explicitly requested by the guest module
38    Explicit,
39}
40
41impl SnapshotTrigger {
42    pub fn only_once(&self) -> bool {
43        matches!(
44            self,
45            Self::FirstListen
46                | Self::FirstEnviron
47                | Self::FirstStdin
48                | Self::FirstSigint
49                // TODO: I don't think this should be an only_once trigger, but
50                // repeatable triggers currently get stuck in a loop
51                | Self::Explicit
52        )
53    }
54}
55
56pub const DEFAULT_SNAPSHOT_TRIGGERS: [SnapshotTrigger; 5] = [
57    SnapshotTrigger::Idle,
58    SnapshotTrigger::FirstEnviron,
59    SnapshotTrigger::FirstListen,
60    SnapshotTrigger::FirstStdin,
61    SnapshotTrigger::Explicit,
62];
63
64// We're purposefully redirecting serialization-related functionality for SnapshotTrigger
65// through the equivalent type in wasmer_config (ConfigSnapshotTrigger) to make sure the
66// two types always stay in sync.
67impl From<ConfigSnapshotTrigger> for SnapshotTrigger {
68    fn from(value: ConfigSnapshotTrigger) -> Self {
69        match value {
70            ConfigSnapshotTrigger::Bootstrap => Self::Bootstrap,
71            ConfigSnapshotTrigger::Explicit => Self::Explicit,
72            ConfigSnapshotTrigger::FirstEnviron => Self::FirstEnviron,
73            ConfigSnapshotTrigger::FirstListen => Self::FirstListen,
74            ConfigSnapshotTrigger::FirstSigint => Self::FirstSigint,
75            ConfigSnapshotTrigger::FirstStdin => Self::FirstStdin,
76            ConfigSnapshotTrigger::Idle => Self::Idle,
77            ConfigSnapshotTrigger::NonDeterministicCall => Self::NonDeterministicCall,
78            ConfigSnapshotTrigger::PeriodicInterval => Self::PeriodicInterval,
79            ConfigSnapshotTrigger::Sigalrm => Self::Sigalrm,
80            ConfigSnapshotTrigger::Sigint => Self::Sigint,
81            ConfigSnapshotTrigger::Sigstop => Self::Sigstop,
82            ConfigSnapshotTrigger::Sigtstp => Self::Sigtstp,
83            ConfigSnapshotTrigger::Transaction => Self::Transaction,
84        }
85    }
86}
87
88impl From<SnapshotTrigger> for ConfigSnapshotTrigger {
89    fn from(value: SnapshotTrigger) -> Self {
90        match value {
91            SnapshotTrigger::Bootstrap => Self::Bootstrap,
92            SnapshotTrigger::Explicit => Self::Explicit,
93            SnapshotTrigger::FirstEnviron => Self::FirstEnviron,
94            SnapshotTrigger::FirstListen => Self::FirstListen,
95            SnapshotTrigger::FirstSigint => Self::FirstSigint,
96            SnapshotTrigger::FirstStdin => Self::FirstStdin,
97            SnapshotTrigger::Idle => Self::Idle,
98            SnapshotTrigger::NonDeterministicCall => Self::NonDeterministicCall,
99            SnapshotTrigger::PeriodicInterval => Self::PeriodicInterval,
100            SnapshotTrigger::Sigalrm => Self::Sigalrm,
101            SnapshotTrigger::Sigint => Self::Sigint,
102            SnapshotTrigger::Sigstop => Self::Sigstop,
103            SnapshotTrigger::Sigtstp => Self::Sigtstp,
104            SnapshotTrigger::Transaction => Self::Transaction,
105        }
106    }
107}
108
109impl FromStr for SnapshotTrigger {
110    type Err = <ConfigSnapshotTrigger as FromStr>::Err;
111
112    fn from_str(s: &str) -> Result<Self, Self::Err> {
113        <ConfigSnapshotTrigger as FromStr>::from_str(s).map(Into::into)
114    }
115}
116
117impl Display for SnapshotTrigger {
118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119        <ConfigSnapshotTrigger as Display>::fmt(&(*self).into(), f)
120    }
121}
122
123impl Serialize for SnapshotTrigger {
124    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
125    where
126        S: serde::Serializer,
127    {
128        ConfigSnapshotTrigger::from(*self).serialize(serializer)
129    }
130}
131
132impl<'de> Deserialize<'de> for SnapshotTrigger {
133    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134    where
135        D: serde::Deserializer<'de>,
136    {
137        <ConfigSnapshotTrigger as Deserialize>::deserialize(deserializer).map(Into::into)
138    }
139}