1
#pragma once
2

            
3
#include <functional>
4

            
5
#include "source/common/common/assert.h"
6

            
7
#include "spdlog/spdlog.h"
8

            
9
namespace Envoy {
10
namespace Quic {
11

            
12
// A class, together with a stand alone buffer, used to achieve the purpose of WatermarkBuffer.
13
// Itself doesn't have buffer or bookkeep buffered bytes. But provided with buffered_bytes,
14
// it reacts upon crossing high/low watermarks.
15
// It's no-op if provided low and high watermark are 0.
16
class EnvoyQuicSimulatedWatermarkBuffer {
17
public:
18
  EnvoyQuicSimulatedWatermarkBuffer(uint32_t low_watermark, uint32_t high_watermark,
19
                                    std::function<void()> below_low_watermark,
20
                                    std::function<void()> above_high_watermark,
21
                                    spdlog::logger& logger)
22
14225
      : low_watermark_(low_watermark), high_watermark_(high_watermark),
23
14225
        below_low_watermark_(std::move(below_low_watermark)),
24
14225
        above_high_watermark_(std::move(above_high_watermark)), logger_(logger) {
25
14225
    ASSERT((high_watermark == 0 && low_watermark == 0) || (high_watermark_ > low_watermark_));
26
14225
  }
27

            
28
2533
  uint32_t highWatermark() const { return high_watermark_; }
29

            
30
3
  uint32_t lowWatermark() const { return low_watermark_; }
31

            
32
62648
  void checkHighWatermark(uint32_t bytes_buffered) {
33
62648
    if (high_watermark_ > 0 && !is_full_ && bytes_buffered > high_watermark_) {
34
      // Transitioning from below low watermark to above high watermark.
35
3113
      ENVOY_LOG_TO_LOGGER(logger_, debug, "Buffered {} bytes, cross high watermark {}",
36
3113
                          bytes_buffered, high_watermark_);
37
3113
      is_full_ = true;
38
3113
      above_high_watermark_();
39
3113
    }
40
62648
  }
41

            
42
106098
  void checkLowWatermark(uint32_t bytes_buffered) {
43
106098
    if (low_watermark_ > 0 && is_full_ && bytes_buffered < low_watermark_) {
44
      // Transitioning from above high watermark to below low watermark.
45
3113
      ENVOY_LOG_TO_LOGGER(logger_, debug, "Buffered {} bytes, cross low watermark {}",
46
3113
                          bytes_buffered, low_watermark_);
47
3113
      is_full_ = false;
48
3113
      below_low_watermark_();
49
3113
    }
50
106098
  }
51

            
52
  // True after the buffer goes above high watermark and hasn't come down below low
53
  // watermark yet, even though the buffered data might be between high and low
54
  // watermarks.
55
8021
  bool isAboveHighWatermark() const { return is_full_; }
56

            
57
  // True before the buffer crosses the high watermark for the first time and after the buffer goes
58
  // below low watermark and hasn't come up above high watermark yet, even though the buffered data
59
  // might be between high and low watermarks.
60
5
  bool isBelowLowWatermark() const { return !is_full_; }
61

            
62
private:
63
  uint32_t low_watermark_{0};
64
  uint32_t high_watermark_{0};
65
  bool is_full_{false};
66
  std::function<void()> below_low_watermark_;
67
  std::function<void()> above_high_watermark_;
68
  spdlog::logger& logger_;
69
};
70

            
71
} // namespace Quic
72
} // namespace Envoy