Directory: | cvmfs/ |
---|---|
File: | cvmfs/file_chunk.h |
Date: | 2025-02-09 02:34:19 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 27 | 33 | 81.8% |
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 | 11 | FileChunk() : content_hash_(shash::Any(shash::kAny)), offset_(0), size_(0) { } | |
34 | 250534 | FileChunk(const shash::Any &hash, | |
35 | const off_t offset, | ||
36 | 250534 | const size_t size) : | |
37 | 250534 | content_hash_(hash), | |
38 | 250534 | offset_(offset), | |
39 | 250534 | size_(size) { } | |
40 | |||
41 | 500616 | inline const shash::Any& content_hash() const { return content_hash_; } | |
42 | 250143 | inline off_t offset() const { return offset_; } | |
43 | 250102 | inline size_t size() const { return size_; } | |
44 | |||
45 | protected: | ||
46 | shash::Any content_hash_; //!< content hash of the compressed file chunk | ||
47 | off_t offset_; //!< byte offset in the uncompressed input file | ||
48 | size_t size_; //!< uncompressed size of the data chunk | ||
49 | }; | ||
50 | |||
51 | typedef BigVector<FileChunk> FileChunkList; | ||
52 | |||
53 | struct FileChunkReflist { | ||
54 | 356 | FileChunkReflist() : list(NULL) | |
55 | 356 | , compression_alg(zlib::kZlibDefault) | |
56 | 356 | , external_data(false) { } | |
57 | 2 | FileChunkReflist(FileChunkList *l, | |
58 | const PathString &p, | ||
59 | zlib::Algorithms alg, | ||
60 | bool external) | ||
61 | 2 | : list(l) | |
62 | 2 | , path(p) | |
63 | 2 | , compression_alg(alg) | |
64 | 2 | , external_data(external) { } | |
65 | |||
66 | unsigned FindChunkIdx(const uint64_t offset); | ||
67 | shash::Any HashChunkList(); | ||
68 | |||
69 | FileChunkList *list; | ||
70 | PathString path; | ||
71 | zlib::Algorithms compression_alg; | ||
72 | bool external_data; | ||
73 | }; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Stores the chunk index of a file descriptor. Needed for the Fuse module | ||
78 | * and for libcvmfs. | ||
79 | */ | ||
80 | struct ChunkFd { | ||
81 | 344 | ChunkFd() : fd(-1), chunk_idx(0) { } | |
82 | int fd; // -1 or pointing to chunk_idx | ||
83 | unsigned chunk_idx; | ||
84 | }; | ||
85 | |||
86 | |||
87 | /** | ||
88 | * All chunk related data structures in the Fuse module. | ||
89 | */ | ||
90 | struct ChunkTables { | ||
91 | ChunkTables(); | ||
92 | ~ChunkTables(); | ||
93 | ChunkTables(const ChunkTables &other); | ||
94 | ChunkTables &operator= (const ChunkTables &other); | ||
95 | void CopyFrom(const ChunkTables &other); | ||
96 | void InitLocks(); | ||
97 | void InitHashmaps(); | ||
98 | |||
99 | pthread_mutex_t *Handle2Lock(const uint64_t handle) const; | ||
100 | |||
101 | ✗ | inline void Lock() { | |
102 | ✗ | int retval = pthread_mutex_lock(lock); | |
103 | ✗ | assert(retval == 0); | |
104 | } | ||
105 | |||
106 | ✗ | inline void Unlock() { | |
107 | ✗ | int retval = pthread_mutex_unlock(lock); | |
108 | ✗ | assert(retval == 0); | |
109 | } | ||
110 | |||
111 | // Version 2 --> 4: add handle2uniqino | ||
112 | static const unsigned kVersion = 4; | ||
113 | |||
114 | int version; | ||
115 | static const unsigned kNumHandleLocks = 128; | ||
116 | // Versions < 4 of ChunkTables didn't have this map. Therefore, after a | ||
117 | // hot patch a handle can be missing from this map. In this case, the fuse | ||
118 | // module falls back to the inode passed by the kernel. | ||
119 | SmallHashDynamic<uint64_t, uint64_t> handle2uniqino; | ||
120 | SmallHashDynamic<uint64_t, ChunkFd> handle2fd; | ||
121 | // The file descriptors attached to handles need to be locked. | ||
122 | // Using a hash map to survive with a small, fixed number of locks | ||
123 | BigVector<pthread_mutex_t *> handle_locks; | ||
124 | SmallHashDynamic<uint64_t, FileChunkReflist> inode2chunks; | ||
125 | SmallHashDynamic<uint64_t, uint32_t> inode2references; | ||
126 | uint64_t next_handle; | ||
127 | pthread_mutex_t *lock; | ||
128 | }; | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Connects virtual file descriptors to FileChunkLists. Used by libcvmfs. | ||
133 | * Tries to keep the file descriptors small because they need to fit within | ||
134 | * 29bit. This class takes the ownership of the FileChunkList objects pointed | ||
135 | * to by the elements of fd_table_. | ||
136 | */ | ||
137 | class SimpleChunkTables : SingleCopy { | ||
138 | public: | ||
139 | /** | ||
140 | * While a chunked file is open, a single file descriptor is moved around the | ||
141 | * individual chunks. | ||
142 | */ | ||
143 | struct OpenChunks { | ||
144 | 12 | OpenChunks() : chunk_fd(NULL) { } | |
145 | ChunkFd *chunk_fd; | ||
146 | FileChunkReflist chunk_reflist; | ||
147 | }; | ||
148 | |||
149 | SimpleChunkTables(); | ||
150 | ~SimpleChunkTables(); | ||
151 | int Add(FileChunkReflist chunks); | ||
152 | OpenChunks Get(int fd); | ||
153 | void Release(int fd); | ||
154 | |||
155 | private: | ||
156 | 18 | inline void Lock() { | |
157 | 18 | int retval = pthread_mutex_lock(lock_); | |
158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | assert(retval == 0); |
159 | 18 | } | |
160 | |||
161 | 18 | inline void Unlock() { | |
162 | 18 | int retval = pthread_mutex_unlock(lock_); | |
163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | assert(retval == 0); |
164 | 18 | } | |
165 | |||
166 | std::vector<OpenChunks> fd_table_; | ||
167 | pthread_mutex_t *lock_; | ||
168 | }; | ||
169 | |||
170 | #endif // CVMFS_FILE_CHUNK_H_ | ||
171 |