]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/aligned_buffer.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rocksdb / util / aligned_buffer.h
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 #pragma once
10
11 #include <algorithm>
12 #include "port/port.h"
13
14 namespace rocksdb {
15
16 inline size_t TruncateToPageBoundary(size_t page_size, size_t s) {
17 s -= (s & (page_size - 1));
18 assert((s % page_size) == 0);
19 return s;
20 }
21
22 inline size_t Roundup(size_t x, size_t y) {
23 return ((x + y - 1) / y) * y;
24 }
25
26 // This class is to manage an aligned user
27 // allocated buffer for direct I/O purposes
28 // though can be used for any purpose.
29 class AlignedBuffer {
30 size_t alignment_;
31 std::unique_ptr<char[]> buf_;
32 size_t capacity_;
33 size_t cursize_;
34 char* bufstart_;
35
36 public:
37 AlignedBuffer()
38 : alignment_(),
39 capacity_(0),
40 cursize_(0),
41 bufstart_(nullptr) {
42 }
43
44 AlignedBuffer(AlignedBuffer&& o) ROCKSDB_NOEXCEPT {
45 *this = std::move(o);
46 }
47
48 AlignedBuffer& operator=(AlignedBuffer&& o) ROCKSDB_NOEXCEPT {
49 alignment_ = std::move(o.alignment_);
50 buf_ = std::move(o.buf_);
51 capacity_ = std::move(o.capacity_);
52 cursize_ = std::move(o.cursize_);
53 bufstart_ = std::move(o.bufstart_);
54 return *this;
55 }
56
57 AlignedBuffer(const AlignedBuffer&) = delete;
58
59 AlignedBuffer& operator=(const AlignedBuffer&) = delete;
60
61 static bool isAligned(const void* ptr, size_t alignment) {
62 return reinterpret_cast<uintptr_t>(ptr) % alignment == 0;
63 }
64
65 static bool isAligned(size_t n, size_t alignment) {
66 return n % alignment == 0;
67 }
68
69 size_t Alignment() const {
70 return alignment_;
71 }
72
73 size_t Capacity() const {
74 return capacity_;
75 }
76
77 size_t CurrentSize() const {
78 return cursize_;
79 }
80
81 const char* BufferStart() const {
82 return bufstart_;
83 }
84
85 char* BufferStart() { return bufstart_; }
86
87 void Clear() {
88 cursize_ = 0;
89 }
90
91 void Alignment(size_t alignment) {
92 assert(alignment > 0);
93 assert((alignment & (alignment - 1)) == 0);
94 alignment_ = alignment;
95 }
96
97 // Allocates a new buffer and sets bufstart_ to the aligned first byte
98 void AllocateNewBuffer(size_t requestedCapacity) {
99
100 assert(alignment_ > 0);
101 assert((alignment_ & (alignment_ - 1)) == 0);
102
103 size_t size = Roundup(requestedCapacity, alignment_);
104 buf_.reset(new char[size + alignment_]);
105
106 char* p = buf_.get();
107 bufstart_ = reinterpret_cast<char*>(
108 (reinterpret_cast<uintptr_t>(p)+(alignment_ - 1)) &
109 ~static_cast<uintptr_t>(alignment_ - 1));
110 capacity_ = size;
111 cursize_ = 0;
112 }
113 // Used for write
114 // Returns the number of bytes appended
115 size_t Append(const char* src, size_t append_size) {
116 size_t buffer_remaining = capacity_ - cursize_;
117 size_t to_copy = std::min(append_size, buffer_remaining);
118
119 if (to_copy > 0) {
120 memcpy(bufstart_ + cursize_, src, to_copy);
121 cursize_ += to_copy;
122 }
123 return to_copy;
124 }
125
126 size_t Read(char* dest, size_t offset, size_t read_size) const {
127 assert(offset < cursize_);
128 size_t to_read = std::min(cursize_ - offset, read_size);
129 if (to_read > 0) {
130 memcpy(dest, bufstart_ + offset, to_read);
131 }
132 return to_read;
133 }
134
135 /// Pad to alignment
136 void PadToAlignmentWith(int padding) {
137 size_t total_size = Roundup(cursize_, alignment_);
138 size_t pad_size = total_size - cursize_;
139
140 if (pad_size > 0) {
141 assert((pad_size + cursize_) <= capacity_);
142 memset(bufstart_ + cursize_, padding, pad_size);
143 cursize_ += pad_size;
144 }
145 }
146
147 // After a partial flush move the tail to the beginning of the buffer
148 void RefitTail(size_t tail_offset, size_t tail_size) {
149 if (tail_size > 0) {
150 memmove(bufstart_, bufstart_ + tail_offset, tail_size);
151 }
152 cursize_ = tail_size;
153 }
154
155 // Returns place to start writing
156 char* Destination() {
157 return bufstart_ + cursize_;
158 }
159
160 void Size(size_t cursize) {
161 cursize_ = cursize;
162 }
163 };
164 }