GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/file_backed_buffer.cc
Date: 2026-10-11 02:40:02
Exec Total Coverage
Lines: 101 110 91.8%
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 <cstdint>
9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <string>
13 #include <unistd.h>
14
15 #include "util/exception.h"
16 #include "util/logging.h"
17 #include "util/posix.h"
18 #include "util/smalloc.h"
19
20 27563 FileBackedBuffer *FileBackedBuffer::Create(uint64_t in_memory_threshold,
21 const std::string &tmp_dir) {
22
1/2
✓ Branch 2 taken 27563 times.
✗ Branch 3 not taken.
27563 return new FileBackedBuffer(in_memory_threshold, tmp_dir);
23 }
24
25 27563 FileBackedBuffer::FileBackedBuffer(uint64_t in_memory_threshold,
26 27563 const std::string &tmp_dir)
27 27563 : in_memory_threshold_(in_memory_threshold)
28 27563 , tmp_dir_(tmp_dir)
29 27563 , state_(kWriteState)
30 27563 , mode_(kMemoryMode)
31 27563 , size_(0)
32 27563 , buf_(NULL)
33 27563 , pos_(0)
34 27563 , fp_(NULL)
35
1/2
✓ Branch 2 taken 27563 times.
✗ Branch 3 not taken.
27563 , file_path_("")
36 27563 , mmapped_(NULL) { }
37
38 55126 FileBackedBuffer::~FileBackedBuffer() {
39 27563 free(buf_);
40
2/2
✓ Branch 0 taken 16343 times.
✓ Branch 1 taken 11220 times.
27563 if (mode_ != kFileMode)
41 16343 return;
42
43
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 if (state_ == kWriteState) {
44 ✗ const int retval = fclose(fp_);
45 ✗ if (retval != 0)
46 ✗ PANIC(kLogStderr, "could not close temporary file %s: error %d",
47 file_path_.c_str(), retval);
48 } else {
49 11220 mmapped_->Unmap();
50
1/2
✓ Branch 0 taken 11220 times.
✗ Branch 1 not taken.
11220 delete mmapped_;
51 }
52 11220 const int retval = unlink(file_path_.c_str());
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 if (retval != 0)
54 ✗ PANIC(kLogStderr, "could not delete temporary file %s: error %d",
55 file_path_.c_str(), retval);
56
4/4
✓ Branch 1 taken 11220 times.
✓ Branch 2 taken 16343 times.
✓ Branch 4 taken 11220 times.
✓ Branch 5 taken 16343 times.
43906 }
57
58 8784732 void FileBackedBuffer::Append(const void *source, uint64_t len) {
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8784732 times.
8784732 assert(source != NULL);
60
61 // Cannot write after Commit()
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8784732 times.
8784732 assert(state_ == kWriteState);
63
64
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 8784688 times.
8784732 if (len == 0)
65 44 return;
66
67 // check the size and eventually save to file
68
4/4
✓ Branch 0 taken 1041436 times.
✓ Branch 1 taken 7743252 times.
✓ Branch 2 taken 11220 times.
✓ Branch 3 taken 1030216 times.
8784688 if (mode_ == kMemoryMode && pos_ + len > in_memory_threshold_) {
69 // changes mode_ to kFileMode
70 11220 SaveToFile();
71 }
72
73
2/2
✓ Branch 0 taken 1030216 times.
✓ Branch 1 taken 7754472 times.
8784688 if (mode_ == kMemoryMode) {
74
2/2
✓ Branch 0 taken 18920 times.
✓ Branch 1 taken 1011296 times.
1030216 if (buf_ == NULL) {
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18920 times.
18920 assert(size_ == 0);
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18920 times.
18920 assert(pos_ == 0);
77 18920 buf_ = reinterpret_cast<unsigned char *>(smalloc(len));
78 18920 size_ = len;
79
2/2
✓ Branch 0 taken 85492 times.
✓ Branch 1 taken 925804 times.
1011296 } else if (size_ < pos_ + len) {
80 85492 const uint64_t newsize = (size_ * 2 < pos_ + len) ? (pos_ + len)
81 : (size_ * 2);
82 85492 buf_ = reinterpret_cast<unsigned char *>(srealloc(buf_, newsize));
83 85492 size_ = newsize;
84 }
85
86 1030216 memcpy(buf_ + pos_, source, len);
87 1030216 pos_ += len;
88 } else {
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7754472 times.
7754472 assert(fp_ != NULL);
90 7754472 const uint64_t bytes_written = fwrite(source, 1, len, fp_);
91
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7754472 times.
7754472 if (bytes_written != len) {
92 ✗ PANIC(kLogStderr,
93 "could not append to temporary file %s: length %lu, "
94 "actually written %lu, error %d",
95 file_path_.c_str(), len, bytes_written, ferror(fp_));
96 }
97 7754472 pos_ += len;
98 7754472 size_ += len;
99 }
100 }
101
102 27324 void FileBackedBuffer::Commit() {
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27324 times.
27324 assert(state_ == kWriteState);
104
105
2/2
✓ Branch 0 taken 11220 times.
✓ Branch 1 taken 16104 times.
27324 if (mode_ == kFileMode) {
106 11220 const int retval = fclose(fp_);
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 if (retval != 0)
108 ✗ PANIC(kLogStderr, "could not close file after writing finished: %s",
109 file_path_.c_str());
110 11220 fp_ = NULL;
111
112
1/2
✓ Branch 2 taken 11220 times.
✗ Branch 3 not taken.
11220 mmapped_ = new MemoryMappedFile(file_path_);
113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11220 times.
11220 if (!mmapped_->Map())
114 ✗ PANIC(kLogStderr, "could not memory-map file %s", file_path_.c_str());
115 } else {
116 // Trim memory chunk size to actual data size
117 16104 buf_ = reinterpret_cast<unsigned char *>(srealloc(buf_, pos_));
118 16104 size_ = pos_;
119 }
120
121 27324 pos_ = 0;
122 27324 state_ = kReadState;
123 27324 }
124
125 717332 int64_t FileBackedBuffer::Data(void **ptr, int64_t len, uint64_t pos) {
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 717332 times.
717332 assert(state_ == kReadState);
127
128 1434664 const int64_t actual_len = (pos + len <= size_)
129
2/2
✓ Branch 0 taken 12760 times.
✓ Branch 1 taken 704572 times.
717332 ? len
130 12760 : static_cast<int64_t>(size_)
131 12760 - static_cast<int64_t>(pos);
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 717332 times.
717332 assert(actual_len >= 0);
133
134
2/2
✓ Branch 0 taken 27016 times.
✓ Branch 1 taken 690316 times.
717332 if (mode_ == kMemoryMode) {
135 27016 *ptr = buf_ + pos;
136 } else {
137 690316 *ptr = mmapped_->buffer() + pos;
138 }
139 717332 return actual_len;
140 }
141
142 690052 int64_t FileBackedBuffer::Read(void *ptr, int64_t len) {
143 690052 const int64_t bytes_read = ReadP(ptr, len, pos_);
144 690052 pos_ += bytes_read;
145 690052 return bytes_read;
146 }
147
148 690052 int64_t FileBackedBuffer::ReadP(void *ptr, int64_t len, uint64_t pos) {
149 void *source;
150
1/2
✓ Branch 1 taken 690052 times.
✗ Branch 2 not taken.
690052 const int64_t bytes_read = Data(&source, len, pos);
151 690052 memcpy(ptr, source, bytes_read);
152 690052 return bytes_read;
153 }
154
155 26752 void FileBackedBuffer::Rewind() {
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26752 times.
26752 assert(state_ == kReadState);
157 26752 pos_ = 0;
158 26752 }
159
160 139920 uint64_t FileBackedBuffer::GetSize() const {
161
4/4
✓ Branch 0 taken 352 times.
✓ Branch 1 taken 139568 times.
✓ Branch 2 taken 308 times.
✓ Branch 3 taken 44 times.
139920 if (state_ == kWriteState && mode_ == kMemoryMode)
162 308 return pos_;
163 139612 return size_;
164 }
165
166
167 11220 void FileBackedBuffer::SaveToFile() {
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 assert(state_ == kWriteState);
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 assert(mode_ == kMemoryMode);
170
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 assert(fp_ == NULL);
172 11220 fp_ = CreateTempFile(tmp_dir_, 0644, "w", &file_path_);
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 if (fp_ == NULL)
174 ✗ PANIC(kLogStderr, "could not create temporary file");
175
176 11220 const uint64_t bytes_written = fwrite(buf_, 1, pos_, fp_);
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11220 times.
11220 if (bytes_written != pos_) {
178 ✗ PANIC(kLogStderr,
179 "could not write to temporary file %s: length %lu, "
180 "actually written %lu, error %d",
181 file_path_.c_str(), pos_, bytes_written, ferror(fp_));
182 }
183
184 11220 free(buf_);
185 11220 buf_ = NULL;
186 11220 size_ = pos_;
187 11220 mode_ = kFileMode;
188 11220 }
189