Document AlignedBuffer (#5345)

Summary:
Add comments to util/aligned_buffer.h
Pull Request resolved: https://github.com/facebook/rocksdb/pull/5345

Differential Revision: D15496004

Pulled By: sagar0

fbshipit-source-id: 31bc6f35e88dedd74cff55febe02c9e761304f76
This commit is contained in:
Sagar Vemuri 2019-05-24 10:02:36 -07:00 committed by Facebook Github Bot
parent 74a334a2eb
commit 5d359fc337

View File

@ -13,21 +13,47 @@
namespace rocksdb { namespace rocksdb {
// This file contains utilities to handle the alignment of pages and buffers.
// Truncate to a multiple of page_size, which is also a page boundary. This
// helps to figuring out the right alignment.
// Example:
// TruncateToPageBoundary(5000, 4096) => 4096
// TruncateToPageBoundary(10000, 4096) => 8192
inline size_t TruncateToPageBoundary(size_t page_size, size_t s) { inline size_t TruncateToPageBoundary(size_t page_size, size_t s) {
s -= (s & (page_size - 1)); s -= (s & (page_size - 1));
assert((s % page_size) == 0); assert((s % page_size) == 0);
return s; return s;
} }
// Round up x to a multiple of y.
// Example:
// Roundup(13, 5) => 15
// Roundup(201, 16) => 208
inline size_t Roundup(size_t x, size_t y) { inline size_t Roundup(size_t x, size_t y) {
return ((x + y - 1) / y) * y; return ((x + y - 1) / y) * y;
} }
// Round down x to a multiple of y.
// Example:
// Rounddown(13, 5) => 10
// Rounddown(201, 16) => 192
inline size_t Rounddown(size_t x, size_t y) { return (x / y) * y; } inline size_t Rounddown(size_t x, size_t y) { return (x / y) * y; }
// This class is to manage an aligned user // AlignedBuffer manages a buffer by taking alignment into consideration, and
// allocated buffer for direct I/O purposes // aligns the buffer start and end positions. It is mainly used for direct I/O,
// though can be used for any purpose. // though it can be used other purposes as well.
// It also supports expanding the managed buffer, and copying whole or part of
// the data from old buffer into the new expanded buffer. Such a copy especially
// helps in cases avoiding an IO to re-fetch the data from disk.
//
// Example:
// AlignedBuffer buf;
// buf.Alignment(alignment);
// buf.AllocateNewBuffer(user_requested_buf_size);
// ...
// buf.AllocateNewBuffer(2*user_requested_buf_size, /*copy_data*/ true,
// copy_offset, copy_len);
class AlignedBuffer { class AlignedBuffer {
size_t alignment_; size_t alignment_;
std::unique_ptr<char[]> buf_; std::unique_ptr<char[]> buf_;
@ -96,12 +122,21 @@ public:
alignment_ = alignment; alignment_ = alignment;
} }
// Allocates a new buffer and sets bufstart_ to the aligned first byte. // Allocates a new buffer and sets the start position to the first aligned
// byte.
//
// requested_capacity: requested new buffer capacity. This capacity will be // requested_capacity: requested new buffer capacity. This capacity will be
// rounded up based on alignment. // rounded up based on alignment.
// copy_data: Copy data from old buffer to new buffer. // copy_data: Copy data from old buffer to new buffer. If copy_offset and
// copy_len are not passed in and the new requested capacity is bigger
// than the existing buffer's capacity, the data in the exising buffer is
// fully copied over to the new buffer.
// copy_offset: Copy data from this offset in old buffer. // copy_offset: Copy data from this offset in old buffer.
// copy_len: Number of bytes to copy. // copy_len: Number of bytes to copy.
//
// The function does nothing if the new requested_capacity is smaller than
// the current buffer capacity and copy_data is true i.e. the old buffer is
// retained as is.
void AllocateNewBuffer(size_t requested_capacity, bool copy_data = false, void AllocateNewBuffer(size_t requested_capacity, bool copy_data = false,
uint64_t copy_offset = 0, size_t copy_len = 0) { uint64_t copy_offset = 0, size_t copy_len = 0) {
assert(alignment_ > 0); assert(alignment_ > 0);
@ -110,7 +145,7 @@ public:
copy_len = copy_len > 0 ? copy_len : cursize_; copy_len = copy_len > 0 ? copy_len : cursize_;
if (copy_data && requested_capacity < copy_len) { if (copy_data && requested_capacity < copy_len) {
// If we are downsizing to a capacity that is smaller than the current // If we are downsizing to a capacity that is smaller than the current
// data in the buffer. Ignore the request. // data in the buffer -- Ignore the request.
return; return;
} }
@ -132,8 +167,15 @@ public:
capacity_ = new_capacity; capacity_ = new_capacity;
buf_.reset(new_buf); buf_.reset(new_buf);
} }
// Used for write
// Returns the number of bytes appended // Append to the buffer.
//
// src : source to copy the data from.
// append_size : number of bytes to copy from src.
// Returns the number of bytes appended.
//
// If append_size is more than the remaining buffer size only the
// remaining-size worth of bytes are copied.
size_t Append(const char* src, size_t append_size) { size_t Append(const char* src, size_t append_size) {
size_t buffer_remaining = capacity_ - cursize_; size_t buffer_remaining = capacity_ - cursize_;
size_t to_copy = std::min(append_size, buffer_remaining); size_t to_copy = std::min(append_size, buffer_remaining);
@ -145,6 +187,12 @@ public:
return to_copy; return to_copy;
} }
// Read from the buffer.
//
// dest : destination buffer to copy the data to.
// offset : the buffer offset to start reading from.
// read_size : the number of bytes to copy from the buffer to dest.
// Returns the number of bytes read/copied to dest.
size_t Read(char* dest, size_t offset, size_t read_size) const { size_t Read(char* dest, size_t offset, size_t read_size) const {
assert(offset < cursize_); assert(offset < cursize_);
@ -158,7 +206,7 @@ public:
return to_read; return to_read;
} }
/// Pad to alignment // Pad to the end of alignment with "padding"
void PadToAlignmentWith(int padding) { void PadToAlignmentWith(int padding) {
size_t total_size = Roundup(cursize_, alignment_); size_t total_size = Roundup(cursize_, alignment_);
size_t pad_size = total_size - cursize_; size_t pad_size = total_size - cursize_;
@ -176,7 +224,7 @@ public:
cursize_ += pad_size; cursize_ += pad_size;
} }
// After a partial flush move the tail to the beginning of the buffer // After a partial flush move the tail to the beginning of the buffer.
void RefitTail(size_t tail_offset, size_t tail_size) { void RefitTail(size_t tail_offset, size_t tail_size) {
if (tail_size > 0) { if (tail_size > 0) {
memmove(bufstart_, bufstart_ + tail_offset, tail_size); memmove(bufstart_, bufstart_ + tail_offset, tail_size);
@ -184,7 +232,11 @@ public:
cursize_ = tail_size; cursize_ = tail_size;
} }
// Returns place to start writing // Returns a place to start appending.
// WARNING: Note that it is possible to write past the end of the buffer if
// the buffer is modified without using the write APIs or encapsulation
// offered by AlignedBuffer. It is up to the user to guard against such
// errors.
char* Destination() { char* Destination() {
return bufstart_ + cursize_; return bufstart_ + cursize_;
} }