@@ -19,13 +19,26 @@ use gix::prelude::*;
1919use lru:: LruCache ;
2020use std:: collections:: HashMap ;
2121use std:: num:: NonZeroUsize ;
22+ use std:: path:: Path ;
23+ use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
2224
2325const DEFAULT_CACHE_SIZE : NonZeroUsize = NonZeroUsize :: new ( 1000 ) . unwrap ( ) ;
26+ static SYNC_TEMP_COUNTER : AtomicU64 = AtomicU64 :: new ( 0 ) ;
2427use parking_lot:: Mutex ;
2528use std:: sync:: Arc ;
2629
2730use super :: { NodeStorage , StorageError } ;
2831
32+ fn sync_temp_path ( dataset_dir : & Path , nanos : u64 ) -> std:: path:: PathBuf {
33+ let counter = SYNC_TEMP_COUNTER . fetch_add ( 1 , Ordering :: Relaxed ) ;
34+ dataset_dir. join ( format ! (
35+ ".prolly_hash_mappings.{}.{}.{}" ,
36+ std:: process:: id( ) ,
37+ nanos,
38+ counter
39+ ) )
40+ }
41+
2942/// Git-backed storage for ProllyTree nodes
3043///
3144/// This storage implementation uses Git blobs to store serialized ProllyNode instances.
@@ -309,11 +322,7 @@ impl<const N: usize> NodeStorage<N> for GitNodeStorage<N> {
309322 . duration_since ( std:: time:: UNIX_EPOCH )
310323 . map ( |d| d. as_nanos ( ) as u64 )
311324 . unwrap_or ( 0 ) ;
312- let tmp = self . dataset_dir . join ( format ! (
313- ".prolly_hash_mappings.{}.{}" ,
314- std:: process:: id( ) ,
315- nanos
316- ) ) ;
325+ let tmp = sync_temp_path ( & self . dataset_dir , nanos) ;
317326 {
318327 use std:: io:: Write as _;
319328 let mut f = std:: fs:: File :: create ( & tmp) . map_err ( StorageError :: Io ) ?;
@@ -440,6 +449,18 @@ mod tests {
440449 assert ! ( cached. is_some( ) ) ;
441450 }
442451
452+ #[ test]
453+ fn sync_temp_path_uses_counter_for_same_timestamp ( ) {
454+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
455+ let first = sync_temp_path ( temp_dir. path ( ) , 123 ) ;
456+ let second = sync_temp_path ( temp_dir. path ( ) , 123 ) ;
457+
458+ assert_ne ! (
459+ first, second,
460+ "same-process sync temp paths must not collide for the same timestamp"
461+ ) ;
462+ }
463+
443464 #[ test]
444465 fn clone_preserves_memory_only_tree_config ( ) {
445466 let ( temp_dir, repo) = create_test_repo ( ) ;
0 commit comments