| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/file_chunk.h |
| Date: | 2025-10-26 02:35:25 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 22 | 28 | 78.6% |
| Branches: | 2 | 8 | 25.0% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * This file is part of the CernVM File System. | ||
| 3 | * | ||
| 4 | * This class implements a data wrapper for single dentries in CVMFS | ||
| 5 | * Additionally to the normal file meta data it manages some | ||
| 6 | * bookkeeping data like the associated catalog. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef CVMFS_FILE_CHUNK_H_ | ||
| 10 | #define CVMFS_FILE_CHUNK_H_ | ||
| 11 | |||
| 12 | #include <pthread.h> | ||
| 13 | #include <stdint.h> | ||
| 14 | #include <sys/types.h> | ||
| 15 | |||
| 16 | #include <string> | ||
| 17 | #include <vector> | ||
| 18 | |||
| 19 | #include "bigvector.h" | ||
| 20 | #include "compression/compression.h" | ||
| 21 | #include "crypto/hash.h" | ||
| 22 | #include "shortstring.h" | ||
| 23 | #include "smallhash.h" | ||
| 24 | #include "util/atomic.h" | ||
| 25 | #include "util/single_copy.h" | ||
| 26 | |||
| 27 | /** | ||
| 28 | * Describes a FileChunk as generated from the FileProcessor in collaboration | ||
| 29 | * with the ChunkGenerator. | ||
| 30 | */ | ||
| 31 | class FileChunk { | ||
| 32 | public: | ||
| 33 | 525 | FileChunk() : content_hash_(shash::Any(shash::kAny)), offset_(0), size_(0) { } | |
| 34 | 4510534 | FileChunk(const shash::Any &hash, const off_t offset, const size_t size) | |
| 35 | 4510534 | : content_hash_(hash), offset_(offset), size_(size) { } | |
| 36 | |||
| 37 | 9012792 | inline const shash::Any &content_hash() const { return content_hash_; } | |
| 38 | 4504700 | inline off_t offset() const { return offset_; } | |
| 39 | 4503125 | inline size_t size() const { return size_; } | |
| 40 | |||
| 41 | protected: | ||
| 42 | shash::Any content_hash_; //!< content hash of the compressed file chunk | ||
| 43 | off_t offset_; //!< byte offset in the uncompressed input file | ||
| 44 | size_t size_; //!< uncompressed size of the data chunk | ||
| 45 | }; | ||
| 46 | |||
| 47 | typedef BigVector<FileChunk> FileChunkList; | ||
| 48 | |||
| 49 | struct FileChunkReflist { | ||
| 50 | 7839 | FileChunkReflist() | |
| 51 | 7839 | : list(NULL) | |
| 52 | 7839 | , compression_alg(zlib::kZlibDefault) | |
| 53 | 7839 | , external_data(false) { } | |
| 54 | 72 | FileChunkReflist(FileChunkList *l, | |
| 55 | const PathString &p, | ||
| 56 | zlib::Algorithms alg, | ||
| 57 | bool external) | ||
| 58 | 72 | : list(l), path(p), compression_alg(alg), external_data(external) { } | |
| 59 | |||
| 60 | unsigned FindChunkIdx(const uint64_t offset); | ||
| 61 | shash::Any HashChunkList(); | ||
| 62 | |||
| 63 | FileChunkList *list; | ||
| 64 | PathString path; | ||
| 65 | zlib::Algorithms compression_alg; | ||
| 66 | bool external_data; | ||
| 67 | }; | ||
| 68 | |||
| 69 | |||
| 70 | /** | ||
| 71 | * Stores the chunk index of a file descriptor. Needed for the Fuse module | ||
| 72 | * and for libcvmfs. | ||
| 73 | */ | ||
| 74 | struct ChunkFd { | ||
| 75 | 7407 | ChunkFd() : fd(-1), chunk_idx(0) { } | |
| 76 | int fd; // -1 or pointing to chunk_idx | ||
| 77 | unsigned chunk_idx; | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | /** | ||
| 82 | * All chunk related data structures in the Fuse module. | ||
| 83 | */ | ||
| 84 | struct ChunkTables { | ||
| 85 | ChunkTables(); | ||
| 86 | ~ChunkTables(); | ||
| 87 | ChunkTables(const ChunkTables &other); | ||
| 88 | ChunkTables &operator=(const ChunkTables &other); | ||
| 89 | void CopyFrom(const ChunkTables &other); | ||
| 90 | void InitLocks(); | ||
| 91 | void InitHashmaps(); | ||
| 92 | |||
| 93 | pthread_mutex_t *Handle2Lock(const uint64_t handle) const; | ||
| 94 | |||
| 95 | ✗ | inline void Lock() { | |
| 96 | ✗ | const int retval = pthread_mutex_lock(lock); | |
| 97 | ✗ | assert(retval == 0); | |
| 98 | } | ||
| 99 | |||
| 100 | ✗ | inline void Unlock() { | |
| 101 | ✗ | const int retval = pthread_mutex_unlock(lock); | |
| 102 | ✗ | assert(retval == 0); | |
| 103 | } | ||
| 104 | |||
| 105 | // Version 2 --> 4: add handle2uniqino | ||
| 106 | static const unsigned kVersion = 4; | ||
| 107 | |||
| 108 | int version; | ||
| 109 | static const unsigned kNumHandleLocks = 128; | ||
| 110 | // Versions < 4 of ChunkTables didn't have this map. Therefore, after a | ||
| 111 | // hot patch a handle can be missing from this map. In this case, the fuse | ||
| 112 | // module falls back to the inode passed by the kernel. | ||
| 113 | SmallHashDynamic<uint64_t, uint64_t> handle2uniqino; | ||
| 114 | SmallHashDynamic<uint64_t, ChunkFd> handle2fd; | ||
| 115 | // The file descriptors attached to handles need to be locked. | ||
| 116 | // Using a hash map to survive with a small, fixed number of locks | ||
| 117 | BigVector<pthread_mutex_t *> handle_locks; | ||
| 118 | SmallHashDynamic<uint64_t, FileChunkReflist> inode2chunks; | ||
| 119 | SmallHashDynamic<uint64_t, uint32_t> inode2references; | ||
| 120 | uint64_t next_handle; | ||
| 121 | pthread_mutex_t *lock; | ||
| 122 | }; | ||
| 123 | |||
| 124 | |||
| 125 | /** | ||
| 126 | * Connects virtual file descriptors to FileChunkLists. Used by libcvmfs. | ||
| 127 | * Tries to keep the file descriptors small because they need to fit within | ||
| 128 | * 29bit. This class takes the ownership of the FileChunkList objects pointed | ||
| 129 | * to by the elements of fd_table_. | ||
| 130 | */ | ||
| 131 | class SimpleChunkTables : SingleCopy { | ||
| 132 | public: | ||
| 133 | /** | ||
| 134 | * While a chunked file is open, a single file descriptor is moved around the | ||
| 135 | * individual chunks. | ||
| 136 | */ | ||
| 137 | struct OpenChunks { | ||
| 138 | 432 | OpenChunks() : chunk_fd(NULL) { } | |
| 139 | ChunkFd *chunk_fd; | ||
| 140 | FileChunkReflist chunk_reflist; | ||
| 141 | }; | ||
| 142 | |||
| 143 | SimpleChunkTables(); | ||
| 144 | ~SimpleChunkTables(); | ||
| 145 | int Add(FileChunkReflist chunks); | ||
| 146 | OpenChunks Get(int fd); | ||
| 147 | void Release(int fd); | ||
| 148 | |||
| 149 | private: | ||
| 150 | 648 | inline void Lock() { | |
| 151 | 648 | const int retval = pthread_mutex_lock(lock_); | |
| 152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 648 times.
|
648 | assert(retval == 0); |
| 153 | 648 | } | |
| 154 | |||
| 155 | 648 | inline void Unlock() { | |
| 156 | 648 | const int retval = pthread_mutex_unlock(lock_); | |
| 157 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 648 times.
|
648 | assert(retval == 0); |
| 158 | 648 | } | |
| 159 | |||
| 160 | std::vector<OpenChunks> fd_table_; | ||
| 161 | pthread_mutex_t *lock_; | ||
| 162 | }; | ||
| 163 | |||
| 164 | #endif // CVMFS_FILE_CHUNK_H_ | ||
| 165 |