brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · 609e5f1 Raw
154 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This file declares the common interface for a DatabaseFile that is used to11/// implement OnDiskCAS.12//13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_LIB_CAS_DATABASEFILE_H16#define LLVM_LIB_CAS_DATABASEFILE_H17 18#include "llvm/ADT/StringRef.h"19#include "llvm/CAS/MappedFileRegionArena.h"20#include "llvm/Support/Error.h"21 22namespace llvm::cas::ondisk {23 24using MappedFileRegion = MappedFileRegionArena::RegionT;25 26/// Generic handle for a table.27///28/// Generic table header layout:29/// - 2-bytes: TableKind30/// - 2-bytes: TableNameSize31/// - 4-bytes: TableNameRelOffset (relative to header)32class TableHandle {33public:34  enum class TableKind : uint16_t {35    TrieRawHashMap = 1,36    DataAllocator = 2,37  };38  struct Header {39    TableKind Kind;40    uint16_t NameSize;41    int32_t NameRelOffset; ///< Relative to Header.42  };43 44  explicit operator bool() const { return H; }45  const Header &getHeader() const { return *H; }46  MappedFileRegion &getRegion() const { return *Region; }47 48  template <class T> static void check() {49    static_assert(50        std::is_same<decltype(T::Header::GenericHeader), Header>::value,51        "T::GenericHeader should be of type TableHandle::Header");52    static_assert(offsetof(typename T::Header, GenericHeader) == 0,53                  "T::GenericHeader must be the head of T::Header");54  }55  template <class T> bool is() const { return T::Kind == H->Kind; }56  template <class T> T dyn_cast() const {57    check<T>();58    if (is<T>())59      return T(*Region, *reinterpret_cast<typename T::Header *>(H));60    return T();61  }62  template <class T> T cast() const {63    assert(is<T>());64    return dyn_cast<T>();65  }66 67  StringRef getName() const {68    auto *Begin = reinterpret_cast<const char *>(H) + H->NameRelOffset;69    return StringRef(Begin, H->NameSize);70  }71 72  TableHandle() = default;73  TableHandle(MappedFileRegion &Region, Header &H) : Region(&Region), H(&H) {}74  TableHandle(MappedFileRegion &Region, intptr_t HeaderOffset)75      : TableHandle(Region,76                    *reinterpret_cast<Header *>(Region.data() + HeaderOffset)) {77  }78 79private:80  MappedFileRegion *Region = nullptr;81  Header *H = nullptr;82};83 84/// Encapsulate a database file, which:85/// - Sets/checks magic.86/// - Sets/checks version.87/// - Points at an arbitrary root table.88/// - Sets up a MappedFileRegionArena for allocation.89///90/// Top-level layout:91/// - 4-bytes: Magic92/// - 4-bytes: Version93/// - 8-bytes: RootTableOffset (16-bits: Kind; 48-bits: Offset)94/// - 8-bytes: BumpPtr from MappedFileRegionArena95class DatabaseFile {96public:97  static constexpr uint32_t getMagic() { return 0xDA7ABA53UL; }98  static constexpr uint32_t getVersion() { return 1UL; }99  struct Header {100    uint32_t Magic;101    uint32_t Version;102    std::atomic<int64_t> RootTableOffset;103  };104 105  const Header &getHeader() { return *H; }106  MappedFileRegionArena &getAlloc() { return Alloc; }107  MappedFileRegion &getRegion() { return Alloc.getRegion(); }108 109  /// Add a table. This is currently not thread safe and should be called inside110  /// NewDBConstructor.111  Error addTable(TableHandle Table);112 113  /// Find a table. May return null.114  std::optional<TableHandle> findTable(StringRef Name);115 116  /// Create the DatabaseFile at Path with Capacity.117  static Expected<DatabaseFile>118  create(const Twine &Path, uint64_t Capacity,119         function_ref<Error(DatabaseFile &)> NewDBConstructor);120 121  size_t size() const { return Alloc.size(); }122 123private:124  static Expected<DatabaseFile>125  get(std::unique_ptr<MappedFileRegionArena> Alloc) {126    if (Error E = validate(Alloc->getRegion()))127      return std::move(E);128    return DatabaseFile(std::move(Alloc));129  }130 131  static Error validate(MappedFileRegion &Region);132 133  DatabaseFile(MappedFileRegionArena &Alloc)134      : H(reinterpret_cast<Header *>(Alloc.data())), Alloc(Alloc) {}135  DatabaseFile(std::unique_ptr<MappedFileRegionArena> Alloc)136      : DatabaseFile(*Alloc) {137    OwnedAlloc = std::move(Alloc);138  }139 140  Header *H = nullptr;141  MappedFileRegionArena &Alloc;142  std::unique_ptr<MappedFileRegionArena> OwnedAlloc;143};144 145Error createTableConfigError(std::errc ErrC, StringRef Path,146                             StringRef TableName, const Twine &Msg);147 148Error checkTable(StringRef Label, size_t Expected, size_t Observed,149                 StringRef Path, StringRef TrieName);150 151} // namespace llvm::cas::ondisk152 153#endif154