2
2
3
3
//use lading_payload::block;
4
4
5
- use std:: collections:: HashMap ;
5
+ use std:: collections:: { HashMap , HashSet } ;
6
6
7
7
use bytes:: Bytes ;
8
8
use lading_payload:: block;
@@ -52,6 +52,10 @@ pub struct File {
52
52
/// The ordinal number of this File. If the file is foo.log the ordinal
53
53
/// number is 0, if foo.log.1 then 1 etc.
54
54
ordinal : u8 ,
55
+
56
+ /// The group ID of this File. So for instance all File instances that are
57
+ /// called foo.log, foo.log.1 etc have the same group ID.
58
+ group_id : u8 ,
55
59
}
56
60
57
61
impl File {
@@ -131,7 +135,7 @@ impl File {
131
135
/// instances or `File` instances. Root directory will not have a `parent`.
132
136
#[ derive( Debug ) ]
133
137
pub struct Directory {
134
- children : HashMap < String , Inode > ,
138
+ children : HashSet < Inode > ,
135
139
parent : Option < Inode > ,
136
140
}
137
141
@@ -140,8 +144,6 @@ pub struct Directory {
140
144
pub enum Node {
141
145
/// A [`File`]
142
146
File {
143
- /// The name of this file. If the full path is /logs/foo.log then this is "foo.log".
144
- name : String ,
145
147
/// The `File` instance.
146
148
file : File ,
147
149
} ,
@@ -176,6 +178,8 @@ pub struct State {
176
178
now : Tick ,
177
179
block_cache : block:: Cache ,
178
180
max_bytes_per_file : u64 ,
181
+ // [GroupID, [Names]]. The interior Vec have size `max_rotations`.
182
+ group_names : Vec < Vec < String > > ,
179
183
}
180
184
181
185
/// The attributes of a `Node`.
@@ -220,10 +224,10 @@ impl State {
220
224
let mut nodes = HashMap :: new ( ) ;
221
225
222
226
let mut root_dir = Directory {
223
- children : HashMap :: new ( ) ,
227
+ children : HashSet :: new ( ) ,
224
228
parent : None ,
225
229
} ;
226
- root_dir. children . insert ( "logs" . to_string ( ) , logs_inode) ;
230
+ root_dir. children . insert ( logs_inode) ;
227
231
nodes. insert (
228
232
root_inode,
229
233
Node :: Directory {
@@ -233,12 +237,10 @@ impl State {
233
237
) ;
234
238
235
239
let mut logs_dir = Directory {
236
- children : HashMap :: new ( ) ,
240
+ children : HashSet :: new ( ) ,
237
241
parent : Some ( root_inode) ,
238
242
} ;
239
- logs_dir
240
- . children
241
- . insert ( "foo.log" . to_string ( ) , foo_log_inode) ;
243
+ logs_dir. children . insert ( foo_log_inode) ;
242
244
nodes. insert (
243
245
logs_inode,
244
246
Node :: Directory {
@@ -247,6 +249,17 @@ impl State {
247
249
} ,
248
250
) ;
249
251
252
+ let mut group_names = Vec :: new ( ) ;
253
+
254
+ // Create names for the rotation group
255
+ let base_name = "foo.log" . to_string ( ) ;
256
+ let mut names = Vec :: new ( ) ;
257
+ names. push ( base_name. clone ( ) ) ; // Ordinal 0
258
+ for i in 1 ..=max_rotations {
259
+ names. push ( format ! ( "foo.log.{i}" ) ) ; // Ordinal i
260
+ }
261
+ group_names. push ( names) ;
262
+
250
263
let foo_log = File {
251
264
parent : logs_inode,
252
265
@@ -261,14 +274,9 @@ impl State {
261
274
262
275
read_only : false ,
263
276
ordinal : 0 ,
277
+ group_id : 0 ,
264
278
} ;
265
- nodes. insert (
266
- foo_log_inode,
267
- Node :: File {
268
- name : "foo.log" . to_string ( ) ,
269
- file : foo_log,
270
- } ,
271
- ) ;
279
+ nodes. insert ( foo_log_inode, Node :: File { file : foo_log } ) ;
272
280
273
281
// NOTE this structure is going to be a problem when I include rotating
274
282
// files. Specifically the inodes will need to change so there might
@@ -281,6 +289,7 @@ impl State {
281
289
now : 0 ,
282
290
block_cache,
283
291
max_bytes_per_file,
292
+ group_names,
284
293
}
285
294
}
286
295
@@ -344,10 +353,21 @@ impl State {
344
353
self . advance_time ( now) ;
345
354
346
355
if let Some ( Node :: Directory { dir, .. } ) = self . nodes . get ( & parent_inode) {
347
- dir. children . get ( name) . copied ( )
348
- } else {
349
- None
356
+ for & child_inode in & dir. children {
357
+ if let Some ( node) = self . nodes . get ( & child_inode) {
358
+ let child_name = match node {
359
+ Node :: File { file } => {
360
+ & self . group_names [ file. group_id as usize ] [ file. ordinal as usize ]
361
+ }
362
+ Node :: Directory { name, .. } => name,
363
+ } ;
364
+ if child_name == name {
365
+ return Some ( child_inode) ;
366
+ }
367
+ }
368
+ }
350
369
}
370
+ None
351
371
}
352
372
353
373
/// Look up the attributes for an `Inode`.
@@ -388,10 +408,7 @@ impl State {
388
408
self . advance_time ( now) ;
389
409
390
410
match self . nodes . get_mut ( & inode) {
391
- Some ( Node :: File {
392
- name : _,
393
- ref mut file,
394
- } ) => {
411
+ Some ( Node :: File { ref mut file } ) => {
395
412
let bytes_written = usize:: try_from ( file. bytes_written )
396
413
. expect ( "more bytes written than machine word" ) ;
397
414
@@ -421,7 +438,7 @@ impl State {
421
438
///
422
439
/// Function does not advance time in the model.
423
440
#[ tracing:: instrument( skip( self ) ) ]
424
- pub fn readdir ( & self , inode : Inode ) -> Option < & HashMap < String , Inode > > {
441
+ pub fn readdir ( & self , inode : Inode ) -> Option < & HashSet < Inode > > {
425
442
if let Some ( Node :: Directory { dir, .. } ) = self . nodes . get ( & inode) {
426
443
Some ( & dir. children )
427
444
} else {
@@ -438,6 +455,24 @@ impl State {
438
455
} )
439
456
}
440
457
458
+ /// Return the name of the inode if it exists
459
+ #[ tracing:: instrument( skip( self ) ) ]
460
+ pub fn get_name ( & self , inode : Inode ) -> Option < & str > {
461
+ if inode == self . root_inode {
462
+ Some ( "/" )
463
+ } else {
464
+ self . nodes
465
+ . get ( & inode)
466
+ . map ( |node| match node {
467
+ Node :: Directory { name, .. } => name,
468
+ Node :: File { file } => {
469
+ & self . group_names [ file. group_id as usize ] [ file. ordinal as usize ]
470
+ }
471
+ } )
472
+ . map ( String :: as_str)
473
+ }
474
+ }
475
+
441
476
/// Return the parent inode of an inode, if it exists
442
477
#[ tracing:: instrument( skip( self ) ) ]
443
478
pub fn get_parent_inode ( & self , inode : Inode ) -> Option < Inode > {
@@ -464,7 +499,7 @@ impl State {
464
499
let subdirectory_count = dir
465
500
. children
466
501
. iter ( )
467
- . filter ( |( _ , child_inode) | {
502
+ . filter ( |child_inode| {
468
503
matches ! ( self . nodes. get( child_inode) , Some ( Node :: Directory { .. } ) )
469
504
} )
470
505
. count ( ) ;
0 commit comments