LLVM 24.0.0git
UnifiedOnDiskCache.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CAS_UNIFIEDONDISKCACHE_H
10#define LLVM_CAS_UNIFIEDONDISKCACHE_H
11
14#include <atomic>
15
16namespace llvm::cas::ondisk {
17
19
20/// A unified CAS nodes and key-value database, using on-disk storage for both.
21/// It manages storage growth and provides APIs for garbage collection.
22///
23/// High-level properties:
24/// * While \p UnifiedOnDiskCache is open on a directory, by any process, the
25/// storage size in that directory will keep growing unrestricted. For data to
26/// become eligible for garbage-collection there should be no open instances
27/// of \p UnifiedOnDiskCache for that directory, by any process.
28/// * Garbage-collection needs to be triggered explicitly by the client. It can
29/// be triggered on a directory concurrently, at any time and by any process,
30/// without affecting any active readers/writers, in the same process or other
31/// processes.
32///
33/// Usage patterns should be that an instance of \p UnifiedOnDiskCache is open
34/// for a limited period of time, e.g. for the duration of a build operation.
35/// For long-living processes that need periodic access to a
36/// \p UnifiedOnDiskCache, the client should devise a scheme where access is
37/// performed within some defined period. For example, if a service is designed
38/// to continuously wait for requests that access a \p UnifiedOnDiskCache, it
39/// could keep the instance alive while new requests are coming in but close it
40/// after a time period in which there are no new requests.
41class UnifiedOnDiskCache {
42public:
43 /// The \p OnDiskGraphDB instance for the open directory.
44 OnDiskGraphDB &getGraphDB() { return *PrimaryGraphDB; }
45
46 /// The \p OnDiskGraphDB instance for the open directory.
47 const OnDiskGraphDB &getGraphDB() const { return *PrimaryGraphDB; }
48
49 /// The \p OnDiskGraphDB instance for the open directory.
50 OnDiskKeyValueDB &getKeyValueDB() { return *PrimaryKVDB; }
51
52 /// The \p OnDiskGraphDB instance for the open directory.
53 const OnDiskKeyValueDB &getKeyValueDB() const { return *PrimaryKVDB; }
54
55 /// Open a \p UnifiedOnDiskCache instance for a directory.
56 ///
57 /// \param Path directory for the on-disk database. The directory will be
58 /// created if it doesn't exist.
59 /// \param SizeLimit Optional size for limiting growth. This has an effect for
60 /// when the instance is closed.
61 /// \param HashName Identifier name for the hashing algorithm that is going to
62 /// be used.
63 /// \param HashByteSize Size for the object digest hash bytes.
64 /// \param FaultInPolicy Controls how nodes are copied to primary store. This
65 /// is recorded at creation time and subsequent opens need to pass the same
66 /// policy otherwise the \p open will fail.
68 open(StringRef Path, std::optional<uint64_t> SizeLimit, StringRef HashName,
69 unsigned HashByteSize,
70 OnDiskGraphDB::FaultInPolicy FaultInPolicy =
72
73 /// Validate the data in \p Path in-process, if it has not been validated
74 /// since the last system boot. A successful validation is recorded so that
75 /// subsequent calls can skip it; a failed or crashed one is recorded as
76 /// pending for \c recover, and is not skipped by subsequent calls. Where the
77 /// boot time is not known validation is never skipped.
78 ///
79 /// Clients that want to be resilient to unexpected crashes during validation
80 /// may call this from a separate process (e.g. via
81 /// \c llvm-cas -validate-if-needed) and call \c recover if it fails.
82 ///
83 /// \param Path directory for the on-disk database.
84 /// \param HashName Identifier name for the hashing algorithm that is going to
85 /// be used.
86 /// \param HashByteSize Size for the object digest hash bytes.
87 /// \param CheckHash Whether to validate hashes match the data.
88 /// \param ForceValidation Whether to force validation to occur even if it
89 /// should not be necessary.
90 ///
91 /// \returns \c Valid if the data is valid, \c Skipped if validation is not
92 /// needed, or an \c Error if validation cannot be performed or the data is
93 /// invalid.
95 validateIfNeeded(StringRef Path, StringRef HashName, unsigned HashByteSize,
96 bool CheckHash, OnDiskGraphDB::HashingFuncT HashFn,
97 bool ForceValidation);
98
99 /// Recover from invalid data in \p Path after a failed \c validateIfNeeded,
100 /// by marking all the data for garbage collection.
101 ///
102 /// Recovery requires exclusive access to the CAS and it is an error to
103 /// attempt recovery if there is concurrent use of the CAS.
104 ///
105 /// Recovery is serialized with \c validateIfNeeded, and only happens if the
106 /// last validation failed or crashed. If the data has been recovered or
107 /// validated successfully since, e.g. by a concurrent process, recovery is
108 /// skipped.
109 ///
110 /// \param Path directory for the on-disk database.
111 ///
112 /// \returns \c Recovered if the data has been cleared, \c Skipped if
113 /// recovery is not needed, or an \c Error if recovery cannot be performed.
115
116 /// Validate the action cache only.
118
119 /// This is called implicitly at destruction time, so it is not required for a
120 /// client to call this. After calling \p close the only method that is valid
121 /// to call is \p needsGarbageCollection.
122 ///
123 /// \param CheckSizeLimit if true it will check whether the primary store has
124 /// exceeded its intended size limit. If false the check is skipped even if a
125 /// \p SizeLimit was passed to the \p open call.
126 LLVM_ABI Error close(bool CheckSizeLimit = true);
127
128 /// Set the size for limiting growth. This has an effect for when the instance
129 /// is closed.
130 LLVM_ABI void setSizeLimit(std::optional<uint64_t> SizeLimit);
131
132 /// \returns the storage size of the cache data.
134
135 /// \returns whether the primary store has exceeded the intended size limit.
136 /// This can return false even if the overall size of the opened directory is
137 /// over the \p SizeLimit passed to \p open. To know whether garbage
138 /// collection needs to be triggered or not, call \p needsGarbaseCollection.
139 LLVM_ABI bool hasExceededSizeLimit() const;
140
141 /// \returns whether there are unused data that can be deleted using a
142 /// \p collectGarbage call.
143 bool needsGarbageCollection() const { return NeedsGarbageCollection; }
144
145 /// Remove any unused data from the directory at \p Path. If there are no such
146 /// data the operation is a no-op.
147 ///
148 /// This can be called concurrently, regardless of whether there is an open
149 /// \p UnifiedOnDiskCache instance or not; it has no effect on readers/writers
150 /// in the same process or other processes.
151 ///
152 /// It is recommended that garbage-collection is triggered concurrently in the
153 /// background, so that it has minimal effect on the workload of the process.
154 LLVM_ABI static Error
156
157 /// Remove unused data from the current UnifiedOnDiskCache.
159
160 /// Helper function to convert the value stored in KeyValueDB and ObjectID.
162
163 using ValueBytes = std::array<char, sizeof(uint64_t)>;
165
167
168private:
169 friend class OnDiskGraphDB;
170 friend class OnDiskKeyValueDB;
171 UnifiedOnDiskCache();
172
174 faultInFromUpstreamKV(ArrayRef<uint8_t> Key);
175
176 /// \returns the storage size of the primary directory.
177 uint64_t getPrimaryStorageSize() const;
178
179 std::string RootPath;
180 std::atomic<uint64_t> SizeLimit;
181
182 int LockFD = -1;
183
184 std::atomic<bool> NeedsGarbageCollection;
185 std::string PrimaryDBDir;
186
187 std::unique_ptr<OnDiskGraphDB> UpstreamGraphDB;
188 std::unique_ptr<OnDiskGraphDB> PrimaryGraphDB;
189
190 std::unique_ptr<OnDiskKeyValueDB> UpstreamKVDB;
191 std::unique_ptr<OnDiskKeyValueDB> PrimaryKVDB;
192
193 std::shared_ptr<ondisk::OnDiskCASLogger> Logger = nullptr;
194};
195
196} // namespace llvm::cas::ondisk
197
198#endif // LLVM_CAS_UNIFIEDONDISKCACHE_H
unsigned uint64_t
#define LLVM_ABI
Definition Compiler.h:215
static cl::opt< unsigned > SizeLimit("eif-limit", cl::init(6), cl::Hidden, cl::desc("Size limit in Hexagon early if-conversion"))
This declares OnDiskGraphDB, an ondisk CAS database with a fixed length hash.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
Logging utility - given an ordered specification of features, and assuming a scalar reward,...
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM Value Representation.
Definition Value.h:75
Reference to a node.
Interface for logging low-level on-disk cas operations.
FaultInPolicy
How to fault-in nodes if an upstream database is used.
@ FullTree
Copy the the entire graph of a node.
function_ref< void( ArrayRef< ArrayRef< uint8_t > >, ArrayRef< char >, SmallVectorImpl< uint8_t > &)> HashingFuncT
Hashing function type for validation.
An on-disk key-value data store with the following properties:
OnDiskGraphDB & getGraphDB()
The OnDiskGraphDB instance for the open directory.
static LLVM_ABI ValueBytes getValueFromObjectID(ObjectID ID)
static LLVM_ABI Expected< ValidationResult > recover(StringRef Path)
Recover from invalid data in Path after a failed validateIfNeeded, by marking all the data for garbag...
static LLVM_ABI Expected< std::unique_ptr< UnifiedOnDiskCache > > open(StringRef Path, std::optional< uint64_t > SizeLimit, StringRef HashName, unsigned HashByteSize, OnDiskGraphDB::FaultInPolicy FaultInPolicy=OnDiskGraphDB::FaultInPolicy::FullTree)
Open a UnifiedOnDiskCache instance for a directory.
LLVM_ABI Error close(bool CheckSizeLimit=true)
This is called implicitly at destruction time, so it is not required for a client to call this.
LLVM_ABI Error validateActionCache() const
Validate the action cache only.
const OnDiskKeyValueDB & getKeyValueDB() const
The OnDiskGraphDB instance for the open directory.
static LLVM_ABI ObjectID getObjectIDFromValue(ArrayRef< char > Value)
Helper function to convert the value stored in KeyValueDB and ObjectID.
const OnDiskGraphDB & getGraphDB() const
The OnDiskGraphDB instance for the open directory.
static LLVM_ABI Expected< ValidationResult > validateIfNeeded(StringRef Path, StringRef HashName, unsigned HashByteSize, bool CheckHash, OnDiskGraphDB::HashingFuncT HashFn, bool ForceValidation)
Validate the data in Path in-process, if it has not been validated since the last system boot.
OnDiskKeyValueDB & getKeyValueDB()
The OnDiskGraphDB instance for the open directory.
std::array< char, sizeof(uint64_t)> ValueBytes
LLVM_ABI Error collectGarbage()
Remove unused data from the current UnifiedOnDiskCache.
LLVM_ABI void setSizeLimit(std::optional< uint64_t > SizeLimit)
Set the size for limiting growth.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key