@@ -174,12 +174,15 @@ use std::{
174174 marker:: PhantomData ,
175175 num:: NonZeroU64 ,
176176 path:: { Path , PathBuf } ,
177- sync:: Arc ,
177+ sync:: {
178+ Arc ,
179+ atomic:: { AtomicU64 , Ordering } ,
180+ } ,
178181} ;
179182
180183use async_trait:: async_trait;
181184use snafu:: { ResultExt , Snafu } ;
182- use tracing:: debug;
185+ use tracing:: { debug, info } ;
183186use vector_common:: finalization:: Finalizable ;
184187
185188mod backed_archive;
@@ -212,6 +215,62 @@ use crate::{
212215 } ,
213216} ;
214217
218+ /// An approximate view of unread records in a disk buffer.
219+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
220+ pub struct DiskBufferUsageSnapshot {
221+ /// Number of unread events in the buffer.
222+ pub event_count : u64 ,
223+ /// Encoded size of unread records in the buffer.
224+ pub byte_size : u64 ,
225+ }
226+
227+ /// Read-only access to the current unread usage of a disk buffer.
228+ #[ derive( Clone , Debug ) ]
229+ pub struct DiskBufferUsageHandle {
230+ event_count : Arc < AtomicU64 > ,
231+ byte_size : Arc < AtomicU64 > ,
232+ }
233+
234+ impl DiskBufferUsageHandle {
235+ fn new ( ) -> Self {
236+ Self {
237+ event_count : Arc :: new ( AtomicU64 :: new ( 0 ) ) ,
238+ byte_size : Arc :: new ( AtomicU64 :: new ( 0 ) ) ,
239+ }
240+ }
241+
242+ /// Gets the approximate current number and encoded size of unread records.
243+ pub fn snapshot ( & self ) -> DiskBufferUsageSnapshot {
244+ DiskBufferUsageSnapshot {
245+ event_count : self . event_count . load ( Ordering :: Relaxed ) ,
246+ byte_size : self . byte_size . load ( Ordering :: Relaxed ) ,
247+ }
248+ }
249+
250+ fn set ( & self , event_count : u64 , byte_size : u64 ) {
251+ self . event_count . store ( event_count, Ordering :: Relaxed ) ;
252+ self . byte_size . store ( byte_size, Ordering :: Relaxed ) ;
253+ }
254+
255+ fn increment ( & self , event_count : u64 , byte_size : u64 ) {
256+ self . event_count . fetch_add ( event_count, Ordering :: Relaxed ) ;
257+ self . byte_size . fetch_add ( byte_size, Ordering :: Relaxed ) ;
258+ }
259+
260+ fn decrement ( & self , event_count : u64 , byte_size : u64 ) {
261+ _ = self
262+ . event_count
263+ . fetch_update ( Ordering :: Relaxed , Ordering :: Relaxed , |current| {
264+ Some ( current. saturating_sub ( event_count) )
265+ } ) ;
266+ _ = self
267+ . byte_size
268+ . fetch_update ( Ordering :: Relaxed , Ordering :: Relaxed , |current| {
269+ Some ( current. saturating_sub ( byte_size) )
270+ } ) ;
271+ }
272+ }
273+
215274/// Error that occurred when creating/loading a disk buffer.
216275#[ derive( Debug , Snafu ) ]
217276pub enum BufferError < T >
@@ -396,7 +455,8 @@ where
396455 usage_handle. set_buffer_limits ( Some ( max_size. get ( ) ) , None ) ;
397456
398457 let buffer_path = get_disk_v2_data_dir_path ( data_dir, id) ;
399- let builder = DiskBufferConfigBuilder :: from_path ( buffer_path) . max_buffer_size ( max_size. get ( ) ) ;
458+ let builder =
459+ DiskBufferConfigBuilder :: from_path ( buffer_path. clone ( ) ) . max_buffer_size ( max_size. get ( ) ) ;
400460 // Shrink the data-file size (and the matching record size) so files fill and
401461 // rotate constantly. That is what reaches the rare recovery paths the bug hides
402462 // in: reopening a file whose last write was cut short, and reusing a file number
@@ -412,9 +472,27 @@ where
412472 None => builder,
413473 } ;
414474 let config = builder. build ( ) ?;
415- Buffer :: from_config ( config, usage_handle)
475+ let ( writer , reader ) = Buffer :: from_config ( config, usage_handle)
416476 . await
417- . map_err ( Into :: into)
477+ . map_err ( Box :: < dyn Error + Send + Sync > :: from) ?;
478+ let existing_usage = writer. usage_handle ( ) . snapshot ( ) ;
479+ if existing_usage. event_count > 0 || existing_usage. byte_size > 0 {
480+ info ! (
481+ buffer_id = id,
482+ buffer_dir = buffer_path. to_string_lossy( ) . as_ref( ) ,
483+ unread_events = existing_usage. event_count,
484+ unread_bytes = existing_usage. byte_size,
485+ message = "Opened disk buffer with unread data." ,
486+ ) ;
487+ } else {
488+ debug ! (
489+ buffer_id = id,
490+ buffer_dir = buffer_path. to_string_lossy( ) . as_ref( ) ,
491+ message = "Opened empty disk buffer." ,
492+ ) ;
493+ }
494+
495+ Ok ( ( writer, reader) )
418496}
419497
420498pub ( crate ) fn get_disk_v2_data_dir_path ( base_dir : & Path , buffer_id : & str ) -> PathBuf {
0 commit comments