-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce type InvalidationDataInfoOrFuture to replace InvalidationDa…
…taReference. This change will replace `InvalidationDataReference` with a new type hierarchy, `InvalidationDataInfoOrFuture`, to manage information about remotely stored invalidation data for files, directory listings, and nested file system operation nodes. `InvalidationDataInfoOrFuture` is not hooked up to anything in this change but broken out for ease of review. **Motivation:** The previous `InvalidationDataReference` model relied on immediate availability of Maximum Transitive Source Versions (MTSVs) from Skyframe, however, that approach creates too much coupling. Computing MTSVs will now require a full traversal of the Skyframe dependency graph. This traversal is parallelized, leading to potential race conditions where multiple threads might attempt to compute the same value redundantly. **Solution:** The `InvalidationDataInfoOrFuture` hierarchy addresses this by: 1. **Memoization:** Employing `SettableFutureKeyedValue` to memoize the results of the parallelized MTSV computation, preventing redundant work. 2. **Type Safety:** Introducing a type system that clearly distinguishes between constant (no persisted data), value (persisted data with cache key and write status), and future (in-progress computation) states for each of the three basic types: files, directory listings, and nodes (nested sets of files and directory listings). This improved type safety allows for more precise handling of invalidation data. **Details:** - The hierarchy uses sealed interfaces to represent the different states and types of invalidation data. - `FileDataInfo` includes the MTSV and resolved real path for ancestor resolution and symlink handling. - `Constant*` types (e.g., `ConstantFileData`) indicate that no invalidation data is associated, enabling a collection type declaration to simply exclude (uninformative) constants. `InvalidationDataReference` will be removed in a subsequent change. PiperOrigin-RevId: 716224019 Change-Id: I6ee05721ff8a220cce0643a34d5c8a53a5ba4d0f
- Loading branch information
1 parent
fce65ab
commit b9b83b7
Showing
2 changed files
with
195 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
183 changes: 183 additions & 0 deletions
183
...ogle/devtools/build/lib/skyframe/serialization/analysis/InvalidationDataInfoOrFuture.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
// Copyright 2024 The Bazel Authors. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
package com.google.devtools.build.lib.skyframe.serialization.analysis; | ||
|
||
import com.google.common.util.concurrent.ListenableFuture; | ||
import com.google.devtools.build.lib.concurrent.SettableFutureKeyedValue; | ||
import com.google.devtools.build.lib.skyframe.DirectoryListingKey; | ||
import com.google.devtools.build.lib.skyframe.FileKey; | ||
import com.google.devtools.build.lib.skyframe.NestedFileSystemOperationNodes; | ||
import com.google.devtools.build.lib.skyframe.serialization.PackedFingerprint; | ||
import com.google.devtools.build.lib.vfs.RootedPath; | ||
import java.util.function.BiConsumer; | ||
|
||
/** | ||
* Information about remotely stored invalidation data. | ||
* | ||
* <p>There are 3 distinct type families, associated with files, directory listings and nodes | ||
* (nested sets of files and directory listings). | ||
* | ||
* <p>Each family has 3 types, a constant type (no persisted data), information about stored | ||
* invalidation data or a future. Information about stored invalidation data always includes a cache | ||
* key and a {@link ListenableFuture<Void>} write status. | ||
* | ||
* <p>In the case of {@link FileInvalidationData}, a Max Transitive Source Version (MTSV) and fully | ||
* resolved path is also included. These fields are used for ancestor resolution. | ||
*/ | ||
@SuppressWarnings("InterfaceWithOnlyStatics") // sealed hierarchy root | ||
sealed interface InvalidationDataInfoOrFuture | ||
permits InvalidationDataInfoOrFuture.InvalidationDataInfo, | ||
InvalidationDataInfoOrFuture.FileDataInfoOrFuture, | ||
InvalidationDataInfoOrFuture.ListingDataInfoOrFuture, | ||
InvalidationDataInfoOrFuture.NodeDataInfoOrFuture { | ||
|
||
/** Non-future, immediate value sub-types of {@link InvalidationDataInfoOrFuture}. */ | ||
sealed interface InvalidationDataInfo extends InvalidationDataInfoOrFuture | ||
permits FileDataInfo, ListingDataInfo, NodeDataInfo {} | ||
|
||
/** Base implementation of a {@link InvalidationDataInfoOrFuture} value. */ | ||
abstract static sealed class BaseInvalidationDataInfo<T> { | ||
private final T cacheKey; | ||
private final ListenableFuture<Void> writeStatus; | ||
|
||
BaseInvalidationDataInfo(T cacheKey, ListenableFuture<Void> writeStatus) { | ||
this.cacheKey = cacheKey; | ||
this.writeStatus = writeStatus; | ||
} | ||
|
||
/** Key for {@link com.google.devtools.build.lib.serialization.FingerprintValueService}. */ | ||
final T cacheKey() { | ||
return cacheKey; | ||
} | ||
|
||
/** Transitively inclusive status of writing this data to the cache. */ | ||
final ListenableFuture<Void> writeStatus() { | ||
return writeStatus; | ||
} | ||
} | ||
|
||
sealed interface FileDataInfoOrFuture extends InvalidationDataInfoOrFuture | ||
permits FileDataInfo, FutureFileDataInfo {} | ||
|
||
sealed interface FileDataInfo extends FileDataInfoOrFuture, InvalidationDataInfo | ||
permits ConstantFileData, FileInvalidationDataInfo {} | ||
|
||
/** The file doesn't change and isn't associated with any invalidation data. */ | ||
enum ConstantFileData implements FileDataInfo { | ||
CONSTANT_FILE; | ||
} | ||
|
||
/** Information about transitive upload of invalidation data for a certain {@link FileKey}. */ | ||
static final class FileInvalidationDataInfo extends BaseInvalidationDataInfo<String> | ||
implements FileDataInfo { | ||
private final long mtsv; | ||
private final RootedPath realPath; | ||
|
||
FileInvalidationDataInfo( | ||
String cacheKey, ListenableFuture<Void> writeStatus, long mtsv, RootedPath realPath) { | ||
super(cacheKey, writeStatus); | ||
this.mtsv = mtsv; | ||
this.realPath = realPath; | ||
} | ||
|
||
/** | ||
* The MTSV. | ||
* | ||
* <p>Used by dependents to create parent references. This information is already incorporated | ||
* into the {@link #cacheKey} value. | ||
*/ | ||
long mtsv() { | ||
return mtsv; | ||
} | ||
|
||
/** | ||
* The resolved real path. | ||
* | ||
* <p>Used for symlink resolution. | ||
*/ | ||
RootedPath realPath() { | ||
return realPath; | ||
} | ||
} | ||
|
||
static final class FutureFileDataInfo | ||
extends SettableFutureKeyedValue<FutureFileDataInfo, FileKey, FileDataInfo> | ||
implements FileDataInfoOrFuture { | ||
FutureFileDataInfo(FileKey key, BiConsumer<FileKey, FileDataInfo> consumer) { | ||
super(key, consumer); | ||
} | ||
} | ||
|
||
sealed interface ListingDataInfoOrFuture extends InvalidationDataInfoOrFuture | ||
permits ListingDataInfo, FutureListingDataInfo {} | ||
|
||
sealed interface ListingDataInfo extends ListingDataInfoOrFuture, InvalidationDataInfo | ||
permits ConstantListingData, ListingInvalidationDataInfo {} | ||
|
||
/** This listing doesn't change and isn't associated with invalidation data. */ | ||
enum ConstantListingData implements ListingDataInfo { | ||
CONSTANT_LISTING; | ||
} | ||
|
||
/** | ||
* Information about transitive upload of invalidation data for a certain {@link | ||
* DirectoryListingKey}. | ||
*/ | ||
static final class ListingInvalidationDataInfo extends BaseInvalidationDataInfo<String> | ||
implements ListingDataInfo { | ||
ListingInvalidationDataInfo(String cacheKey, ListenableFuture<Void> writeStatus) { | ||
super(cacheKey, writeStatus); | ||
} | ||
} | ||
|
||
static final class FutureListingDataInfo | ||
extends SettableFutureKeyedValue<FutureListingDataInfo, DirectoryListingKey, ListingDataInfo> | ||
implements ListingDataInfoOrFuture { | ||
FutureListingDataInfo( | ||
DirectoryListingKey key, BiConsumer<DirectoryListingKey, ListingDataInfo> consumer) { | ||
super(key, consumer); | ||
} | ||
} | ||
|
||
sealed interface NodeDataInfoOrFuture extends InvalidationDataInfoOrFuture | ||
permits NodeDataInfo, FutureNodeDataInfo {} | ||
|
||
sealed interface NodeDataInfo extends NodeDataInfoOrFuture, InvalidationDataInfo | ||
permits ConstantNodeData, NodeInvalidationDataInfo {} | ||
|
||
enum ConstantNodeData implements NodeDataInfo { | ||
CONSTANT_NODE; | ||
} | ||
|
||
/** Information about remotely persisted {@link NestedFileSystemOperationNodes}. */ | ||
static final class NodeInvalidationDataInfo extends BaseInvalidationDataInfo<PackedFingerprint> | ||
implements NodeDataInfo { | ||
NodeInvalidationDataInfo(PackedFingerprint key, ListenableFuture<Void> writeStatus) { | ||
super(key, writeStatus); | ||
} | ||
} | ||
|
||
static final class FutureNodeDataInfo | ||
extends SettableFutureKeyedValue< | ||
FutureNodeDataInfo, NestedFileSystemOperationNodes, NodeDataInfo> | ||
implements NodeDataInfoOrFuture { | ||
FutureNodeDataInfo(NestedFileSystemOperationNodes key) { | ||
super(key, FutureNodeDataInfo::setNodeDataInfo); | ||
} | ||
|
||
private static void setNodeDataInfo(NestedFileSystemOperationNodes key, NodeDataInfo value) { | ||
key.setSerializationScratch(value); | ||
} | ||
} | ||
} |