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,48 @@ 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+ GoToStep3 ( ManifestUpdateLockGuard ) ,
72+ GoToStep4 ( ( ManifestUpdateLockGuard , ArcLocalChildManifest ) ) ,
73+ }
74+ let outcome = store. data . with_current_view_cache ( |cache| {
75+ match cache. lock_update_manifests . take ( entry_id) {
7276 ManifestUpdateLockTakeOutcome :: Taken ( update_guard) => {
7377 // 2) Cache lookup for entry...
7478
75- let found = cache_guard . manifests . get ( & entry_id) ;
79+ let found = cache . manifests . get ( & entry_id) ;
7680 if let Some ( manifest) = found {
7781 // Cache hit ! We go to step 4.
78- break ( update_guard, manifest. clone ( ) ) ;
82+ LockForUpdateOutcome :: GoToStep4 ( ( update_guard, manifest. clone ( ) ) )
83+ } else {
84+ // The entry is not in cache, go to step 3 for a lookup in the local storage.
85+ // Note we keep the update lock: this has no impact on read operation, and
86+ // any other write operation taking the lock will have no choice but to try
87+ // to populate the cache just like we are going to do.
88+ LockForUpdateOutcome :: GoToStep3 ( update_guard)
7989 }
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
8590 }
8691
8792 ManifestUpdateLockTakeOutcome :: NeedWait ( listener) => {
88- if !wait {
89- return Err ( ForUpdateFileError :: WouldBlock ) ;
90- }
91- maybe_need_wait = Some ( listener) ;
92- continue ;
93+ LockForUpdateOutcome :: WaitAndRetryStep1 ( listener)
9394 }
9495 }
96+ } ) ;
97+ let update_guard = match outcome {
98+ LockForUpdateOutcome :: GoToStep3 ( update_guard) => update_guard,
99+ LockForUpdateOutcome :: GoToStep4 ( ( update_guard, manifest) ) => {
100+ break ( update_guard, manifest)
101+ }
102+ LockForUpdateOutcome :: WaitAndRetryStep1 ( listener) => {
103+ if !wait {
104+ return Err ( ForUpdateFileError :: WouldBlock ) ;
105+ }
106+ maybe_need_wait = Some ( listener) ;
107+ continue ;
108+ }
95109 } ;
96110
97111 // Be careful here: `update_guard` must be manually released in case of error !
@@ -143,7 +157,7 @@ pub(super) async fn for_update_file(
143157 } ;
144158
145159 let updater = FileUpdater {
146- _update_guard : update_guard,
160+ update_guard,
147161 #[ cfg( debug_assertions) ]
148162 entry_id : manifest. base . id ,
149163 } ;
@@ -159,7 +173,7 @@ pub(super) async fn for_update_file(
159173/// keep hold on the store.
160174#[ derive( Debug ) ]
161175pub ( crate ) struct FileUpdater {
162- _update_guard : ManifestUpdateLockGuard ,
176+ update_guard : ManifestUpdateLockGuard ,
163177 #[ cfg( debug_assertions) ]
164178 entry_id : VlobID ,
165179}
@@ -176,39 +190,41 @@ impl FileUpdater {
176190 #[ cfg( debug_assertions) ]
177191 assert_eq ! ( manifest. base. id, self . entry_id) ;
178192
179- let mut storage_guard = store. storage . lock ( ) . await ;
180- let storage = storage_guard
181- . as_mut ( )
182- . ok_or_else ( || UpdateFileManifestAndContinueError :: Stopped ) ?;
183-
184193 let update_data = UpdateManifestData {
185194 entry_id : manifest. base . id ,
186195 base_version : manifest. base . version ,
187196 need_sync : manifest. need_sync ,
188197 encrypted : manifest. dump_and_encrypt ( & store. device . local_symkey ) ,
189198 } ;
190-
191199 let new_chunks = new_chunks
192200 . 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)
201+ store
202+ . data
203+ . with_storage ( |maybe_storage| async move {
204+ let storage = maybe_storage
205+ . as_mut ( )
206+ . ok_or_else ( || UpdateFileManifestAndContinueError :: Stopped ) ?;
207+
208+ storage
209+ . update_manifest_and_chunks ( & update_data, new_chunks, removed_chunks)
210+ . await
211+ . map_err ( UpdateFileManifestAndContinueError :: Internal )
212+ } )
195213 . await ?;
196214
197215 // 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) ) ;
216+ store. data . with_current_view_cache ( |cache| {
217+ cache
218+ . manifests
219+ . insert ( ArcLocalChildManifest :: File ( manifest) ) ;
220+ } ) ;
202221
203222 Ok ( ( ) )
204223 }
205224
206225 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 ) ;
226+ store. data . with_current_view_cache ( |cache| {
227+ cache. lock_update_manifests . release ( self . update_guard ) ;
228+ } ) ;
213229 }
214230}
0 commit comments