22
33use std:: sync:: Arc ;
44
5+ use libparsec_platform_async:: event:: EventListener ;
56use libparsec_types:: prelude:: * ;
67
78use crate :: certif:: { InvalidCertificateError , InvalidKeysBundleError , InvalidManifestError } ;
@@ -49,8 +50,9 @@ pub(super) async fn for_update_file(
4950 // Guard's drop will panic if the lock is not released
5051 macro_rules! release_guard_on_error {
5152 ( $update_guard: expr) => {
52- let mut cache_guard = store. current_view_cache. lock( ) . expect( "Mutex is poisoned" ) ;
53- cache_guard. lock_update_manifests. release( $update_guard) ;
53+ store. data. with_current_view_cache( |cache| {
54+ cache. lock_update_manifests. release( $update_guard) ;
55+ } ) ;
5456 } ;
5557 }
5658
@@ -62,36 +64,49 @@ pub(super) async fn for_update_file(
6264 listener. await ;
6365 }
6466
65- let update_guard = {
66- let mut cache_guard = store. current_view_cache . lock ( ) . expect ( "Mutex is poisoned" ) ;
67-
68- // 1) Lock for update
67+ // 1) Lock for update
6968
70- let outcome = cache_guard. lock_update_manifests . take ( entry_id) ;
71- match outcome {
69+ enum LockForUpdateOutcome {
70+ WaitAndRetryStep1 ( EventListener ) ,
71+ // There is no GoToStep2 because it's the dispatching step
72+ GoToStep3 ( ManifestUpdateLockGuard ) ,
73+ GoToStep4 ( ( ManifestUpdateLockGuard , ArcLocalChildManifest ) ) ,
74+ }
75+ let outcome = store. data . with_current_view_cache ( |cache| {
76+ match cache. lock_update_manifests . take ( entry_id) {
7277 ManifestUpdateLockTakeOutcome :: Taken ( update_guard) => {
7378 // 2) Cache lookup for entry...
7479
75- let found = cache_guard . manifests . get ( & entry_id) ;
80+ let found = cache . manifests . get ( & entry_id) ;
7681 if let Some ( manifest) = found {
7782 // Cache hit ! We go to step 4.
78- break ( update_guard, manifest. clone ( ) ) ;
83+ LockForUpdateOutcome :: GoToStep4 ( ( update_guard, manifest. clone ( ) ) )
84+ } else {
85+ // The entry is not in cache, go to step 3 for a lookup in the local storage.
86+ // Note we keep the update lock: this has no impact on read operation, and
87+ // any other write operation taking the lock will have no choice but to try
88+ // to populate the cache just like we are going to do.
89+ LockForUpdateOutcome :: GoToStep3 ( update_guard)
7990 }
80- // The entry is not in cache, go to step 3 for a lookup in the local storage.
81- // Note we keep the update lock: this has no impact on read operation, and
82- // any other write operation taking the lock will have no choice but to try
83- // to populate the cache just like we are going to do.
84- update_guard
8591 }
8692
8793 ManifestUpdateLockTakeOutcome :: NeedWait ( listener) => {
88- if !wait {
89- return Err ( ForUpdateFileError :: WouldBlock ) ;
90- }
91- maybe_need_wait = Some ( listener) ;
92- continue ;
94+ LockForUpdateOutcome :: WaitAndRetryStep1 ( listener)
9395 }
9496 }
97+ } ) ;
98+ let update_guard = match outcome {
99+ LockForUpdateOutcome :: GoToStep3 ( update_guard) => update_guard,
100+ LockForUpdateOutcome :: GoToStep4 ( ( update_guard, manifest) ) => {
101+ break ( update_guard, manifest)
102+ }
103+ LockForUpdateOutcome :: WaitAndRetryStep1 ( listener) => {
104+ if !wait {
105+ return Err ( ForUpdateFileError :: WouldBlock ) ;
106+ }
107+ maybe_need_wait = Some ( listener) ;
108+ continue ;
109+ }
95110 } ;
96111
97112 // Be careful here: `update_guard` must be manually released in case of error !
@@ -143,7 +158,7 @@ pub(super) async fn for_update_file(
143158 } ;
144159
145160 let updater = FileUpdater {
146- _update_guard : update_guard,
161+ update_guard,
147162 #[ cfg( debug_assertions) ]
148163 entry_id : manifest. base . id ,
149164 } ;
@@ -159,7 +174,7 @@ pub(super) async fn for_update_file(
159174/// keep hold on the store.
160175#[ derive( Debug ) ]
161176pub ( crate ) struct FileUpdater {
162- _update_guard : ManifestUpdateLockGuard ,
177+ update_guard : ManifestUpdateLockGuard ,
163178 #[ cfg( debug_assertions) ]
164179 entry_id : VlobID ,
165180}
@@ -176,39 +191,41 @@ impl FileUpdater {
176191 #[ cfg( debug_assertions) ]
177192 assert_eq ! ( manifest. base. id, self . entry_id) ;
178193
179- let mut storage_guard = store. storage . lock ( ) . await ;
180- let storage = storage_guard
181- . as_mut ( )
182- . ok_or_else ( || UpdateFileManifestAndContinueError :: Stopped ) ?;
183-
184194 let update_data = UpdateManifestData {
185195 entry_id : manifest. base . id ,
186196 base_version : manifest. base . version ,
187197 need_sync : manifest. need_sync ,
188198 encrypted : manifest. dump_and_encrypt ( & store. device . local_symkey ) ,
189199 } ;
190-
191200 let new_chunks = new_chunks
192201 . map ( |( chunk_id, cleartext) | ( chunk_id, store. device . local_symkey . encrypt ( cleartext) ) ) ;
193- storage
194- . update_manifest_and_chunks ( & update_data, new_chunks, removed_chunks)
202+ store
203+ . data
204+ . with_storage ( |maybe_storage| async move {
205+ let storage = maybe_storage
206+ . as_mut ( )
207+ . ok_or_else ( || UpdateFileManifestAndContinueError :: Stopped ) ?;
208+
209+ storage
210+ . update_manifest_and_chunks ( & update_data, new_chunks, removed_chunks)
211+ . await
212+ . map_err ( UpdateFileManifestAndContinueError :: Internal )
213+ } )
195214 . await ?;
196215
197216 // Finally update cache
198- let mut cache = store. current_view_cache . lock ( ) . expect ( "Mutex is poisoned" ) ;
199- cache
200- . manifests
201- . insert ( ArcLocalChildManifest :: File ( manifest) ) ;
217+ store. data . with_current_view_cache ( |cache| {
218+ cache
219+ . manifests
220+ . insert ( ArcLocalChildManifest :: File ( manifest) ) ;
221+ } ) ;
202222
203223 Ok ( ( ) )
204224 }
205225
206226 pub fn close ( self , store : & super :: WorkspaceStore ) {
207- store
208- . current_view_cache
209- . lock ( )
210- . expect ( "Mutex is poisoned" )
211- . lock_update_manifests
212- . release ( self . _update_guard ) ;
227+ store. data . with_current_view_cache ( |cache| {
228+ cache. lock_update_manifests . release ( self . update_guard ) ;
229+ } ) ;
213230 }
214231}
0 commit comments