| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/catalog_rw.h |
| Date: | 2025-10-19 02:35:28 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 30 | 31 | 96.8% |
| 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 | 1589 | inline bool IsDirty() const { return dirty_; } | |
| 58 | 12947 | 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 | 97 | inline void TouchEntry(const DirectoryEntryBase &entry, | |
| 69 | const XattrList &xattrs, | ||
| 70 | const std::string &path) { | ||
| 71 |
2/4✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 97 times.
✗ Branch 6 not taken.
|
97 | TouchEntry(entry, xattrs, shash::Md5(shash::AsciiPtr(path))); |
| 72 | 97 | } | |
| 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 | 2978 | CatalogDatabase::OpenMode DatabaseOpenMode() const { | |
| 112 | 2978 | return CatalogDatabase::kOpenReadWrite; | |
| 113 | } | ||
| 114 | |||
| 115 | void UpdateEntry(const DirectoryEntry &entry, const shash::Md5 &path_hash); | ||
| 116 | 5962 | inline void UpdateEntry(const DirectoryEntry &entry, | |
| 117 | const std::string &path) { | ||
| 118 |
2/4✓ Branch 2 taken 5962 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5962 times.
✗ Branch 6 not taken.
|
5962 | UpdateEntry(entry, shash::Md5(shash::AsciiPtr(path))); |
| 119 | 5962 | } | |
| 120 | |||
| 121 | 3598 | inline void AddEntry(const DirectoryEntry &entry, | |
| 122 | const XattrList &xattrs, | ||
| 123 | const std::string &path) { | ||
| 124 |
1/2✓ Branch 2 taken 3598 times.
✗ Branch 3 not taken.
|
3598 | AddEntry(entry, xattrs, path, GetParentPath(path)); |
| 125 | 3598 | } | |
| 126 | |||
| 127 | void InitPreparedStatements(); | ||
| 128 | void FinalizePreparedStatements(); | ||
| 129 | |||
| 130 | 2029 | inline WritableCatalog *GetWritableParent() const { | |
| 131 | 2029 | Catalog *parent = this->parent(); | |
| 132 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2029 times.
|
2029 | assert(parent->IsWritable()); |
| 133 | 2029 | return static_cast<WritableCatalog *>(parent); | |
| 134 | } | ||
| 135 | |||
| 136 | ✗ | int dirty_children() const { return atomic_read32(&dirty_children_); } | |
| 137 | 1589 | void set_dirty_children(const int count) { | |
| 138 | 1589 | atomic_write32(&dirty_children_, count); | |
| 139 | 1589 | } | |
| 140 | 902 | int DecrementDirtyChildren() { | |
| 141 | 902 | return atomic_xadd32(&dirty_children_, -1) - 1; | |
| 142 | } | ||
| 143 | |||
| 144 | private: | ||
| 145 | SqlDirentInsert *sql_insert_; | ||
| 146 | SqlDirentUnlink *sql_unlink_; | ||
| 147 | SqlDirentTouch *sql_touch_; | ||
| 148 | SqlDirentUpdate *sql_update_; | ||
| 149 | SqlChunkInsert *sql_chunk_insert_; | ||
| 150 | SqlChunksRemove *sql_chunks_remove_; | ||
| 151 | SqlChunksCount *sql_chunks_count_; | ||
| 152 | SqlMaxHardlinkGroup *sql_max_link_id_; | ||
| 153 | SqlIncLinkcount *sql_inc_linkcount_; | ||
| 154 | |||
| 155 | bool dirty_; /**< Indicates if the catalog has been changed */ | ||
| 156 | |||
| 157 | DeltaCounters delta_counters_; | ||
| 158 | |||
| 159 | // parallel commit state | ||
| 160 | mutable atomic_int32 dirty_children_; | ||
| 161 | |||
| 162 | 27902 | inline void SetDirty() { | |
| 163 |
2/2✓ Branch 0 taken 2675 times.
✓ Branch 1 taken 25227 times.
|
27902 | if (!dirty_) |
| 164 | 2675 | Transaction(); | |
| 165 | 27902 | dirty_ = true; | |
| 166 | 27902 | } | |
| 167 | |||
| 168 | // Helpers for nested catalog creation and removal | ||
| 169 | void MakeTransitionPoint(const std::string &mountpoint); | ||
| 170 | void MakeNestedRoot(); | ||
| 171 | 965 | inline void MoveToNested(const std::string &dir_structure_root, | |
| 172 | WritableCatalog *new_nested_catalog, | ||
| 173 | std::vector<std::string> *grand_child_mountpoints) { | ||
| 174 |
1/2✓ Branch 2 taken 965 times.
✗ Branch 3 not taken.
|
965 | MoveToNestedRecursively( |
| 175 | dir_structure_root, new_nested_catalog, grand_child_mountpoints); | ||
| 176 | 965 | } | |
| 177 | void MoveToNestedRecursively( | ||
| 178 | const std::string dir_structure_root, | ||
| 179 | WritableCatalog *new_nested_catalog, | ||
| 180 | std::vector<std::string> *grand_child_mountpoints); | ||
| 181 | void MoveCatalogsToNested(const std::vector<std::string> &nested_catalogs, | ||
| 182 | WritableCatalog *new_nested_catalog); | ||
| 183 | void MoveFileChunksToNested(const std::string &full_path, | ||
| 184 | const shash::Algorithms algorithm, | ||
| 185 | WritableCatalog *new_nested_catalog); | ||
| 186 | |||
| 187 | void CopyToParent(); | ||
| 188 | void CopyCatalogsToParent(); | ||
| 189 | |||
| 190 | void UpdateCounters(); | ||
| 191 | void VacuumDatabaseIfNecessary(); | ||
| 192 | }; // class WritableCatalog | ||
| 193 | |||
| 194 | typedef std::vector<WritableCatalog *> WritableCatalogList; | ||
| 195 | |||
| 196 | } // namespace catalog | ||
| 197 | |||
| 198 | #endif // CVMFS_CATALOG_RW_H_ | ||
| 199 |