/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/aligned_buffer.h
Line | Count | Source (jump to first uncovered line) |
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 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
21 | | // Use of this source code is governed by a BSD-style license that can be |
22 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
23 | | #pragma once |
24 | | |
25 | | #include <algorithm> |
26 | | #include "yb/rocksdb/port/port.h" |
27 | | |
28 | | namespace rocksdb { |
29 | | |
30 | 0 | inline size_t TruncateToPageBoundary(size_t page_size, size_t s) { |
31 | 0 | s -= (s & (page_size - 1)); |
32 | 0 | assert((s % page_size) == 0); |
33 | 0 | return s; |
34 | 0 | } |
35 | | |
36 | 1.33M | inline size_t Roundup(size_t x, size_t y) { |
37 | 1.33M | return ((x + y - 1) / y) * y; |
38 | 1.33M | } |
39 | | |
40 | | // This class is to manage an aligned user |
41 | | // allocated buffer for unbuffered I/O purposes |
42 | | // though can be used for any purpose. |
43 | | class AlignedBuffer { |
44 | | size_t alignment_; |
45 | | std::unique_ptr<char[]> buf_; |
46 | | size_t capacity_; |
47 | | size_t cursize_; |
48 | | char* bufstart_; |
49 | | |
50 | | public: |
51 | | AlignedBuffer() |
52 | | : alignment_(), |
53 | | capacity_(0), |
54 | | cursize_(0), |
55 | 1.31M | bufstart_(nullptr) { |
56 | 1.31M | } |
57 | | |
58 | 0 | AlignedBuffer(AlignedBuffer&& o) ROCKSDB_NOEXCEPT { |
59 | 0 | *this = std::move(o); |
60 | 0 | } |
61 | | |
62 | 0 | AlignedBuffer& operator=(AlignedBuffer&& o) ROCKSDB_NOEXCEPT { |
63 | 0 | alignment_ = std::move(o.alignment_); |
64 | 0 | buf_ = std::move(o.buf_); |
65 | 0 | capacity_ = std::move(o.capacity_); |
66 | 0 | cursize_ = std::move(o.cursize_); |
67 | 0 | bufstart_ = std::move(o.bufstart_); |
68 | 0 | return *this; |
69 | 0 | } |
70 | | |
71 | | AlignedBuffer(const AlignedBuffer&) = delete; |
72 | | |
73 | | AlignedBuffer& operator=(const AlignedBuffer&) = delete; |
74 | | |
75 | 0 | size_t Alignment() const { |
76 | 0 | return alignment_; |
77 | 0 | } |
78 | | |
79 | 98.6M | size_t Capacity() const { |
80 | 98.6M | return capacity_; |
81 | 98.6M | } |
82 | | |
83 | 98.3M | size_t CurrentSize() const { |
84 | 98.3M | return cursize_; |
85 | 98.3M | } |
86 | | |
87 | 23.8M | const char* BufferStart() const { |
88 | 23.8M | return bufstart_; |
89 | 23.8M | } |
90 | | |
91 | 0 | void Clear() { |
92 | 0 | cursize_ = 0; |
93 | 0 | } |
94 | | |
95 | 1.31M | void Alignment(size_t alignment) { |
96 | 1.31M | assert(alignment > 0); |
97 | 0 | assert((alignment & (alignment - 1)) == 0); |
98 | 0 | alignment_ = alignment; |
99 | 1.31M | } |
100 | | |
101 | | // Allocates a new buffer and sets bufstart_ to the aligned first byte |
102 | 1.33M | void AllocateNewBuffer(size_t requestedCapacity) { |
103 | | |
104 | 1.33M | assert(alignment_ > 0); |
105 | 0 | assert((alignment_ & (alignment_ - 1)) == 0); |
106 | | |
107 | 0 | size_t size = Roundup(requestedCapacity, alignment_); |
108 | 1.33M | buf_.reset(new char[size + alignment_]); |
109 | | |
110 | 1.33M | char* p = buf_.get(); |
111 | 1.33M | bufstart_ = reinterpret_cast<char*>( |
112 | 1.33M | (reinterpret_cast<uintptr_t>(p)+(alignment_ - 1)) & |
113 | 1.33M | ~static_cast<uintptr_t>(alignment_ - 1)); |
114 | 1.33M | capacity_ = size; |
115 | 1.33M | cursize_ = 0; |
116 | 1.33M | } |
117 | | // Used for write |
118 | | // Returns the number of bytes appended |
119 | 49.2M | size_t Append(const char* src, size_t append_size) { |
120 | 49.2M | size_t buffer_remaining = capacity_ - cursize_; |
121 | 49.2M | size_t to_copy = std::min(append_size, buffer_remaining); |
122 | | |
123 | 49.2M | if (to_copy > 0) { |
124 | 49.2M | memcpy(bufstart_ + cursize_, src, to_copy); |
125 | 49.2M | cursize_ += to_copy; |
126 | 49.2M | } |
127 | 49.2M | return to_copy; |
128 | 49.2M | } |
129 | | |
130 | 0 | size_t Read(char* dest, size_t offset, size_t read_size) const { |
131 | 0 | assert(offset < cursize_); |
132 | 0 | size_t to_read = std::min(cursize_ - offset, read_size); |
133 | 0 | if (to_read > 0) { |
134 | 0 | memcpy(dest, bufstart_ + offset, to_read); |
135 | 0 | } |
136 | 0 | return to_read; |
137 | 0 | } |
138 | | |
139 | | /// Pad to alignment |
140 | 0 | void PadToAlignmentWith(int padding) { |
141 | 0 | size_t total_size = Roundup(cursize_, alignment_); |
142 | 0 | size_t pad_size = total_size - cursize_; |
143 | 0 |
|
144 | 0 | if (pad_size > 0) { |
145 | 0 | assert((pad_size + cursize_) <= capacity_); |
146 | 0 | memset(bufstart_ + cursize_, padding, pad_size); |
147 | 0 | cursize_ += pad_size; |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | | // After a partial flush move the tail to the beginning of the buffer |
152 | 0 | void RefitTail(size_t tail_offset, size_t tail_size) { |
153 | 0 | if (tail_size > 0) { |
154 | 0 | memmove(bufstart_, bufstart_ + tail_offset, tail_size); |
155 | 0 | } |
156 | 0 | cursize_ = tail_size; |
157 | 0 | } |
158 | | |
159 | | // Returns place to start writing |
160 | 0 | char* Destination() { |
161 | 0 | return bufstart_ + cursize_; |
162 | 0 | } |
163 | | |
164 | 23.8M | void Size(size_t cursize) { |
165 | 23.8M | cursize_ = cursize; |
166 | 23.8M | } |
167 | | }; |
168 | | } |