Directory: | cvmfs/ |
---|---|
File: | cvmfs/ring_buffer.cc |
Date: | 2025-10-19 02:35:28 |
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 | 124 | RingBuffer::RingBuffer(size_t total_size) | |
18 | 124 | : total_size_(total_size) | |
19 | 124 | , free_space_(total_size) | |
20 | 124 | , front_(0) | |
21 | 124 | , back_(0) | |
22 | 124 | , buffer_(reinterpret_cast<unsigned char *>(sxmmap(total_size_))) { | |
23 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
|
124 | assert(total_size_ >= sizeof(size_t)); |
24 | 124 | } | |
25 | |||
26 | |||
27 | 124 | RingBuffer::~RingBuffer() { sxunmap(buffer_, total_size_); } | |
28 | |||
29 | |||
30 | 62186 | void RingBuffer::Put(const void *data, size_t size) { | |
31 | 62186 | const size_t size_head = std::min(size, total_size_ - front_); | |
32 |
2/2✓ Branch 0 taken 62155 times.
✓ Branch 1 taken 31 times.
|
62186 | if (size_head > 0) |
33 | 62155 | memcpy(buffer_ + front_, data, size_head); | |
34 | |||
35 |
2/2✓ Branch 0 taken 10509 times.
✓ Branch 1 taken 51677 times.
|
62186 | if (size_head < size) { |
36 | 10509 | const size_t size_tail = size - size_head; | |
37 | 10509 | memcpy(buffer_, reinterpret_cast<const unsigned char *>(data) + size_head, | |
38 | size_tail); | ||
39 | } | ||
40 | |||
41 | 62186 | front_ = (front_ + size) % total_size_; | |
42 | 62186 | free_space_ -= size; | |
43 | 62186 | } | |
44 | |||
45 | |||
46 | 3217676 | void RingBuffer::Get(size_t from, size_t size, void *to) const { | |
47 | 3217676 | const size_t size_head = std::min(size, total_size_ - from); | |
48 |
2/2✓ Branch 0 taken 3067202 times.
✓ Branch 1 taken 150474 times.
|
3217676 | if (size_head > 0) |
49 | 3067202 | memcpy(to, buffer_ + from, size_head); | |
50 | |||
51 |
2/2✓ Branch 0 taken 270289 times.
✓ Branch 1 taken 2947387 times.
|
3217676 | if (size_head < size) { |
52 | 270289 | const size_t size_tail = size - size_head; | |
53 | 270289 | memcpy(reinterpret_cast<unsigned char *>(to) + size_head, buffer_, | |
54 | size_tail); | ||
55 | } | ||
56 | 3217676 | } | |
57 | |||
58 | |||
59 | 61938 | void RingBuffer::Shrink(size_t by) { | |
60 | 61938 | back_ = (back_ + by) % total_size_; | |
61 | 61938 | free_space_ += by; | |
62 | 61938 | } | |
63 | |||
64 | |||
65 | 92907 | size_t RingBuffer::GetObjectSize(ObjectHandle_t handle) const { | |
66 | size_t size_tag; | ||
67 | 92907 | Get(handle, sizeof(size_tag), &size_tag); | |
68 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92907 times.
|
92907 | assert(size_tag <= total_size_); |
69 | 92907 | return size_tag; | |
70 | } | ||
71 | |||
72 | |||
73 | 31124 | RingBuffer::ObjectHandle_t RingBuffer::PushFront(const void *obj, size_t size) { | |
74 | 31124 | size_t size_tag = size; | |
75 | 31124 | size += sizeof(size_tag); | |
76 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 31093 times.
|
31124 | if (size > free_space_) { |
77 | 31 | return kInvalidObjectHandle; | |
78 | } | ||
79 | |||
80 | 31093 | const ObjectHandle_t result = front_; | |
81 | |||
82 | 31093 | Put(&size_tag, sizeof(size_tag)); | |
83 | 31093 | Put(obj, size_tag); | |
84 | |||
85 | 31093 | return result; | |
86 | } | ||
87 | |||
88 | |||
89 | 30969 | RingBuffer::ObjectHandle_t RingBuffer::RemoveBack() { | |
90 | 30969 | const ObjectHandle_t result = back_; | |
91 | |||
92 | 30969 | const size_t size_tag = GetObjectSize(result); | |
93 | 30969 | Shrink(sizeof(size_tag)); | |
94 | 30969 | Shrink(size_tag); | |
95 | |||
96 | 30969 | return result; | |
97 | } | ||
98 | |||
99 | |||
100 | 30938 | void RingBuffer::CopyObject(ObjectHandle_t handle, void *to) const { | |
101 | 30938 | const size_t size_tag = GetObjectSize(handle); | |
102 | 30938 | const ObjectHandle_t object = (handle + sizeof(size_tag)) % total_size_; | |
103 | 30938 | Get(object, size_tag, to); | |
104 | 30938 | } | |
105 | |||
106 | |||
107 | 3093831 | void RingBuffer::CopySlice(ObjectHandle_t handle, size_t size, size_t offset, | |
108 | void *to) const { | ||
109 | 3093831 | const ObjectHandle_t begin = (handle + sizeof(size_t) + offset) % total_size_; | |
110 | 3093831 | Get(begin, size, to); | |
111 | 3093831 | } | |
112 |