@@ -3,20 +3,19 @@ use crate::lightweight_event::LightweightEvent;
33use crate :: timestamp:: Timestamp ;
44use crate :: StringTable ;
55use measureme:: file_header:: {
6- read_file_header , write_file_header, CURRENT_FILE_FORMAT_VERSION , FILE_HEADER_SIZE ,
7- FILE_MAGIC_EVENT_STREAM ,
6+ verify_file_header , write_file_header, FILE_EXTENSION , FILE_HEADER_SIZE ,
7+ FILE_MAGIC_EVENT_STREAM , FILE_MAGIC_TOP_LEVEL ,
88} ;
99use measureme:: {
10- EventId , PageTag , ProfilerFiles , RawEvent , SerializationSink , SerializationSinkBuilder ,
11- StringTableBuilder ,
10+ EventId , PageTag , RawEvent , SerializationSink , SerializationSinkBuilder , StringTableBuilder ,
1211} ;
1312use serde:: { Deserialize , Deserializer } ;
14- use std:: error:: Error ;
1513use std:: fs;
1614use std:: mem;
1715use std:: path:: Path ;
1816use std:: sync:: Arc ;
1917use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
18+ use std:: { error:: Error , path:: PathBuf } ;
2019
2120const RAW_EVENT_SIZE : usize = mem:: size_of :: < RawEvent > ( ) ;
2221
@@ -46,49 +45,60 @@ pub struct ProfilingData {
4645}
4746
4847impl ProfilingData {
49- pub fn new ( path_stem : & Path ) -> Result < ProfilingData , Box < dyn Error > > {
50- let paths = ProfilerFiles :: new ( path_stem) ;
51-
52- let paged_path = path_stem. with_extension ( "mm_raw" ) ;
48+ pub fn new ( path_stem : & Path ) -> Result < ProfilingData , Box < dyn Error + Send + Sync > > {
49+ let paged_path = path_stem. with_extension ( FILE_EXTENSION ) ;
5350
5451 if paged_path. exists ( ) {
55- let data = fs:: read ( paged_path) . expect ( "couldn't read paged file" ) ;
56- let mut split_data = measureme:: split_streams ( & data[ ..] ) ;
52+ let data = fs:: read ( & paged_path) ?;
53+
54+ verify_file_header ( & data, FILE_MAGIC_TOP_LEVEL , Some ( & paged_path) , "top-level" ) ?;
55+
56+ let mut split_data = measureme:: split_streams ( & data[ FILE_HEADER_SIZE ..] ) ;
5757
5858 let string_data = split_data. remove ( & PageTag :: StringData ) . unwrap ( ) ;
5959 let index_data = split_data. remove ( & PageTag :: StringIndex ) . unwrap ( ) ;
6060 let event_data = split_data. remove ( & PageTag :: Events ) . unwrap ( ) ;
6161
62- ProfilingData :: from_buffers ( string_data, index_data, event_data)
62+ ProfilingData :: from_buffers ( string_data, index_data, event_data, Some ( & paged_path ) )
6363 } else {
64- let string_data =
65- fs:: read ( paths. string_data_file ) . expect ( "couldn't read string_data file" ) ;
66- let index_data =
67- fs:: read ( paths. string_index_file ) . expect ( "couldn't read string_index file" ) ;
68- let event_data = fs:: read ( paths. events_file ) . expect ( "couldn't read events file" ) ;
69-
70- ProfilingData :: from_buffers ( string_data, index_data, event_data)
64+ let mut msg = format ! (
65+ "Could not find profiling data file `{}`." ,
66+ paged_path. display( )
67+ ) ;
68+
69+ // Let's try to give a helpful error message if we encounter files
70+ // in the old three-file-format:
71+ let paths = ProfilerFiles :: new ( path_stem) ;
72+
73+ if paths. events_file . exists ( )
74+ || paths. string_data_file . exists ( )
75+ || paths. string_index_file . exists ( )
76+ {
77+ msg += "It looks like your profiling data has been generated \
78+ by an out-dated version of measureme (0.7 or older).";
79+ }
80+
81+ return Err ( From :: from ( msg) ) ;
7182 }
7283 }
7384
7485 pub fn from_buffers (
7586 string_data : Vec < u8 > ,
7687 string_index : Vec < u8 > ,
7788 events : Vec < u8 > ,
78- ) -> Result < ProfilingData , Box < dyn Error > > {
89+ diagnostic_file_path : Option < & Path > ,
90+ ) -> Result < ProfilingData , Box < dyn Error + Send + Sync > > {
7991 let index_data = string_index;
8092 let event_data = events;
8193
82- let event_data_format = read_file_header ( & event_data, FILE_MAGIC_EVENT_STREAM ) ?;
83- if event_data_format != CURRENT_FILE_FORMAT_VERSION {
84- Err ( format ! (
85- "Event stream file format version '{}' is not supported
86- by this version of `measureme`." ,
87- event_data_format
88- ) ) ?;
89- }
94+ verify_file_header (
95+ & event_data,
96+ FILE_MAGIC_EVENT_STREAM ,
97+ diagnostic_file_path,
98+ "event" ,
99+ ) ?;
90100
91- let string_table = StringTable :: new ( string_data, index_data) ?;
101+ let string_table = StringTable :: new ( string_data, index_data, diagnostic_file_path ) ?;
92102
93103 let metadata = string_table. get_metadata ( ) . to_string ( ) ;
94104 let metadata: Metadata = serde_json:: from_str ( & metadata) ?;
@@ -231,12 +241,13 @@ impl ProfilingDataBuilder {
231241 let string_table_index_sink = Arc :: new ( sink_builder. new_sink ( PageTag :: StringIndex ) ) ;
232242
233243 // The first thing in every file we generate must be the file header.
234- write_file_header ( & event_sink, FILE_MAGIC_EVENT_STREAM ) ;
244+ write_file_header ( & mut event_sink. as_std_write ( ) , FILE_MAGIC_EVENT_STREAM ) . unwrap ( ) ;
235245
236246 let string_table = StringTableBuilder :: new (
237247 string_table_data_sink. clone ( ) ,
238248 string_table_index_sink. clone ( ) ,
239- ) ;
249+ )
250+ . unwrap ( ) ;
240251
241252 ProfilingDataBuilder {
242253 event_sink,
@@ -306,11 +317,9 @@ impl ProfilingDataBuilder {
306317 . unwrap ( )
307318 . into_bytes ( ) ;
308319
309- assert_eq ! (
310- read_file_header( & event_data, FILE_MAGIC_EVENT_STREAM ) . unwrap( ) ,
311- CURRENT_FILE_FORMAT_VERSION
312- ) ;
313- let string_table = StringTable :: new ( data_bytes, index_bytes) . unwrap ( ) ;
320+ verify_file_header ( & event_data, FILE_MAGIC_EVENT_STREAM , None , "event" ) . unwrap ( ) ;
321+
322+ let string_table = StringTable :: new ( data_bytes, index_bytes, None ) . unwrap ( ) ;
314323 let metadata = Metadata {
315324 start_time : UNIX_EPOCH ,
316325 process_id : 0 ,
@@ -338,6 +347,25 @@ fn event_index_to_addr(event_index: usize) -> usize {
338347 FILE_HEADER_SIZE + event_index * mem:: size_of :: < RawEvent > ( )
339348}
340349
350+ // This struct reflects what filenames were in old versions of measureme. It is
351+ // used only for giving helpful error messages now if a user tries to load old
352+ // data.
353+ struct ProfilerFiles {
354+ pub events_file : PathBuf ,
355+ pub string_data_file : PathBuf ,
356+ pub string_index_file : PathBuf ,
357+ }
358+
359+ impl ProfilerFiles {
360+ fn new < P : AsRef < Path > > ( path_stem : P ) -> ProfilerFiles {
361+ ProfilerFiles {
362+ events_file : path_stem. as_ref ( ) . with_extension ( "events" ) ,
363+ string_data_file : path_stem. as_ref ( ) . with_extension ( "string_data" ) ,
364+ string_index_file : path_stem. as_ref ( ) . with_extension ( "string_index" ) ,
365+ }
366+ }
367+ }
368+
341369#[ rustfmt:: skip]
342370#[ cfg( test) ]
343371mod tests {
0 commit comments