| ... | ... | @@ -2,6 +2,7 @@ gpa: Allocator, |
| 2 | 2 | manifest_dir: fs.Dir, |
| 3 | 3 | hash: HashHelper = .{}, |
| 4 | 4 | recent_problematic_timestamp: i128 = 0, |
| 5 | want_refresh_timestamp: bool = true, |
| 5 | 6 | |
| 6 | 7 | const Cache = @This(); |
| 7 | 8 | const std = @import("std"); |
| ... | ... | @@ -346,6 +347,12 @@ pub const Manifest = struct { |
| 346 | 347 | } |
| 347 | 348 | } |
| 348 | 349 | |
| 350 | // Indicate that we want isProblematicTimestamp to perform a filesystem write in |
| 351 | // order to obtain a problematic timestamp for the next call. Calls after that |
| 352 | // in this same hit() function call will then use the same timestamp, to avoid |
| 353 | // writing multiple times to the filesystem. |
| 354 | @atomicStore(bool, &self.cache.want_refresh_timestamp, true, .Monotonic); |
| 355 | |
| 349 | 356 | const file_contents = try self.manifest_file.?.reader().readAllAlloc(self.cache.gpa, manifest_file_size_max); |
| 350 | 357 | defer self.cache.gpa.free(file_contents); |
| 351 | 358 | |
| ... | ... | @@ -749,18 +756,29 @@ fn hashFile(file: fs.File, bin_digest: *[Hasher.mac_length]u8) !void { |
| 749 | 756 | fn isProblematicTimestamp(cache: *Cache, file_time: i128) bool { |
| 750 | 757 | // If the file_time is prior to the most recent problematic timestamp |
| 751 | 758 | // then we don't need to access the filesystem. |
| 752 | | if (file_time < cache.recent_problematic_timestamp) |
| 759 | var ts = @atomicLoad(i128, &cache.recent_problematic_timestamp, .Monotonic); |
| 760 | if (file_time < ts) |
| 753 | 761 | return false; |
| 754 | 762 | |
| 755 | | var file = cache.manifest_dir.createFile("timestamp", .{ |
| 756 | | .read = true, |
| 757 | | .truncate = true, |
| 758 | | }) catch return true; |
| 759 | | defer file.close(); |
| 763 | if (@atomicRmw(bool, &cache.want_refresh_timestamp, .Xchg, false, .Monotonic)) { |
| 764 | var file = cache.manifest_dir.createFile("timestamp", .{ |
| 765 | .read = true, |
| 766 | .truncate = true, |
| 767 | }) catch return true; |
| 768 | defer file.close(); |
| 760 | 769 | |
| 761 | | cache.recent_problematic_timestamp = (file.stat() catch return true).mtime; |
| 770 | const new_ts = (file.stat() catch return true).mtime; |
| 771 | ts = if (@cmpxchgWeak( |
| 772 | i128, |
| 773 | &cache.recent_problematic_timestamp, |
| 774 | ts, |
| 775 | new_ts, |
| 776 | .Monotonic, |
| 777 | .Monotonic, |
| 778 | )) |race_ts| race_ts else new_ts; |
| 779 | } |
| 762 | 780 | |
| 763 | | return file_time >= cache.recent_problematic_timestamp; |
| 781 | return file_time >= ts; |
| 764 | 782 | } |
| 765 | 783 | |
| 766 | 784 | // Create/Write a file, close it, then grab its stat.mtime timestamp. |