You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constERROR_PREFIX:&str = "file-based cache store error:";
62
62
constTEMPFILE_SUFFIX:&str = "tmp";
@@ -203,11 +203,18 @@ impl FileStore {
203
203
.await?;
204
204
205
205
// Here's the flow:
206
-
// We sync the data after writing to it. This ensures that we get the correctly written data even if the later ops fail.
207
-
// We unlock first to let progress move. This is free when there are no concurrent accessor. If we rename then unlock, the final file gets locked instead when subsequent readers progress, defeating the purpose of this method.
208
-
// We create a new file handle to see whether the file still exists or not. If it doesn't exist, we move on. It's most likely has been deleted by `create_dir_root_sync` or `clear`.
209
-
// Finally, we rename only if the thread reasonably hold the "last" lock to the .tmp.
210
-
// This doesn't guarantee that no .tmp file will be renamed by another thread, but it pushes the guarantees towards "writers write and hold in .tmp file, not contesting the final file"
206
+
// We sync the data after writing to it. This ensures that we get the correctly
207
+
// written data even if the later ops fail. We unlock first to let
208
+
// progress move. This is free when there are no concurrent accessor. If we
209
+
// rename then unlock, the final file gets locked instead when subsequent
210
+
// readers progress, defeating the purpose of this method. We create a
211
+
// new file handle to see whether the file still exists or not. If it doesn't
212
+
// exist, we move on. It's most likely has been deleted by
213
+
// `create_dir_root_sync` or `clear`. Finally, we rename only if the
214
+
// thread reasonably hold the "last" lock to the .tmp. This doesn't
215
+
// guarantee that no .tmp file will be renamed by another thread, but it pushes
216
+
// the guarantees towards "writers write and hold in .tmp file, not contesting
let temp_path = self.dir_path.join(format!("{key_hash}.{TEMPFILE_SUFFIX}"));
370
377
371
-
// We must let the loop to propagate upwards to catch sudden missing cache directory
372
-
// Then it would be easier for us to wait for file creation where we offload one lock check into the OS by using `create_new()`. So, the flow looks like this,
378
+
// We must let the loop to propagate upwards to catch sudden missing cache
379
+
// directory Then it would be easier for us to wait for file creation
380
+
// where we offload one lock check into the OS by using `create_new()`. So, the
381
+
// flow looks like this,
373
382
// 1. `create_new()` -> fail, we check if the error is AlreadyExists.
374
-
// 2. In a condition where (1) is triggered, we park task into a blocking thread waiting for the lock to move.
383
+
// 2. In a condition where (1) is triggered, we park task into a blocking thread
384
+
// waiting for the lock to move.
375
385
// 3. The blocking thread will only wait for the existing file in the temp_path
376
386
//
377
-
// This approach was chosen because we can't possibly (at least for now) to create a file AND lock that file atomically. A window where the existing file may get renamed or deleted is expected. Therefore, the blocking task is a pessimistic write.
387
+
// This approach was chosen because we can't possibly (at least for now) to
388
+
// create a file AND lock that file atomically. A window where the existing file
389
+
// may get renamed or deleted is expected. Therefore, the blocking task is a
390
+
// pessimistic write.
378
391
379
392
letmut retry_count = 0;
380
393
let temp_file = loop{
@@ -755,6 +768,9 @@ mod tests {
755
768
let _ = tokio::fs::remove_dir_all(&path).await;
756
769
}
757
770
771
+
// Ignored in miri since it currently doesn't support
0 commit comments