GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/file_backed_buffer.cc
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 102 111 91.9%
Branches: 52 78 66.7%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "file_backed_buffer.h"
6
7 #include <cassert>
8 #include <cstdio>
9 #include <cstring>
10
11 #include "util/exception.h"
12 #include "util/logging.h"
13 #include "util/posix.h"
14 #include "util/smalloc.h"
15
16 8675 FileBackedBuffer *FileBackedBuffer::Create(uint64_t in_memory_threshold,
17 const std::string &tmp_dir) {
18
1/2
✓ Branch 2 taken 8675 times.
✗ Branch 3 not taken.
8675 return new FileBackedBuffer(in_memory_threshold, tmp_dir);
19 }
20
21 8675 FileBackedBuffer::FileBackedBuffer(uint64_t in_memory_threshold,
22 8675 const std::string &tmp_dir)
23 8675 : in_memory_threshold_(in_memory_threshold)
24 8675 , tmp_dir_(tmp_dir)
25 8675 , state_(kWriteState)
26 8675 , mode_(kMemoryMode)
27 8675 , size_(0)
28 8675 , buf_(NULL)
29 8675 , pos_(0)
30 8675 , fp_(NULL)
31
1/2
✓ Branch 2 taken 8675 times.
✗ Branch 3 not taken.
8675 , file_path_("")
32 17350 , mmapped_(NULL) { }
33
34 17350 FileBackedBuffer::~FileBackedBuffer() {
35 8675 free(buf_);
36
2/2
✓ Branch 0 taken 5123 times.
✓ Branch 1 taken 3552 times.
8675 if (mode_ != kFileMode)
37 5123 return;
38
39
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 if (state_ == kWriteState) {
40 const int retval = fclose(fp_);
41 if (retval != 0)
42 PANIC(kLogStderr, "could not close temporary file %s: error %d",
43 file_path_.c_str(), retval);
44 } else {
45 3552 mmapped_->Unmap();
46
1/2
✓ Branch 0 taken 3552 times.
✗ Branch 1 not taken.
3552 delete mmapped_;
47 }
48 3552 const int retval = unlink(file_path_.c_str());
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 if (retval != 0)
50 PANIC(kLogStderr, "could not delete temporary file %s: error %d",
51 file_path_.c_str(), retval);
52
4/4
✓ Branch 1 taken 3552 times.
✓ Branch 2 taken 5123 times.
✓ Branch 4 taken 3552 times.
✓ Branch 5 taken 5123 times.
13798 }
53
54 2794913 void FileBackedBuffer::Append(const void *source, uint64_t len) {
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2794913 times.
2794913 assert(source != NULL);
56
57 // Cannot write after Commit()
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2794913 times.
2794913 assert(state_ == kWriteState);
59
60
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2794908 times.
2794913 if (len == 0)
61 5 return;
62
63 // check the size and eventually save to file
64
4/4
✓ Branch 0 taken 331178 times.
✓ Branch 1 taken 2463730 times.
✓ Branch 2 taken 3552 times.
✓ Branch 3 taken 327626 times.
2794908 if (mode_ == kMemoryMode && pos_ + len > in_memory_threshold_) {
65 // changes mode_ to kFileMode
66 3552 SaveToFile();
67 }
68
69
2/2
✓ Branch 0 taken 327626 times.
✓ Branch 1 taken 2467282 times.
2794908 if (mode_ == kMemoryMode) {
70
2/2
✓ Branch 0 taken 5895 times.
✓ Branch 1 taken 321731 times.
327626 if (buf_ == NULL) {
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5895 times.
5895 assert(size_ == 0);
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5895 times.
5895 assert(pos_ == 0);
73 5895 buf_ = reinterpret_cast<unsigned char *>(smalloc(len));
74 5895 size_ = len;
75
2/2
✓ Branch 0 taken 27166 times.
✓ Branch 1 taken 294565 times.
321731 } else if (size_ < pos_ + len) {
76 27166 const uint64_t newsize =
77 27166 (size_ * 2 < pos_ + len) ? (pos_ + len) : (size_ * 2);
78 27166 buf_ = reinterpret_cast<unsigned char *>(srealloc(buf_, newsize));
79 27166 size_ = newsize;
80 }
81
82 327626 memcpy(buf_ + pos_, source, len);
83 327626 pos_ += len;
84 } else {
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2467282 times.
2467282 assert(fp_ != NULL);
86 2467282 const uint64_t bytes_written = fwrite(source, 1, len, fp_);
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2467296 times.
2467296 if (bytes_written != len) {
88 PANIC(kLogStderr,
89 "could not append to temporary file %s: length %lu, "
90 "actually written %lu, error %d",
91 file_path_.c_str(), len, bytes_written, ferror(fp_));
92 }
93 2467296 pos_ += len;
94 2467296 size_ += len;
95 }
96 }
97
98 8542 void FileBackedBuffer::Commit() {
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8542 times.
8542 assert(state_ == kWriteState);
100
101
2/2
✓ Branch 0 taken 3552 times.
✓ Branch 1 taken 4990 times.
8542 if (mode_ == kFileMode) {
102 3552 const int retval = fclose(fp_);
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 if (retval != 0)
104 PANIC(kLogStderr, "could not close file after writing finished: %s",
105 file_path_.c_str());
106 3552 fp_ = NULL;
107
108
1/2
✓ Branch 2 taken 3552 times.
✗ Branch 3 not taken.
3552 mmapped_ = new MemoryMappedFile(file_path_);
109
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3552 times.
3552 if (!mmapped_->Map())
110 PANIC(kLogStderr, "could not memory-map file %s", file_path_.c_str());
111 } else {
112 // Trim memory chunk size to actual data size
113 4990 buf_ = reinterpret_cast<unsigned char *>(srealloc(buf_, pos_));
114 4990 size_ = pos_;
115 }
116
117 8542 pos_ = 0;
118 8542 state_ = kReadState;
119 8542 }
120
121 227938 int64_t FileBackedBuffer::Data(void **ptr, int64_t len, uint64_t pos) {
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227938 times.
227938 assert(state_ == kReadState);
123
124 227938 const int64_t actual_len =
125 227938 (pos + len <= size_)
126
2/2
✓ Branch 0 taken 3863 times.
✓ Branch 1 taken 224075 times.
227938 ? len
127 3863 : static_cast<int64_t>(size_) - static_cast<int64_t>(pos);
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227938 times.
227938 assert(actual_len >= 0);
129
130
2/2
✓ Branch 0 taken 8328 times.
✓ Branch 1 taken 219610 times.
227938 if (mode_ == kMemoryMode) {
131 8328 *ptr = buf_ + pos;
132 } else {
133 219610 *ptr = mmapped_->buffer() + pos;
134 }
135 227938 return actual_len;
136 }
137
138 219401 int64_t FileBackedBuffer::Read(void *ptr, int64_t len) {
139 219401 const int64_t bytes_read = ReadP(ptr, len, pos_);
140 219401 pos_ += bytes_read;
141 219401 return bytes_read;
142 }
143
144 219401 int64_t FileBackedBuffer::ReadP(void *ptr, int64_t len, uint64_t pos) {
145 void *source;
146
1/2
✓ Branch 1 taken 219401 times.
✗ Branch 2 not taken.
219401 const int64_t bytes_read = Data(&source, len, pos);
147 219401 memcpy(ptr, source, bytes_read);
148 219401 return bytes_read;
149 }
150
151 8512 void FileBackedBuffer::Rewind() {
152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8512 times.
8512 assert(state_ == kReadState);
153 8512 pos_ = 0;
154 8512 }
155
156 44088 uint64_t FileBackedBuffer::GetSize() const {
157
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 43989 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 5 times.
44088 if (state_ == kWriteState && mode_ == kMemoryMode)
158 94 return pos_;
159 43994 return size_;
160 }
161
162
163 3552 void FileBackedBuffer::SaveToFile() {
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 assert(state_ == kWriteState);
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 assert(mode_ == kMemoryMode);
166
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 assert(fp_ == NULL);
168 3552 fp_ = CreateTempFile(tmp_dir_, 0644, "w", &file_path_);
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 if (fp_ == NULL)
170 PANIC(kLogStderr, "could not create temporary file");
171
172 3552 const uint64_t bytes_written = fwrite(buf_, 1, pos_, fp_);
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3552 times.
3552 if (bytes_written != pos_) {
174 PANIC(kLogStderr,
175 "could not write to temporary file %s: length %lu, "
176 "actually written %lu, error %d",
177 file_path_.c_str(), pos_, bytes_written, ferror(fp_));
178 }
179
180 3552 free(buf_);
181 3552 buf_ = NULL;
182 3552 size_ = pos_;
183 3552 mode_ = kFileMode;
184 3552 }
185