Directory: | cvmfs/ |
---|---|
File: | cvmfs/ring_buffer.cc |
Date: | 2025-06-22 02:36:02 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 59 | 59 | 100.0% |
Branches: | 12 | 14 | 85.7% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM File System. | ||
3 | */ | ||
4 | |||
5 | #include "ring_buffer.h" | ||
6 | |||
7 | #include <algorithm> | ||
8 | #include <cassert> | ||
9 | #include <cstdlib> | ||
10 | #include <cstring> | ||
11 | |||
12 | #include "util/smalloc.h" | ||
13 | |||
14 | const RingBuffer::ObjectHandle_t RingBuffer::kInvalidObjectHandle = size_t(-1); | ||
15 | |||
16 | |||
17 | 126 | RingBuffer::RingBuffer(size_t total_size) | |
18 | 126 | : total_size_(total_size) | |
19 | 126 | , free_space_(total_size) | |
20 | 126 | , front_(0) | |
21 | 126 | , back_(0) | |
22 | 126 | , buffer_(reinterpret_cast<unsigned char *>(sxmmap(total_size_))) { | |
23 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
|
126 | assert(total_size_ >= sizeof(size_t)); |
24 | 126 | } | |
25 | |||
26 | |||
27 | 126 | RingBuffer::~RingBuffer() { sxunmap(buffer_, total_size_); } | |
28 | |||
29 | |||
30 | 28154 | void RingBuffer::Put(const void *data, size_t size) { | |
31 | 28154 | const size_t size_head = std::min(size, total_size_ - front_); | |
32 |
2/2✓ Branch 0 taken 28140 times.
✓ Branch 1 taken 14 times.
|
28154 | if (size_head > 0) |
33 | 28140 | memcpy(buffer_ + front_, data, size_head); | |
34 | |||
35 |
2/2✓ Branch 0 taken 4746 times.
✓ Branch 1 taken 23408 times.
|
28154 | if (size_head < size) { |
36 | 4746 | const size_t size_tail = size - size_head; | |
37 | 4746 | memcpy(buffer_, reinterpret_cast<const unsigned char *>(data) + size_head, | |
38 | size_tail); | ||
39 | } | ||
40 | |||
41 | 28154 | front_ = (front_ + size) % total_size_; | |
42 | 28154 | free_space_ -= size; | |
43 | 28154 | } | |
44 | |||
45 | |||
46 | 1453214 | void RingBuffer::Get(size_t from, size_t size, void *to) const { | |
47 | 1453214 | const size_t size_head = std::min(size, total_size_ - from); | |
48 |
2/2✓ Branch 0 taken 1385258 times.
✓ Branch 1 taken 67956 times.
|
1453214 | if (size_head > 0) |
49 | 1385258 | memcpy(to, buffer_ + from, size_head); | |
50 | |||
51 |
2/2✓ Branch 0 taken 122066 times.
✓ Branch 1 taken 1331148 times.
|
1453214 | if (size_head < size) { |
52 | 122066 | const size_t size_tail = size - size_head; | |
53 | 122066 | memcpy(reinterpret_cast<unsigned char *>(to) + size_head, buffer_, | |
54 | size_tail); | ||
55 | } | ||
56 | 1453214 | } | |
57 | |||
58 | |||
59 | 27972 | void RingBuffer::Shrink(size_t by) { | |
60 | 27972 | back_ = (back_ + by) % total_size_; | |
61 | 27972 | free_space_ += by; | |
62 | 27972 | } | |
63 | |||
64 | |||
65 | 41993 | size_t RingBuffer::GetObjectSize(ObjectHandle_t handle) const { | |
66 | size_t size_tag; | ||
67 | 41993 | Get(handle, sizeof(size_tag), &size_tag); | |
68 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41993 times.
|
41993 | assert(size_tag <= total_size_); |
69 | 41993 | return size_tag; | |
70 | } | ||
71 | |||
72 | |||
73 | 14091 | RingBuffer::ObjectHandle_t RingBuffer::PushFront(const void *obj, size_t size) { | |
74 | 14091 | size_t size_tag = size; | |
75 | 14091 | size += sizeof(size_tag); | |
76 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14077 times.
|
14091 | if (size > free_space_) { |
77 | 14 | return kInvalidObjectHandle; | |
78 | } | ||
79 | |||
80 | 14077 | const ObjectHandle_t result = front_; | |
81 | |||
82 | 14077 | Put(&size_tag, sizeof(size_tag)); | |
83 | 14077 | Put(obj, size_tag); | |
84 | |||
85 | 14077 | return result; | |
86 | } | ||
87 | |||
88 | |||
89 | 13986 | RingBuffer::ObjectHandle_t RingBuffer::RemoveBack() { | |
90 | 13986 | const ObjectHandle_t result = back_; | |
91 | |||
92 | 13986 | const size_t size_tag = GetObjectSize(result); | |
93 | 13986 | Shrink(sizeof(size_tag)); | |
94 | 13986 | Shrink(size_tag); | |
95 | |||
96 | 13986 | return result; | |
97 | } | ||
98 | |||
99 | |||
100 | 13972 | void RingBuffer::CopyObject(ObjectHandle_t handle, void *to) const { | |
101 | 13972 | const size_t size_tag = GetObjectSize(handle); | |
102 | 13972 | const ObjectHandle_t object = (handle + sizeof(size_tag)) % total_size_; | |
103 | 13972 | Get(object, size_tag, to); | |
104 | 13972 | } | |
105 | |||
106 | |||
107 | 1397249 | void RingBuffer::CopySlice(ObjectHandle_t handle, size_t size, size_t offset, | |
108 | void *to) const { | ||
109 | 1397249 | const ObjectHandle_t begin = (handle + sizeof(size_t) + offset) % total_size_; | |
110 | 1397249 | Get(begin, size, to); | |
111 | 1397249 | } | |
112 |