memgraph/src/communication/buffer.hpp

175 lines
4.6 KiB
C++

// Copyright 2021 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <vector>
#include "io/network/stream_buffer.hpp"
namespace communication {
/**
* @brief Buffer
*
* Has methods for writing and reading raw data.
*
* Allocating, writing and written stores data in the buffer. The stored
* data can then be read using the pointer returned with the data function.
* This implementation stores data in a variable sized array (a vector).
* The internal array can only grow in size.
*
* This buffer is NOT thread safe. It is intended to be used in the network
* stack where all execution when it is being done is being done on a single
* thread.
*/
class Buffer final {
private:
// Initial capacity of the internal buffer.
const size_t kBufferInitialSize = 65536;
public:
Buffer();
Buffer(const Buffer &) = delete;
Buffer(Buffer &&) = delete;
Buffer &operator=(const Buffer &) = delete;
Buffer &operator=(Buffer &&) = delete;
/**
* This class provides all functions from the buffer that are needed to allow
* reading data from the buffer.
*/
class ReadEnd {
public:
ReadEnd(Buffer *buffer);
ReadEnd(const ReadEnd &) = delete;
ReadEnd(ReadEnd &&) = delete;
ReadEnd &operator=(const ReadEnd &) = delete;
ReadEnd &operator=(ReadEnd &&) = delete;
uint8_t *data();
size_t size() const;
void Shift(size_t len);
void Resize(size_t len);
void Clear();
private:
Buffer *buffer_;
};
/**
* This class provides all functions from the buffer that are needed to allow
* writing data to the buffer.
*/
class WriteEnd {
public:
WriteEnd(Buffer *buffer);
WriteEnd(const WriteEnd &) = delete;
WriteEnd(WriteEnd &&) = delete;
WriteEnd &operator=(const WriteEnd &) = delete;
WriteEnd &operator=(WriteEnd &&) = delete;
io::network::StreamBuffer Allocate();
void Written(size_t len);
void Resize(size_t len);
void Clear();
private:
Buffer *buffer_;
};
/**
* This function returns a pointer to the associated ReadEnd object for this
* buffer.
*/
ReadEnd *read_end();
/**
* This function returns a pointer to the associated WriteEnd object for
* this buffer.
*/
WriteEnd *write_end();
private:
/**
* This function returns a pointer to the internal buffer. It is used for
* reading data from the buffer.
*/
uint8_t *data();
/**
* This function returns the size of available data for reading.
*/
size_t size() const;
/**
* This method shifts the available data for len. It is used when you read
* some data from the buffer and you want to remove it from the buffer.
*
* @param len the length of data that has to be removed from the start of
* the buffer
*/
void Shift(size_t len);
/**
* Allocates a new StreamBuffer from the internal buffer.
* This function returns a pointer to the first currently free memory
* location in the internal buffer. Also, it returns the size of the
* available memory.
*/
io::network::StreamBuffer Allocate();
/**
* This method is used to notify the buffer that the data has been written.
* To write data to this buffer you should do this:
* Call Allocate(), then write to the returned data pointer.
* IMPORTANT: Don't write more data then the returned size, you will cause
* a memory overflow. Then call Written(size) with the length of data that
* you have written into the buffer.
*
* @param len the size of data that has been written into the buffer
*/
void Written(size_t len);
/**
* This method resizes the internal data buffer.
* It is used to notify the buffer of the incoming message size.
* If the requested size is larger than the buffer size then the buffer is
* resized, if the requested size is smaller than the buffer size then
* nothing is done.
*
* @param len the desired size of the buffer
*/
void Resize(size_t len);
/**
* This method clears the buffer. It doesn't release the underlying storage
* space.
*/
void Clear();
std::vector<uint8_t> data_;
size_t have_{0};
ReadEnd read_end_;
WriteEnd write_end_;
};
} // namespace communication