| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/catalog_rw.h |
| Date: | 2026-10-18 02:40:11 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 27 | 28 | 96.4% |
| Branches: | 9 | 16 | 56.2% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * This file is part of the CernVM File System | ||
| 3 | * | ||
| 4 | * The WritableCatalog class is derived from Catalog. It is used by the | ||
| 5 | * WritableCatalogManager on the server side. | ||
| 6 | * | ||
| 7 | * The main functionality is in: | ||
| 8 | * - AddEntry | ||
| 9 | * - UpdateEntry | ||
| 10 | * - RemoveEntry | ||
| 11 | * | ||
| 12 | * Catalogs not thread safe. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef CVMFS_CATALOG_RW_H_ | ||
| 16 | #define CVMFS_CATALOG_RW_H_ | ||
| 17 | |||
| 18 | #include <stdint.h> | ||
| 19 | |||
| 20 | #include <string> | ||
| 21 | #include <vector> | ||
| 22 | |||
| 23 | #include "catalog.h" | ||
| 24 | #include "util/posix.h" | ||
| 25 | |||
| 26 | class XattrList; | ||
| 27 | |||
| 28 | namespace swissknife { | ||
| 29 | class CommandMigrate; | ||
| 30 | } | ||
| 31 | |||
| 32 | namespace catalog { | ||
| 33 | |||
| 34 | class WritableCatalogManager; | ||
| 35 | |||
| 36 | class WritableCatalog : public Catalog { | ||
| 37 | friend class WritableCatalogManager; | ||
| 38 | friend class swissknife::CommandMigrate; // needed for catalog migrations | ||
| 39 | friend class VirtualCatalog; // needed for /.cvmfs creation | ||
| 40 | |||
| 41 | public: | ||
| 42 | WritableCatalog(const std::string &path, | ||
| 43 | const shash::Any &catalog_hash, | ||
| 44 | Catalog *parent, | ||
| 45 | const bool is_not_root = false); | ||
| 46 | virtual ~WritableCatalog(); | ||
| 47 | |||
| 48 | static WritableCatalog *AttachFreely(const std::string &root_path, | ||
| 49 | const std::string &file, | ||
| 50 | const shash::Any &catalog_hash, | ||
| 51 | Catalog *parent = NULL, | ||
| 52 | const bool is_not_root = false); | ||
| 53 | |||
| 54 | void Transaction(); | ||
| 55 | void Commit(); | ||
| 56 | |||
| 57 | 1732 | inline bool IsDirty() const { return dirty_; } | |
| 58 | 11429 | inline bool IsWritable() const { return true; } | |
| 59 | uint32_t GetMaxLinkId() const; | ||
| 60 | |||
| 61 | void AddEntry(const DirectoryEntry &entry, | ||
| 62 | const XattrList &xattr, | ||
| 63 | const std::string &entry_path, | ||
| 64 | const std::string &parent_path); | ||
| 65 | void TouchEntry(const DirectoryEntryBase &entry, | ||
| 66 | const XattrList &xattrs, | ||
| 67 | const shash::Md5 &path_hash); | ||
| 68 | 71 | inline void TouchEntry(const DirectoryEntryBase &entry, | |
| 69 | const XattrList &xattrs, | ||
| 70 | const std::string &path) { | ||
| 71 |
2/4✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 71 times.
✗ Branch 6 not taken.
|
71 | TouchEntry(entry, xattrs, shash::Md5(shash::AsciiPtr(path))); |
| 72 | 71 | } | |
| 73 | void RemoveEntry(const std::string &entry_path); | ||
| 74 | void IncLinkcount(const std::string &path_within_group, const int delta); | ||
| 75 | void AddFileChunk(const std::string &entry_path, const FileChunk &chunk); | ||
| 76 | void RemoveFileChunks(const std::string &entry_path); | ||
| 77 | |||
| 78 | // Creation and removal of catalogs | ||
| 79 | void Partition(WritableCatalog *new_nested_catalog); | ||
| 80 | void MergeIntoParent(); | ||
| 81 | void RemoveFromParent(); | ||
| 82 | |||
| 83 | // Nested catalog references | ||
| 84 | void InsertNestedCatalog(const std::string &mountpoint, | ||
| 85 | Catalog *attached_reference, | ||
| 86 | const shash::Any content_hash, | ||
| 87 | const uint64_t size); | ||
| 88 | void InsertBindMountpoint(const std::string &mountpoint, | ||
| 89 | const shash::Any content_hash, | ||
| 90 | const uint64_t size); | ||
| 91 | void UpdateNestedCatalog(const std::string &path, | ||
| 92 | const shash::Any &hash, | ||
| 93 | const uint64_t size, | ||
| 94 | const DeltaCounters &child_counters); | ||
| 95 | void RemoveNestedCatalog(const std::string &mountpoint, | ||
| 96 | Catalog **attached_reference); | ||
| 97 | void RemoveBindMountpoint(const std::string &mountpoint); | ||
| 98 | |||
| 99 | void UpdateLastModified(); | ||
| 100 | void IncrementRevision(); | ||
| 101 | void SetRevision(const uint64_t new_revision); | ||
| 102 | void SetBranch(const std::string &branch_name); | ||
| 103 | void SetPreviousRevision(const shash::Any &hash); | ||
| 104 | void SetTTL(const uint64_t new_ttl); | ||
| 105 | bool SetVOMSAuthz(const std::string &voms_authz); | ||
| 106 | |||
| 107 | protected: | ||
| 108 | static const double kMaximalFreePageRatio; // = 0.2 | ||
| 109 | static const double kMaximalRowIdWasteRatio; // = 0.25; | ||
| 110 | |||
| 111 | 2675 | CatalogDatabase::OpenMode DatabaseOpenMode() const { | |
| 112 | 2675 | return CatalogDatabase::kOpenReadWrite; | |
| 113 | } | ||
| 114 | |||
| 115 | void UpdateEntry(const DirectoryEntry &entry, const shash::Md5 &path_hash); | ||
| 116 | 5388 | inline void UpdateEntry(const DirectoryEntry &entry, | |
| 117 | const std::string &path) { | ||
| 118 |
2/4✓ Branch 2 taken 5388 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5388 times.
✗ Branch 6 not taken.
|
5388 | UpdateEntry(entry, shash::Md5(shash::AsciiPtr(path))); |
| 119 | 5388 | } | |
| 120 | |||
| 121 | 2675 | inline void AddEntry(const DirectoryEntry &entry, | |
| 122 | const XattrList &xattrs, | ||
| 123 | const std::string &path) { | ||
| 124 |
1/2✓ Branch 2 taken 2675 times.
✗ Branch 3 not taken.
|
2675 | AddEntry(entry, xattrs, path, GetParentPath(path)); |
| 125 | 2675 | } | |
| 126 | |||
| 127 | void InitPreparedStatements(); | ||
| 128 | void FinalizePreparedStatements(); | ||
| 129 | |||
| 130 | 1615 | inline WritableCatalog *GetWritableParent() const { | |
| 131 | 1615 | Catalog *parent = this->parent(); | |
| 132 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1615 times.
|
1615 | assert(parent->IsWritable()); |
| 133 | 1615 | return static_cast<WritableCatalog *>(parent); | |
| 134 | } | ||
| 135 | |||
| 136 | ✗ | int dirty_children() const { return dirty_children_.load(); } | |
| 137 | 1732 | void set_dirty_children(const int count) { dirty_children_.store(count); } | |
| 138 | 1390 | int DecrementDirtyChildren() { return dirty_children_.fetch_add(-1) - 1; } | |
| 139 | |||
| 140 | private: | ||
| 141 | SqlDirentInsert *sql_insert_; | ||
| 142 | SqlDirentUnlink *sql_unlink_; | ||
| 143 | SqlDirentTouch *sql_touch_; | ||
| 144 | SqlDirentUpdate *sql_update_; | ||
| 145 | SqlChunkInsert *sql_chunk_insert_; | ||
| 146 | SqlChunksRemove *sql_chunks_remove_; | ||
| 147 | SqlChunksCount *sql_chunks_count_; | ||
| 148 | SqlMaxHardlinkGroup *sql_max_link_id_; | ||
| 149 | SqlIncLinkcount *sql_inc_linkcount_; | ||
| 150 | |||
| 151 | bool dirty_; /**< Indicates if the catalog has been changed */ | ||
| 152 | |||
| 153 | DeltaCounters delta_counters_; | ||
| 154 | |||
| 155 | // parallel commit state | ||
| 156 | mutable std::atomic<int32_t> dirty_children_; | ||
| 157 | |||
| 158 | 22534 | inline void SetDirty() { | |
| 159 |
2/2✓ Branch 0 taken 2266 times.
✓ Branch 1 taken 20268 times.
|
22534 | if (!dirty_) |
| 160 | 2266 | Transaction(); | |
| 161 | 22534 | dirty_ = true; | |
| 162 | 22534 | } | |
| 163 | |||
| 164 | // Helpers for nested catalog creation and removal | ||
| 165 | void MakeTransitionPoint(const std::string &mountpoint); | ||
| 166 | void MakeNestedRoot(); | ||
| 167 | 722 | inline void MoveToNested(const std::string &dir_structure_root, | |
| 168 | WritableCatalog *new_nested_catalog, | ||
| 169 | std::vector<std::string> *grand_child_mountpoints) { | ||
| 170 |
1/2✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
|
722 | MoveToNestedRecursively( |
| 171 | dir_structure_root, new_nested_catalog, grand_child_mountpoints); | ||
| 172 | 722 | } | |
| 173 | void MoveToNestedRecursively( | ||
| 174 | const std::string dir_structure_root, | ||
| 175 | WritableCatalog *new_nested_catalog, | ||
| 176 | std::vector<std::string> *grand_child_mountpoints); | ||
| 177 | void MoveCatalogsToNested(const std::vector<std::string> &nested_catalogs, | ||
| 178 | WritableCatalog *new_nested_catalog); | ||
| 179 | void MoveFileChunksToNested(const std::string &full_path, | ||
| 180 | const shash::Algorithms algorithm, | ||
| 181 | WritableCatalog *new_nested_catalog); | ||
| 182 | |||
| 183 | void CopyToParent(); | ||
| 184 | void CopyCatalogsToParent(); | ||
| 185 | |||
| 186 | void UpdateCounters(); | ||
| 187 | void VacuumDatabaseIfNecessary(); | ||
| 188 | }; // class WritableCatalog | ||
| 189 | |||
| 190 | typedef std::vector<WritableCatalog *> WritableCatalogList; | ||
| 191 | |||
| 192 | } // namespace catalog | ||
| 193 | |||
| 194 | #endif // CVMFS_CATALOG_RW_H_ | ||
| 195 |