Skip to main content

memscope_rs/capture/
engine.rs

1//! Capture Engine - Event capture backend
2//!
3//! This module provides the CaptureEngine which is responsible for
4//! capturing memory events from the application and forwarding them
5//! to the EventStore. The CaptureEngine does not store events itself;
6//! it only captures and forwards them.
7
8use crate::capture::backends::{CaptureBackend, CaptureBackendType};
9use crate::event_store::SharedEventStore;
10
11/// Capture Engine - Event capture backend
12///
13/// The CaptureEngine is responsible for capturing memory events from
14/// the application and forwarding them to the EventStore. It does not
15/// store events itself; it only captures and forwards them.
16///
17/// Key properties:
18/// - Non-blocking: All capture operations are non-blocking
19/// - Backend abstraction: Supports multiple capture backends
20/// - Zero-storage: Events are forwarded to EventStore, not stored locally
21pub struct CaptureEngine {
22    /// The capture backend being used
23    backend: Box<dyn CaptureBackend>,
24    /// Reference to the event store for recording events
25    event_store: SharedEventStore,
26}
27
28impl CaptureEngine {
29    /// Create a new CaptureEngine with the specified backend
30    ///
31    /// # Arguments
32    /// * `backend_type` - The type of capture backend to use
33    /// * `event_store` - Reference to the event store
34    pub fn new(backend_type: CaptureBackendType, event_store: SharedEventStore) -> Self {
35        let backend = backend_type.create_backend();
36        Self {
37            backend,
38            event_store,
39        }
40    }
41
42    /// Capture an allocation event
43    ///
44    /// # Arguments
45    /// * `ptr` - Memory pointer address
46    /// * `size` - Allocation size in bytes
47    /// * `thread_id` - Thread identifier
48    pub fn capture_alloc(&self, ptr: usize, size: usize, thread_id: u64) {
49        let event = self.backend.capture_alloc(ptr, size, thread_id);
50        self.event_store.record(event);
51    }
52
53    /// Capture a deallocation event
54    ///
55    /// # Arguments
56    /// * `ptr` - Memory pointer address
57    /// * `size` - Deallocation size in bytes
58    /// * `thread_id` - Thread identifier
59    pub fn capture_dealloc(&self, ptr: usize, size: usize, thread_id: u64) {
60        let event = self.backend.capture_dealloc(ptr, size, thread_id);
61        self.event_store.record(event);
62    }
63
64    /// Capture a reallocation event
65    ///
66    /// # Arguments
67    /// * `ptr` - Memory pointer address
68    /// * `old_size` - Old allocation size in bytes
69    /// * `new_size` - New allocation size in bytes
70    /// * `thread_id` - Thread identifier
71    pub fn capture_realloc(&self, ptr: usize, old_size: usize, new_size: usize, thread_id: u64) {
72        let event = self
73            .backend
74            .capture_realloc(ptr, old_size, new_size, thread_id);
75        self.event_store.record(event);
76    }
77
78    /// Capture a move event
79    ///
80    /// # Arguments
81    /// * `from_ptr` - Source pointer address
82    /// * `to_ptr` - Destination pointer address
83    /// * `size` - Size in bytes
84    /// * `thread_id` - Thread identifier
85    pub fn capture_move(&self, from_ptr: usize, to_ptr: usize, size: usize, thread_id: u64) {
86        let event = self.backend.capture_move(from_ptr, to_ptr, size, thread_id);
87        self.event_store.record(event);
88    }
89
90    /// Get the event store reference
91    pub fn event_store(&self) -> &SharedEventStore {
92        &self.event_store
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99    use crate::event_store::EventStore;
100    use std::sync::Arc;
101
102    #[test]
103    fn test_capture_engine_creation() {
104        let event_store = Arc::new(EventStore::new());
105        let engine = CaptureEngine::new(CaptureBackendType::Core, event_store);
106        assert!(engine.event_store().is_empty());
107    }
108
109    #[test]
110    fn test_capture_alloc() {
111        let event_store = Arc::new(EventStore::new());
112        let engine = CaptureEngine::new(CaptureBackendType::Core, event_store.clone());
113        engine.capture_alloc(0x1000, 1024, 1);
114        assert_eq!(event_store.len(), 1);
115    }
116
117    #[test]
118    fn test_capture_dealloc() {
119        let event_store = Arc::new(EventStore::new());
120        let engine = CaptureEngine::new(CaptureBackendType::Core, event_store.clone());
121        engine.capture_dealloc(0x1000, 1024, 1);
122        assert_eq!(event_store.len(), 1);
123    }
124
125    #[test]
126    fn test_capture_multiple_events() {
127        let event_store = Arc::new(EventStore::new());
128        let engine = CaptureEngine::new(CaptureBackendType::Core, event_store.clone());
129        engine.capture_alloc(0x1000, 1024, 1);
130        engine.capture_dealloc(0x1000, 1024, 1);
131        engine.capture_alloc(0x2000, 2048, 1);
132        assert_eq!(event_store.len(), 3);
133    }
134}