]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/util/aligned_buffer.h
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / rocksdb / util / aligned_buffer.h
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
2// This source code is licensed under both the GPLv2 (found in the
3// COPYING file in the root directory) and Apache 2.0 License
4// (found in the LICENSE.Apache file in the root directory).
7c673cae
FG
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
14namespace rocksdb {
15
16inline 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
22inline size_t Roundup(size_t x, size_t y) {
23 return ((x + y - 1) / y) * y;
24}
25
11fdf7f2
TL
26inline size_t Rounddown(size_t x, size_t y) { return (x / y) * y; }
27
7c673cae
FG
28// This class is to manage an aligned user
29// allocated buffer for direct I/O purposes
30// though can be used for any purpose.
31class AlignedBuffer {
32 size_t alignment_;
33 std::unique_ptr<char[]> buf_;
34 size_t capacity_;
35 size_t cursize_;
36 char* bufstart_;
37
38public:
39 AlignedBuffer()
40 : alignment_(),
41 capacity_(0),
42 cursize_(0),
43 bufstart_(nullptr) {
44 }
45
46 AlignedBuffer(AlignedBuffer&& o) ROCKSDB_NOEXCEPT {
47 *this = std::move(o);
48 }
49
50 AlignedBuffer& operator=(AlignedBuffer&& o) ROCKSDB_NOEXCEPT {
51 alignment_ = std::move(o.alignment_);
52 buf_ = std::move(o.buf_);
53 capacity_ = std::move(o.capacity_);
54 cursize_ = std::move(o.cursize_);
55 bufstart_ = std::move(o.bufstart_);
56 return *this;
57 }
58
59 AlignedBuffer(const AlignedBuffer&) = delete;
60
61 AlignedBuffer& operator=(const AlignedBuffer&) = delete;
62
63 static bool isAligned(const void* ptr, size_t alignment) {
64 return reinterpret_cast<uintptr_t>(ptr) % alignment == 0;
65 }
66
67 static bool isAligned(size_t n, size_t alignment) {
68 return n % alignment == 0;
69 }
70
71 size_t Alignment() const {
72 return alignment_;
73 }
74
75 size_t Capacity() const {
76 return capacity_;
77 }
78
79 size_t CurrentSize() const {
80 return cursize_;
81 }
82
83 const char* BufferStart() const {
84 return bufstart_;
85 }
86
87 char* BufferStart() { return bufstart_; }
88
89 void Clear() {
90 cursize_ = 0;
91 }
92
93 void Alignment(size_t alignment) {
94 assert(alignment > 0);
95 assert((alignment & (alignment - 1)) == 0);
96 alignment_ = alignment;
97 }
98
11fdf7f2
TL
99 // Allocates a new buffer and sets bufstart_ to the aligned first byte.
100 // requested_capacity: requested new buffer capacity. This capacity will be
101 // rounded up based on alignment.
102 // copy_data: Copy data from old buffer to new buffer.
103 // copy_offset: Copy data from this offset in old buffer.
104 // copy_len: Number of bytes to copy.
105 void AllocateNewBuffer(size_t requested_capacity, bool copy_data = false,
106 uint64_t copy_offset = 0, size_t copy_len = 0) {
7c673cae
FG
107 assert(alignment_ > 0);
108 assert((alignment_ & (alignment_ - 1)) == 0);
109
11fdf7f2
TL
110 copy_len = copy_len > 0 ? copy_len : cursize_;
111 if (copy_data && requested_capacity < copy_len) {
112 // If we are downsizing to a capacity that is smaller than the current
113 // data in the buffer. Ignore the request.
114 return;
115 }
7c673cae 116
11fdf7f2
TL
117 size_t new_capacity = Roundup(requested_capacity, alignment_);
118 char* new_buf = new char[new_capacity + alignment_];
119 char* new_bufstart = reinterpret_cast<char*>(
120 (reinterpret_cast<uintptr_t>(new_buf) + (alignment_ - 1)) &
121 ~static_cast<uintptr_t>(alignment_ - 1));
122
123 if (copy_data) {
124 assert(bufstart_ + copy_offset + copy_len <= bufstart_ + cursize_);
125 memcpy(new_bufstart, bufstart_ + copy_offset, copy_len);
126 cursize_ = copy_len;
127 } else {
128 cursize_ = 0;
129 }
130
131 bufstart_ = new_bufstart;
132 capacity_ = new_capacity;
133 buf_.reset(new_buf);
7c673cae
FG
134 }
135 // Used for write
136 // Returns the number of bytes appended
137 size_t Append(const char* src, size_t append_size) {
138 size_t buffer_remaining = capacity_ - cursize_;
139 size_t to_copy = std::min(append_size, buffer_remaining);
140
141 if (to_copy > 0) {
142 memcpy(bufstart_ + cursize_, src, to_copy);
143 cursize_ += to_copy;
144 }
145 return to_copy;
146 }
147
148 size_t Read(char* dest, size_t offset, size_t read_size) const {
149 assert(offset < cursize_);
11fdf7f2
TL
150
151 size_t to_read = 0;
152 if(offset < cursize_) {
153 to_read = std::min(cursize_ - offset, read_size);
154 }
7c673cae
FG
155 if (to_read > 0) {
156 memcpy(dest, bufstart_ + offset, to_read);
157 }
158 return to_read;
159 }
160
161 /// Pad to alignment
162 void PadToAlignmentWith(int padding) {
163 size_t total_size = Roundup(cursize_, alignment_);
164 size_t pad_size = total_size - cursize_;
165
166 if (pad_size > 0) {
167 assert((pad_size + cursize_) <= capacity_);
168 memset(bufstart_ + cursize_, padding, pad_size);
169 cursize_ += pad_size;
170 }
171 }
172
11fdf7f2
TL
173 void PadWith(size_t pad_size, int padding) {
174 assert((pad_size + cursize_) <= capacity_);
175 memset(bufstart_ + cursize_, padding, pad_size);
176 cursize_ += pad_size;
177 }
178
7c673cae
FG
179 // After a partial flush move the tail to the beginning of the buffer
180 void RefitTail(size_t tail_offset, size_t tail_size) {
181 if (tail_size > 0) {
182 memmove(bufstart_, bufstart_ + tail_offset, tail_size);
183 }
184 cursize_ = tail_size;
185 }
186
187 // Returns place to start writing
188 char* Destination() {
189 return bufstart_ + cursize_;
190 }
191
192 void Size(size_t cursize) {
193 cursize_ = cursize;
194 }
195};
196}