| ... | @@ -2,6 +2,7 @@ gpa: Allocator, | ... | @@ -2,6 +2,7 @@ gpa: Allocator, |
| 2 | manifest_dir: fs.Dir, | 2 | manifest_dir: fs.Dir, |
| 3 | hash: HashHelper = .{}, | 3 | hash: HashHelper = .{}, |
| 4 | recent_problematic_timestamp: i128 = 0, | 4 | recent_problematic_timestamp: i128 = 0, |
| | 5 | want_refresh_timestamp: bool = true, |
| 5 | | 6 | |
| 6 | const Cache = @This(); | 7 | const Cache = @This(); |
| 7 | const std = @import("std"); | 8 | const std = @import("std"); |
| ... | @@ -346,6 +347,12 @@ pub const Manifest = struct { | ... | @@ -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 | const file_contents = try self.manifest_file.?.reader().readAllAlloc(self.cache.gpa, manifest_file_size_max); | 356 | const file_contents = try self.manifest_file.?.reader().readAllAlloc(self.cache.gpa, manifest_file_size_max); |
| 350 | defer self.cache.gpa.free(file_contents); | 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,18 +756,29 @@ fn hashFile(file: fs.File, bin_digest: *[Hasher.mac_length]u8) !void { |
| 749 | fn isProblematicTimestamp(cache: *Cache, file_time: i128) bool { | 756 | fn isProblematicTimestamp(cache: *Cache, file_time: i128) bool { |
| 750 | // If the file_time is prior to the most recent problematic timestamp | 757 | // If the file_time is prior to the most recent problematic timestamp |
| 751 | // then we don't need to access the filesystem. | 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 | return false; | 761 | return false; |
| 754 | | 762 | |
| 755 | var file = cache.manifest_dir.createFile("timestamp", .{ | 763 | if (@atomicRmw(bool, &cache.want_refresh_timestamp, .Xchg, false, .Monotonic)) { |
| 756 | .read = true, | 764 | var file = cache.manifest_dir.createFile("timestamp", .{ |
| 757 | .truncate = true, | 765 | .read = true, |
| 758 | }) catch return true; | 766 | .truncate = true, |
| 759 | defer file.close(); | 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 | // Create/Write a file, close it, then grab its stat.mtime timestamp. | 784 | // Create/Write a file, close it, then grab its stat.mtime timestamp. |