Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/envoy/api/io_error.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <memory>
4
#include <string>
5
6
#include "envoy/common/platform.h"
7
#include "envoy/common/pure.h"
8
9
namespace Envoy {
10
namespace Api {
11
12
class IoError;
13
14
using IoErrorDeleterType = void (*)(IoError*);
15
using IoErrorPtr = std::unique_ptr<IoError, IoErrorDeleterType>;
16
17
/**
18
 * Base class for any I/O error.
19
 */
20
class IoError {
21
public:
22
  enum class IoErrorCode {
23
    // No data available right now, try again later.
24
    Again,
25
    // Not supported.
26
    NoSupport,
27
    // Address family not supported.
28
    AddressFamilyNoSupport,
29
    // During non-blocking connect, the connection cannot be completed immediately.
30
    InProgress,
31
    // Permission denied.
32
    Permission,
33
    // Message too big to send.
34
    MessageTooBig,
35
    // Kernel interrupt.
36
    Interrupt,
37
    // Requested a nonexistent interface or a non-local source address.
38
    AddressNotAvailable,
39
    // Bad file descriptor.
40
    BadFd,
41
    // An existing connection was forcibly closed by the remote host.
42
    ConnectionReset,
43
    // Network is unreachable due to network settings.
44
    NetworkUnreachable,
45
    // Invalid arguments passed in.
46
    InvalidArgument,
47
    // Other error codes cannot be mapped to any one above in getErrorCode().
48
    UnknownError
49
  };
50
82
  virtual ~IoError() = default;
51
52
  virtual IoErrorCode getErrorCode() const PURE;
53
  virtual std::string getErrorDetails() const PURE;
54
  virtual int getSystemErrorCode() const PURE;
55
56
  // Wrap an IoError* in unique_ptr with custom deleter that doesn't delete.
57
20.5k
  static IoErrorPtr reusedStatic(IoError* err) {
58
20.5k
    return {err, [](IoError*) {}};
59
20.5k
  }
60
  // Wrap an IoError* in unique_ptr with custom deleter.
61
60
  static IoErrorPtr wrap(IoError* err) {
62
60
    return {err, [](IoError* err) { delete err; }};
63
60
  }
64
  // Use this non-error for the success case.
65
121k
  static IoErrorPtr none() {
66
121k
    return {nullptr, [](IoError*) {}};
67
121k
  }
68
};
69
70
/**
71
 * Basic type for return result which has a return code and error code defined
72
 * according to different implementations.
73
 * If the call succeeds, ok() should return true and |return_value_| is valid. Otherwise |err_|
74
 * can be passed into IoError::getErrorCode() to extract the error. In this
75
 * case, |return_value_| is invalid.
76
 */
77
template <typename ReturnValue> struct IoCallResult {
78
  IoCallResult(ReturnValue return_value, IoErrorPtr err)
79
177k
      : return_value_(return_value), err_(std::move(err)) {}
Envoy::Api::IoCallResult<unsigned long>::IoCallResult(unsigned long, std::__1::unique_ptr<Envoy::Api::IoError, void (*)(Envoy::Api::IoError*)>)
Line
Count
Source
79
143k
      : return_value_(return_value), err_(std::move(err)) {}
Envoy::Api::IoCallResult<bool>::IoCallResult(bool, std::__1::unique_ptr<Envoy::Api::IoError, void (*)(Envoy::Api::IoError*)>)
Line
Count
Source
79
18.7k
      : return_value_(return_value), err_(std::move(err)) {}
Envoy::Api::IoCallResult<long>::IoCallResult(long, std::__1::unique_ptr<Envoy::Api::IoError, void (*)(Envoy::Api::IoError*)>)
Line
Count
Source
79
15.6k
      : return_value_(return_value), err_(std::move(err)) {}
Unexecuted instantiation: Envoy::Api::IoCallResult<Envoy::Filesystem::FileInfo>::IoCallResult(Envoy::Filesystem::FileInfo, std::__1::unique_ptr<Envoy::Api::IoError, void (*)(Envoy::Api::IoError*)>)
80
81
  IoCallResult(IoCallResult<ReturnValue>&& result) noexcept
82
115k
      : return_value_(std::move(result.return_value_)), err_(std::move(result.err_)) {}
Envoy::Api::IoCallResult<unsigned long>::IoCallResult(Envoy::Api::IoCallResult<unsigned long>&&)
Line
Count
Source
82
115k
      : return_value_(std::move(result.return_value_)), err_(std::move(result.err_)) {}
Unexecuted instantiation: Envoy::Api::IoCallResult<Envoy::Filesystem::FileInfo>::IoCallResult(Envoy::Api::IoCallResult<Envoy::Filesystem::FileInfo>&&)
Unexecuted instantiation: Envoy::Api::IoCallResult<bool>::IoCallResult(Envoy::Api::IoCallResult<bool>&&)
Unexecuted instantiation: Envoy::Api::IoCallResult<long>::IoCallResult(Envoy::Api::IoCallResult<long>&&)
83
84
293k
  virtual ~IoCallResult() = default;
Envoy::Api::IoCallResult<unsigned long>::~IoCallResult()
Line
Count
Source
84
258k
  virtual ~IoCallResult() = default;
Envoy::Api::IoCallResult<long>::~IoCallResult()
Line
Count
Source
84
15.6k
  virtual ~IoCallResult() = default;
Envoy::Api::IoCallResult<bool>::~IoCallResult()
Line
Count
Source
84
18.7k
  virtual ~IoCallResult() = default;
Unexecuted instantiation: Envoy::Api::IoCallResult<Envoy::Filesystem::FileInfo>::~IoCallResult()
85
86
0
  IoCallResult& operator=(IoCallResult&& result) noexcept {
87
0
    return_value_ = result.return_value_;
88
0
    err_ = std::move(result.err_);
89
0
    return *this;
90
0
  }
91
92
  /**
93
   * @return true if the call succeeds.
94
   */
95
171k
  bool ok() const { return err_ == nullptr; }
Envoy::Api::IoCallResult<unsigned long>::ok() const
Line
Count
Source
95
167k
  bool ok() const { return err_ == nullptr; }
Envoy::Api::IoCallResult<long>::ok() const
Line
Count
Source
95
3.71k
  bool ok() const { return err_ == nullptr; }
96
97
  /**
98
   * This return code is frequent enough that we have a separate function to check.
99
   * @return true if the system call failed because the socket would block.
100
   */
101
0
  bool wouldBlock() const { return !ok() && err_->getErrorCode() == IoError::IoErrorCode::Again; }
102
103
  ReturnValue return_value_;
104
  IoErrorPtr err_;
105
};
106
107
using IoCallBoolResult = IoCallResult<bool>;
108
using IoCallSizeResult = IoCallResult<ssize_t>;
109
using IoCallUint64Result = IoCallResult<uint64_t>;
110
111
1.29k
inline Api::IoCallUint64Result ioCallUint64ResultNoError() {
112
1.29k
  return {0, IoErrorPtr(nullptr, [](IoError*) {})};
113
1.29k
}
114
115
} // namespace Api
116
} // namespace Envoy