@ -2,7 +2,7 @@ use crate::error::unexpected::{self, Intoable, Mappable};
use crate ::{ origin , util } ;
use std ::path ::{ Path , PathBuf } ;
use std ::{ collections , fs , io , sync } ;
use std ::{ collections , fs , future , io , sync } ;
use futures ::stream ;
@ -216,50 +216,62 @@ impl FSStore {
}
impl super ::Store for FSStore {
fn sync ( & self , descr : & origin ::Descr ) -> Result < ( ) , origin ::SyncError > {
// attempt to lock this descr for syncing, doing so within a new scope so the mutex
// isn't actually being held for the whole method duration.
let is_already_syncing = {
self . sync_guard
. lock ( )
. unwrap ( )
. insert ( descr . clone ( ) , ( ) )
. is_some ( )
} ;
fn sync (
& self ,
descr : & origin ::Descr ,
) -> util ::BoxFuture < ' static , Result < ( ) , origin ::SyncError > > {
// TODO this implementation is kind of cheating, as it's doing everything synchronously but
// then returning the result in an async box. But the git store is going to be
// re-implemented soon anyway, so it doesn't matter.
let res = ( | | {
// attempt to lock this descr for syncing, doing so within a new scope so the mutex
// isn't actually being held for the whole method duration.
let is_already_syncing = {
self . sync_guard
. lock ( )
. unwrap ( )
. insert ( descr . clone ( ) , ( ) )
. is_some ( )
} ;
if is_already_syncing {
return Err ( origin ::SyncError ::AlreadyInProgress ) ;
}
if is_already_syncing {
return Err ( origin ::SyncError ::AlreadyInProgress ) ;
}
let res = self . sync_inner ( & descr ) ;
let res = self . sync_inner ( descr ) ;
self . sync_guard . lock ( ) . unwrap ( ) . remove ( & descr ) ;
self . sync_guard . lock ( ) . unwrap ( ) . remove ( descr ) ;
let repo = match res {
Ok ( repo ) = > repo ,
Err ( e ) = > return Err ( e ) ,
} ;
let repo = match res {
Ok ( repo ) = > repo ,
Err ( e ) = > return Err ( e ) ,
} ;
// repo is synced at this point (though the sync lock is still held), just gotta create
// the RepoSnapshot and store it.
//
// TODO this is a bit of a memory leak, but by the time we get
// to that point this should all be backed by something which isn't local storage
// anyway.
// repo is synced at this point (though the sync lock is still held), just gotta create
// the RepoSnapshot and store it.
//
// TODO this is a bit of a memory leak, but by the time we get
// to that point this should all be backed by something which isn't local storage
// anyway.
// calling this while the sync lock is held isn't ideal, but it's convenient and
// shouldn't be too terrible generally
let repo_snapshot = self
. create_repo_snapshot ( repo , & descr )
. map_err ( | e | match e {
CreateRepoSnapshotError ::InvalidBranchName = > {
origin ::SyncError ::InvalidBranchName
}
CreateRepoSnapshotError ::Unexpected ( e ) = > origin ::SyncError ::Unexpected ( e ) ,
} ) ? ;
// calling this while the sync lock is held isn't ideal, but it's convenient and
// shouldn't be too terrible generally
let repo_snapshot = self
. create_repo_snapshot ( repo , descr )
. map_err ( | e | match e {
CreateRepoSnapshotError ::InvalidBranchName = > origin ::SyncError ::InvalidBranchName ,
CreateRepoSnapshotError ::Unexpected ( e ) = > origin ::SyncError ::Unexpected ( e ) ,
} ) ? ;
let mut repo_snapshots = self . repo_snapshots . write ( ) . unwrap ( ) ;
( * repo_snapshots ) . insert ( descr . clone ( ) , sync ::Arc ::new ( repo_snapshot ) ) ;
let mut repo_snapshots = self . repo_snapshots . write ( ) . unwrap ( ) ;
( * repo_snapshots ) . insert ( descr . clone ( ) , sync ::Arc ::new ( repo_snapshot ) ) ;
Ok ( ( ) )
} ) ( ) ;
Ok ( ( ) )
Box ::pin ( future ::ready ( res ) )
}
fn all_descrs ( & self ) -> Result < Vec < origin ::Descr > , origin ::AllDescrsError > {
@ -374,8 +386,11 @@ mod tests {
let store = super ::FSStore ::new ( & config ) . expect ( "store created" ) ;
store . sync ( & descr ) . expect ( "sync should succeed" ) ;
store . sync ( & descr ) . expect ( "second sync should succeed" ) ;
store . sync ( & descr ) . await . expect ( "sync should succeed" ) ;
store
. sync ( & descr )
. await
. expect ( "second sync should succeed" ) ;
// RepoSnapshot doesn't exist
match store . get_file ( & other_descr , "DNE" ) {