LLVM 22.0.0git
OnDiskDataAllocator.cpp
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/// \file Implements OnDiskDataAllocator.
10///
11//===----------------------------------------------------------------------===//
12
14#include "DatabaseFile.h"
15#include "llvm/Config/llvm-config.h"
16
17using namespace llvm;
18using namespace llvm::cas;
19using namespace llvm::cas::ondisk;
20
21#if LLVM_ENABLE_ONDISK_CAS
22
23//===----------------------------------------------------------------------===//
24// DataAllocator data structures.
25//===----------------------------------------------------------------------===//
26
27namespace {
28/// DataAllocator table layout:
29/// - [8-bytes: Generic table header]
30/// - 8-bytes: AllocatorOffset (reserved for implementing free lists)
31/// - 8-bytes: Size for user data header
32/// - <user data buffer>
33///
34/// Record layout:
35/// - <data>
36class DataAllocatorHandle {
37public:
38 static constexpr TableHandle::TableKind Kind =
39 TableHandle::TableKind::DataAllocator;
40
41 struct Header {
42 TableHandle::Header GenericHeader;
43 std::atomic<int64_t> AllocatorOffset;
44 const uint64_t UserHeaderSize;
45 };
46
47 operator TableHandle() const {
48 if (!H)
49 return TableHandle();
50 return TableHandle(*Region, H->GenericHeader);
51 }
52
53 Expected<MutableArrayRef<char>> allocate(MappedFileRegionArena &Alloc,
54 size_t DataSize) {
55 assert(&Alloc.getRegion() == Region);
56 auto Ptr = Alloc.allocate(DataSize);
57 if (LLVM_UNLIKELY(!Ptr))
58 return Ptr.takeError();
60 }
61
62 explicit operator bool() const { return H; }
63 const Header &getHeader() const { return *H; }
64 MappedFileRegion &getRegion() const { return *Region; }
65
66 MutableArrayRef<uint8_t> getUserHeader() {
67 return MutableArrayRef(reinterpret_cast<uint8_t *>(H + 1),
68 H->UserHeaderSize);
69 }
70
71 static Expected<DataAllocatorHandle>
72 create(MappedFileRegionArena &Alloc, StringRef Name, uint32_t UserHeaderSize);
73
74 DataAllocatorHandle() = default;
75 DataAllocatorHandle(MappedFileRegion &Region, Header &H)
76 : Region(&Region), H(&H) {}
77 DataAllocatorHandle(MappedFileRegion &Region, intptr_t HeaderOffset)
78 : DataAllocatorHandle(
79 Region, *reinterpret_cast<Header *>(Region.data() + HeaderOffset)) {
80 }
81
82private:
83 MappedFileRegion *Region = nullptr;
84 Header *H = nullptr;
85};
86
87} // end anonymous namespace
88
90 DatabaseFile File;
91 DataAllocatorHandle Store;
92};
93
95DataAllocatorHandle::create(MappedFileRegionArena &Alloc, StringRef Name,
96 uint32_t UserHeaderSize) {
97 // Allocate.
98 auto Offset =
99 Alloc.allocateOffset(sizeof(Header) + UserHeaderSize + Name.size() + 1);
100 if (LLVM_UNLIKELY(!Offset))
101 return Offset.takeError();
102
103 // Construct the header and the name.
104 assert(Name.size() <= UINT16_MAX && "Expected smaller table name");
105 auto *H = new (Alloc.getRegion().data() + *Offset)
107 static_cast<uint16_t>(Name.size()),
108 static_cast<int32_t>(sizeof(Header) + UserHeaderSize)},
109 /*AllocatorOffset=*/{0},
110 /*UserHeaderSize=*/UserHeaderSize};
111 // Memset UserHeader.
112 char *UserHeader = reinterpret_cast<char *>(H + 1);
113 memset(UserHeader, 0, UserHeaderSize);
114 // Write database file name (null-terminated).
115 char *NameStorage = UserHeader + UserHeaderSize;
116 llvm::copy(Name, NameStorage);
117 NameStorage[Name.size()] = 0;
118 return DataAllocatorHandle(Alloc.getRegion(), *H);
119}
120
122 const Twine &PathTwine, const Twine &TableNameTwine, uint64_t MaxFileSize,
123 std::optional<uint64_t> NewFileInitialSize, uint32_t UserHeaderSize,
124 function_ref<void(void *)> UserHeaderInit) {
125 assert(!UserHeaderSize || UserHeaderInit);
126 SmallString<128> PathStorage;
127 StringRef Path = PathTwine.toStringRef(PathStorage);
128 SmallString<128> TableNameStorage;
129 StringRef TableName = TableNameTwine.toStringRef(TableNameStorage);
130
131 // Constructor for if the file doesn't exist.
132 auto NewDBConstructor = [&](DatabaseFile &DB) -> Error {
133 auto Store =
134 DataAllocatorHandle::create(DB.getAlloc(), TableName, UserHeaderSize);
135 if (LLVM_UNLIKELY(!Store))
136 return Store.takeError();
137
138 if (auto E = DB.addTable(*Store))
139 return E;
140
141 if (UserHeaderSize)
142 UserHeaderInit(Store->getUserHeader().data());
143 return Error::success();
144 };
145
146 // Get or create the file.
147 Expected<DatabaseFile> File =
148 DatabaseFile::create(Path, MaxFileSize, NewDBConstructor);
149 if (!File)
150 return File.takeError();
151
152 // Find the table and validate it.
153 std::optional<TableHandle> Table = File->findTable(TableName);
154 if (!Table)
155 return createTableConfigError(std::errc::argument_out_of_domain, Path,
156 TableName, "table not found");
157 if (Error E = checkTable("table kind", (size_t)DataAllocatorHandle::Kind,
158 (size_t)Table->getHeader().Kind, Path, TableName))
159 return std::move(E);
160 auto Store = Table->cast<DataAllocatorHandle>();
161 assert(Store && "Already checked the kind");
162
163 // Success.
164 OnDiskDataAllocator::ImplType Impl{DatabaseFile(std::move(*File)), Store};
165 return OnDiskDataAllocator(std::make_unique<ImplType>(std::move(Impl)));
166}
167
168Expected<OnDiskDataAllocator::OnDiskPtr>
170 auto Data = Impl->Store.allocate(Impl->File.getAlloc(), Size);
171 if (LLVM_UNLIKELY(!Data))
172 return Data.takeError();
173
174 return OnDiskPtr(FileOffset(Data->data() - Impl->Store.getRegion().data()),
175 *Data);
176}
177
178Expected<ArrayRef<char>> OnDiskDataAllocator::get(FileOffset Offset,
179 size_t Size) const {
180 assert(Offset);
181 assert(Impl);
182 if (Offset.get() + Size >= Impl->File.getAlloc().size())
183 return createStringError(make_error_code(std::errc::protocol_error),
184 "requested size too large in allocator");
185 return ArrayRef<char>{Impl->File.getRegion().data() + Offset.get(), Size};
186}
187
188MutableArrayRef<uint8_t> OnDiskDataAllocator::getUserHeader() {
189 return Impl->Store.getUserHeader();
190}
191
192size_t OnDiskDataAllocator::size() const { return Impl->File.size(); }
193size_t OnDiskDataAllocator::capacity() const {
194 return Impl->File.getRegion().size();
195}
196
197OnDiskDataAllocator::OnDiskDataAllocator(std::unique_ptr<ImplType> Impl)
198 : Impl(std::move(Impl)) {}
199
200#else // !LLVM_ENABLE_ONDISK_CAS
201
203
205 const Twine &Path, const Twine &TableName, uint64_t MaxFileSize,
206 std::optional<uint64_t> NewFileInitialSize, uint32_t UserHeaderSize,
207 function_ref<void(void *)> UserHeaderInit) {
208 return createStringError(make_error_code(std::errc::not_supported),
209 "OnDiskDataAllocator is not supported");
210}
211
214 return createStringError(make_error_code(std::errc::not_supported),
215 "OnDiskDataAllocator is not supported");
216}
217
219 size_t Size) const {
220 return createStringError(make_error_code(std::errc::not_supported),
221 "OnDiskDataAllocator is not supported");
222}
223
225
226size_t OnDiskDataAllocator::size() const { return 0; }
227size_t OnDiskDataAllocator::capacity() const { return 0; }
228
229#endif // LLVM_ENABLE_ONDISK_CAS
230
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Prepare AGPR Alloc
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:336
This file declares the common interface for a DatabaseFile that is used to implement OnDiskCAS.
#define H(x, y, z)
Definition MD5.cpp:57
This file declares interface for OnDiskDataAllocator, a file backed data pool can be used to allocate...
static Split data
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition ArrayRef.h:303
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
Definition Twine.h:461
FileOffset is a wrapper around uint64_t to represent the offset of data from the beginning of the fil...
Definition FileOffset.h:24
Allocator for an owned mapped file region that supports thread-safe and process-safe bump pointer all...
A pointer to data stored on disk.
Expected< OnDiskPtr > allocate(size_t Size)
Allocate at least Size with 8-byte alignment.
Expected< ArrayRef< char > > get(FileOffset Offset, size_t Size) const
Get the data of Size stored at the given Offset.
static Expected< OnDiskDataAllocator > create(const Twine &Path, const Twine &TableName, uint64_t MaxFileSize, std::optional< uint64_t > NewFileInitialSize, uint32_t UserHeaderSize=0, function_ref< void(void *)> UserHeaderInit=nullptr)
OnDiskDataAllocator & operator=(OnDiskDataAllocator &&RHS)
OnDiskDataAllocator(OnDiskDataAllocator &&RHS)
MutableArrayRef< uint8_t > getUserHeader()
static Expected< DatabaseFile > create(const Twine &Path, uint64_t Capacity, function_ref< Error(DatabaseFile &)> NewDBConstructor)
Create the DatabaseFile at Path with Capacity.
An efficient, type-erasing, non-owning reference to a callable.
Error createTableConfigError(std::errc ErrC, StringRef Path, StringRef TableName, const Twine &Msg)
MappedFileRegionArena::RegionT MappedFileRegion
Error checkTable(StringRef Label, size_t Expected, size_t Observed, StringRef Path, StringRef TrieName)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
std::error_code make_error_code(BitcodeError E)
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
Definition InstrProf.h:267
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1837
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1869