]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/aligned_buffer.h
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
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).
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.
12 #include "port/port.h"
16 inline size_t TruncateToPageBoundary(size_t page_size
, size_t s
) {
17 s
-= (s
& (page_size
- 1));
18 assert((s
% page_size
) == 0);
22 inline size_t Roundup(size_t x
, size_t y
) {
23 return ((x
+ y
- 1) / y
) * y
;
26 inline size_t Rounddown(size_t x
, size_t y
) { return (x
/ y
) * y
; }
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.
33 std::unique_ptr
<char[]> buf_
;
46 AlignedBuffer(AlignedBuffer
&& o
) ROCKSDB_NOEXCEPT
{
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_
);
59 AlignedBuffer(const AlignedBuffer
&) = delete;
61 AlignedBuffer
& operator=(const AlignedBuffer
&) = delete;
63 static bool isAligned(const void* ptr
, size_t alignment
) {
64 return reinterpret_cast<uintptr_t>(ptr
) % alignment
== 0;
67 static bool isAligned(size_t n
, size_t alignment
) {
68 return n
% alignment
== 0;
71 size_t Alignment() const {
75 size_t Capacity() const {
79 size_t CurrentSize() const {
83 const char* BufferStart() const {
87 char* BufferStart() { return bufstart_
; }
93 void Alignment(size_t alignment
) {
94 assert(alignment
> 0);
95 assert((alignment
& (alignment
- 1)) == 0);
96 alignment_
= alignment
;
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) {
107 assert(alignment_
> 0);
108 assert((alignment_
& (alignment_
- 1)) == 0);
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.
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));
124 assert(bufstart_
+ copy_offset
+ copy_len
<= bufstart_
+ cursize_
);
125 memcpy(new_bufstart
, bufstart_
+ copy_offset
, copy_len
);
131 bufstart_
= new_bufstart
;
132 capacity_
= new_capacity
;
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
);
142 memcpy(bufstart_
+ cursize_
, src
, to_copy
);
148 size_t Read(char* dest
, size_t offset
, size_t read_size
) const {
149 assert(offset
< cursize_
);
152 if(offset
< cursize_
) {
153 to_read
= std::min(cursize_
- offset
, read_size
);
156 memcpy(dest
, bufstart_
+ offset
, to_read
);
162 void PadToAlignmentWith(int padding
) {
163 size_t total_size
= Roundup(cursize_
, alignment_
);
164 size_t pad_size
= total_size
- cursize_
;
167 assert((pad_size
+ cursize_
) <= capacity_
);
168 memset(bufstart_
+ cursize_
, padding
, pad_size
);
169 cursize_
+= pad_size
;
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
;
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
) {
182 memmove(bufstart_
, bufstart_
+ tail_offset
, tail_size
);
184 cursize_
= tail_size
;
187 // Returns place to start writing
188 char* Destination() {
189 return bufstart_
+ cursize_
;
192 void Size(size_t cursize
) {