GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/file_backed_buffer.cc
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 99 108 91.7%
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 621 FileBackedBuffer *FileBackedBuffer::Create(uint64_t in_memory_threshold,
17 const std::string &tmp_dir)
18 {
19
1/2
✓ Branch 2 taken 621 times.
✗ Branch 3 not taken.
621 return new FileBackedBuffer(in_memory_threshold, tmp_dir);
20 }
21
22 621 FileBackedBuffer::FileBackedBuffer(uint64_t in_memory_threshold,
23 621 const std::string &tmp_dir) :
24 621 in_memory_threshold_(in_memory_threshold),
25 621 tmp_dir_(tmp_dir),
26 621 state_(kWriteState),
27 621 mode_(kMemoryMode),
28 621 size_(0),
29 621 buf_(NULL),
30 621 pos_(0),
31 621 fp_(NULL),
32
1/2
✓ Branch 2 taken 621 times.
✗ Branch 3 not taken.
621 file_path_(""),
33 621 mmapped_(NULL)
34 {
35 621 }
36
37 1242 FileBackedBuffer::~FileBackedBuffer() {
38 621 free(buf_);
39
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 255 times.
621 if (mode_ != kFileMode)
40 366 return;
41
42
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 if (state_ == kWriteState) {
43 int retval = fclose(fp_);
44 if (retval != 0)
45 PANIC(kLogStderr, "could not close temporary file %s: error %d",
46 file_path_.c_str(), retval);
47 } else {
48 255 mmapped_->Unmap();
49
1/2
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
255 delete mmapped_;
50 }
51 255 int retval = unlink(file_path_.c_str());
52
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 if (retval != 0)
53 PANIC(kLogStderr, "could not delete temporary file %s: error %d",
54 file_path_.c_str(), retval);
55
4/4
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 366 times.
✓ Branch 4 taken 255 times.
✓ Branch 5 taken 366 times.
987 }
56
57 199646 void FileBackedBuffer::Append(const void *source, uint64_t len) {
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199646 times.
199646 assert(source != NULL);
59
60 // Cannot write after Commit()
61
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199646 times.
199646 assert(state_ == kWriteState);
62
63
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 199645 times.
199646 if (len == 0) return;
64
65 // check the size and eventually save to file
66
4/4
✓ Branch 0 taken 23662 times.
✓ Branch 1 taken 175983 times.
✓ Branch 2 taken 255 times.
✓ Branch 3 taken 23407 times.
199645 if (mode_ == kMemoryMode && pos_ + len > in_memory_threshold_) {
67 // changes mode_ to kFileMode
68 255 SaveToFile();
69 }
70
71
2/2
✓ Branch 0 taken 23407 times.
✓ Branch 1 taken 176238 times.
199645 if (mode_ == kMemoryMode) {
72
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 22984 times.
23407 if (buf_ == NULL) {
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(size_ == 0);
74
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 assert(pos_ == 0);
75 423 buf_ = reinterpret_cast<unsigned char *>(smalloc(len));
76 423 size_ = len;
77
2/2
✓ Branch 0 taken 1943 times.
✓ Branch 1 taken 21041 times.
22984 } else if (size_ < pos_ + len) {
78 1943 uint64_t newsize = (size_ * 2 < pos_ + len) ? (pos_ + len) : (size_ * 2);
79 1943 buf_ = reinterpret_cast<unsigned char *>(srealloc(buf_, newsize));
80 1943 size_ = newsize;
81 }
82
83 23407 memcpy(buf_ + pos_, source, len);
84 23407 pos_ += len;
85 } else {
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176238 times.
176238 assert(fp_ != NULL);
87 176238 uint64_t bytes_written = fwrite(source, 1, len, fp_);
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176238 times.
176238 if (bytes_written != len) {
89 PANIC(kLogStderr, "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 176238 pos_ += len;
94 176238 size_ += len;
95 }
96 }
97
98 614 void FileBackedBuffer::Commit() {
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 614 times.
614 assert(state_ == kWriteState);
100
101
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 359 times.
614 if (mode_ == kFileMode) {
102 255 int retval = fclose(fp_);
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 if (retval != 0)
104 PANIC(kLogStderr, "could not close file after writing finished: %s",
105 file_path_.c_str());
106 255 fp_ = NULL;
107
108
1/2
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
255 mmapped_ = new MemoryMappedFile(file_path_);
109
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 255 times.
255 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 359 buf_ = reinterpret_cast<unsigned char *>(srealloc(buf_, pos_));
114 359 size_ = pos_;
115 }
116
117 614 pos_ = 0;
118 614 state_ = kReadState;
119 614 }
120
121 16289 int64_t FileBackedBuffer::Data(void **ptr, int64_t len, uint64_t pos) {
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16289 times.
16289 assert(state_ == kReadState);
123
124
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 16006 times.
16289 int64_t actual_len = (pos + len <= size_) ?
125 283 len : static_cast<int64_t>(size_) - static_cast<int64_t>(pos);
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16289 times.
16289 assert(actual_len >= 0);
127
128
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 15689 times.
16289 if (mode_ == kMemoryMode) {
129 600 *ptr = buf_ + pos;
130 } else {
131 15689 *ptr = mmapped_->buffer() + pos;
132 }
133 16289 return actual_len;
134 }
135
136 15676 int64_t FileBackedBuffer::Read(void *ptr, int64_t len) {
137 15676 int64_t bytes_read = ReadP(ptr, len, pos_);
138 15676 pos_ += bytes_read;
139 15676 return bytes_read;
140 }
141
142 15676 int64_t FileBackedBuffer::ReadP(void *ptr, int64_t len, uint64_t pos) {
143 void *source;
144
1/2
✓ Branch 1 taken 15676 times.
✗ Branch 2 not taken.
15676 int64_t bytes_read = Data(&source, len, pos);
145 15676 memcpy(ptr, source, bytes_read);
146 15676 return bytes_read;
147 }
148
149 608 void FileBackedBuffer::Rewind() {
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 608 times.
608 assert(state_ == kReadState);
151 608 pos_ = 0;
152 608 }
153
154 3153 uint64_t FileBackedBuffer::GetSize() const {
155
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3144 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1 times.
3153 if (state_ == kWriteState && mode_ == kMemoryMode)
156 8 return pos_;
157 3145 return size_;
158 }
159
160
161 255 void FileBackedBuffer::SaveToFile() {
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 assert(state_ == kWriteState);
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 assert(mode_ == kMemoryMode);
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 assert(fp_ == NULL);
166 255 fp_ = CreateTempFile(tmp_dir_, 0644, "w", &file_path_);
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 if (fp_ == NULL)
168 PANIC(kLogStderr, "could not create temporary file");
169
170 255 uint64_t bytes_written = fwrite(buf_, 1, pos_, fp_);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 255 times.
255 if (bytes_written != pos_) {
172 PANIC(kLogStderr, "could not write to temporary file %s: length %lu, "
173 "actually written %lu, error %d",
174 file_path_.c_str(), pos_, bytes_written, ferror(fp_));
175 }
176
177 255 free(buf_);
178 255 buf_ = NULL;
179 255 size_ = pos_;
180 255 mode_ = kFileMode;
181 255 }
182