Skip to main content

memscope_rs/event_store/
event.rs

1//! Core memory event types for the event store
2//!
3//! This module defines the unified memory event type used across
4//! all engines in the memscope architecture.
5
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// Type of memory event
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub enum MemoryEventType {
12    /// Memory allocation event
13    Allocate,
14    /// Memory deallocation event
15    Deallocate,
16    /// Memory reallocation event
17    Reallocate,
18    /// Memory move event
19    Move,
20    /// Memory borrow event
21    Borrow,
22    /// Memory return event
23    Return,
24}
25
26impl fmt::Display for MemoryEventType {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        match self {
29            MemoryEventType::Allocate => write!(f, "Allocate"),
30            MemoryEventType::Deallocate => write!(f, "Deallocate"),
31            MemoryEventType::Reallocate => write!(f, "Reallocate"),
32            MemoryEventType::Move => write!(f, "Move"),
33            MemoryEventType::Borrow => write!(f, "Borrow"),
34            MemoryEventType::Return => write!(f, "Return"),
35        }
36    }
37}
38
39/// Unified memory event type
40///
41/// This structure captures all essential information about memory operations
42/// across all tracking backends (core, lockfree, async, unified).
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct MemoryEvent {
45    /// Event timestamp (nanoseconds since epoch)
46    pub timestamp: u64,
47    /// Event type
48    pub event_type: MemoryEventType,
49    /// Memory pointer address
50    pub ptr: usize,
51    /// Allocation size in bytes
52    pub size: usize,
53    /// Previous allocation size (for Reallocate events)
54    pub old_size: Option<usize>,
55    /// Thread identifier
56    pub thread_id: u64,
57    /// Optional variable name
58    pub var_name: Option<String>,
59    /// Optional type name
60    pub type_name: Option<String>,
61    /// Optional call stack hash
62    pub call_stack_hash: Option<u64>,
63    /// Optional thread name
64    pub thread_name: Option<String>,
65}
66
67impl MemoryEvent {
68    /// Create a new allocation event
69    pub fn allocate(ptr: usize, size: usize, thread_id: u64) -> Self {
70        Self {
71            timestamp: Self::now(),
72            event_type: MemoryEventType::Allocate,
73            ptr,
74            size,
75            old_size: None,
76            thread_id,
77            var_name: None,
78            type_name: None,
79            call_stack_hash: None,
80            thread_name: None,
81        }
82    }
83
84    /// Create a new deallocation event
85    pub fn deallocate(ptr: usize, size: usize, thread_id: u64) -> Self {
86        Self {
87            timestamp: Self::now(),
88            event_type: MemoryEventType::Deallocate,
89            ptr,
90            size,
91            old_size: None,
92            thread_id,
93            var_name: None,
94            type_name: None,
95            call_stack_hash: None,
96            thread_name: None,
97        }
98    }
99
100    /// Create a new reallocation event
101    pub fn reallocate(ptr: usize, old_size: usize, new_size: usize, thread_id: u64) -> Self {
102        Self {
103            timestamp: Self::now(),
104            event_type: MemoryEventType::Reallocate,
105            ptr,
106            size: new_size,
107            old_size: Some(old_size),
108            thread_id,
109            var_name: None,
110            type_name: None,
111            call_stack_hash: None,
112            thread_name: None,
113        }
114    }
115
116    /// Get current timestamp in nanoseconds
117    /// Returns 0 if system time is before Unix epoch (should not happen in practice)
118    pub fn now() -> u64 {
119        use std::time::{SystemTime, UNIX_EPOCH};
120        SystemTime::now()
121            .duration_since(UNIX_EPOCH)
122            .map(|d| d.as_nanos() as u64)
123            .unwrap_or_default()
124    }
125
126    /// Set variable name
127    pub fn with_var_name(mut self, name: String) -> Self {
128        self.var_name = Some(name);
129        self
130    }
131
132    /// Set type name
133    pub fn with_type_name(mut self, name: String) -> Self {
134        self.type_name = Some(name);
135        self
136    }
137
138    /// Set call stack hash
139    pub fn with_call_stack_hash(mut self, hash: u64) -> Self {
140        self.call_stack_hash = Some(hash);
141        self
142    }
143
144    /// Set thread name
145    pub fn with_thread_name(mut self, name: String) -> Self {
146        self.thread_name = Some(name);
147        self
148    }
149
150    /// Check if this is an allocation event
151    pub fn is_allocation(&self) -> bool {
152        matches!(
153            self.event_type,
154            MemoryEventType::Allocate | MemoryEventType::Reallocate
155        )
156    }
157
158    /// Check if this is a deallocation event
159    pub fn is_deallocation(&self) -> bool {
160        matches!(self.event_type, MemoryEventType::Deallocate)
161    }
162
163    /// Check if this is a move event
164    pub fn is_move(&self) -> bool {
165        matches!(self.event_type, MemoryEventType::Move)
166    }
167
168    /// Check if this is a borrow event
169    pub fn is_borrow(&self) -> bool {
170        matches!(self.event_type, MemoryEventType::Borrow)
171    }
172
173    /// Check if this is a return event
174    pub fn is_return(&self) -> bool {
175        matches!(self.event_type, MemoryEventType::Return)
176    }
177}