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