YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rpc/growable_buffer.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright (c) YugaByte, Inc.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
// in compliance with the License.  You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software distributed under the License
10
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
// or implied.  See the License for the specific language governing permissions and limitations
12
// under the License.
13
//
14
//
15
#ifndef YB_RPC_GROWABLE_BUFFER_H
16
#define YB_RPC_GROWABLE_BUFFER_H
17
18
#include <iosfwd>
19
#include <memory>
20
21
#include <boost/circular_buffer.hpp>
22
23
#include "yb/rpc/stream.h"
24
25
#include "yb/util/mem_tracker.h"
26
#include "yb/util/status_fwd.h"
27
28
#include "yb/util/net/socket.h"
29
30
namespace yb {
31
32
class MemTracker;
33
34
namespace rpc {
35
36
// Allocates blocks for GrowableBuffer, shared between multiple GrowableBuffers.
37
// Each allocated block has fixed size - block_size.
38
// blocks_limits - max number of blocks that could be allocated in non forced mode.
39
class GrowableBufferAllocator {
40
 public:
41
  GrowableBufferAllocator(size_t block_size, const MemTrackerPtr& mem_tracker);
42
  ~GrowableBufferAllocator();
43
44
  size_t block_size() const;
45
46
  // forced - ignore blocks_limit, used when growable buffer does not have at least 2 allocated
47
  // blocks.
48
  uint8_t* Allocate(bool forced);
49
  void Free(uint8_t* buffer, bool was_forced);
50
51
 private:
52
  class Impl;
53
  std::shared_ptr<Impl> impl_;
54
};
55
56
// Used in conjuction with std::unique_ptr to return buffer to allocator.
57
class GrowableBufferDeleter {
58
 public:
59
4.45k
  GrowableBufferDeleter() : allocator_(nullptr) {}
60
  explicit GrowableBufferDeleter(
61
      GrowableBufferAllocator* allocator,
62
4.85k
      bool was_forced) : allocator_(allocator), was_forced_(was_forced) {}
63
64
4.44k
  void operator()(uint8_t* buffer) const {
65
4.44k
    allocator_->Free(buffer, was_forced_);
66
4.44k
  }
67
68
 private:
69
  GrowableBufferAllocator* allocator_;
70
  bool was_forced_ = false;
71
};
72
73
// Convenience buffer for receiving bytes. Consists of chunks of allocated data.
74
// Major features:
75
//   Limit allocated bytes.
76
//   Resize depending on used size.
77
//   Consume read data.
78
class GrowableBuffer : public StreamReadBuffer {
79
 public:
80
  explicit GrowableBuffer(GrowableBufferAllocator* allocator, size_t limit);
81
82
104k
  inline bool ReadyToRead() override { return !Empty(); }
83
105k
  inline bool Empty() override { return size_ == 0; }
84
44.1k
  inline size_t size() const { return size_; }
85
132k
  inline size_t capacity_left() const { return buffers_.size() * block_size_ - size_ - pos_; }
86
14.1k
  inline size_t limit() const { return limit_; }
87
88
0
  size_t DataAvailable() override {
89
0
    return size_;
90
0
  }
91
92
104k
  bool Full() override { return pos_ + size_ >= limit_; }
93
94
  void Swap(GrowableBuffer* rhs);
95
96
  // Reset buffer size to zero. Like with std::vector Clean does not deallocate any memory.
97
249
  void Clear() { pos_ = 0; size_ = 0; }
98
  std::string ToString() const override;
99
100
  // Removes first `count` bytes from buffer, moves remaining bytes to the beginning of the buffer.
101
  // This function should be used with care, because it has linear complexity in terms of the
102
  // remaining number of bytes.
103
  //
104
  // A good use case for this class and function is the following.
105
  // This function is used after we parse all complete packets to move incomplete packet to the
106
  // beginning of the buffer. Usually, there is just a small amount of incomplete data.
107
  // Since even a big packet is received by parts, we will move only the first received block.
108
  void Consume(size_t count, const Slice& prepend) override;
109
110
  Result<IoVecs> PrepareAppend() override;
111
112
  IoVecs AppendedVecs() override;
113
114
  // Mark next `len` bytes as used.
115
  void DataAppended(size_t len) override;
116
117
  // Releases all memory allocated by this buffer. And makes this buffer unusable.
118
  // valid() will return false after call to Reset.
119
  void Reset() override;
120
121
  bool valid() const;
122
123
 private:
124
  IoVecs IoVecsForRange(size_t begin, size_t end);
125
126
  typedef std::unique_ptr<uint8_t, GrowableBufferDeleter> BufferPtr;
127
128
  GrowableBufferAllocator& allocator_;
129
130
  const size_t block_size_;
131
132
  ScopedTrackedConsumption consumption_;
133
134
  // Max capacity for this buffer
135
  const size_t limit_;
136
137
  // Contained data
138
  boost::circular_buffer<BufferPtr> buffers_;
139
140
  // Current start position of used bytes.
141
  size_t pos_ = 0;
142
143
  // Currently used bytes
144
  size_t size_ = 0;
145
};
146
147
std::ostream& operator<<(std::ostream& out, const GrowableBuffer& receiver);
148
149
} // namespace rpc
150
} // namespace yb
151
152
#endif // YB_RPC_GROWABLE_BUFFER_H