]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/error_code.cc
update ceph source to reef 18.2.0
[ceph.git] / ceph / src / common / error_code.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2017 Red Hat, Inc. <contact@redhat.com>
7 *
8 * Author: Adam C. Emerson <aemerson@redhat.com>
9 *
10 * This is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License version
12 * 2.1, as published by the Free Software Foundation. See file
13 * COPYING.
14 */
15
16 #include <exception>
17
18 #include "common/error_code.h"
19
20 #pragma GCC diagnostic push
21 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
22 #pragma clang diagnostic push
23 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
24
25 using boost::system::error_category;
26 using boost::system::error_condition;
27 using boost::system::generic_category;
28 using boost::system::system_category;
29
30 namespace ceph {
31
32 // A category for error conditions particular to Ceph
33
34 class ceph_error_category : public converting_category {
35 public:
36 ceph_error_category(){}
37 const char* name() const noexcept override;
38 using converting_category::message;
39 std::string message(int ev) const override;
40 const char* message(int ev, char*, std::size_t) const noexcept override;
41 using converting_category::equivalent;
42 bool equivalent(const boost::system::error_code& c,
43 int ev) const noexcept override;
44 int from_code(int ev) const noexcept override;
45 };
46
47 const char* ceph_error_category::name() const noexcept {
48 return "ceph";
49 }
50
51 const char* ceph_error_category::message(int ev, char*,
52 std::size_t) const noexcept {
53 if (ev == 0)
54 return "No error";
55
56 switch (static_cast<errc>(ev)) {
57
58 case errc::not_in_map:
59 return "Map does not contain requested entry.";
60 case errc::does_not_exist:
61 return "Item does not exist";
62 case errc::failure:
63 return "An internal fault or inconsistency occurred";
64 case errc::exists:
65 return "Already exists";
66 case errc::limit_exceeded:
67 return "Attempt to use too much";
68 case errc::auth:
69 return "Authentication error";
70 case errc::conflict:
71 return "Conflict detected or precondition failed";
72 }
73
74 return "Unknown error.";
75 }
76
77 std::string ceph_error_category::message(int ev) const {
78 return message(ev, nullptr, 0);
79 }
80
81 bool ceph_error_category::equivalent(const boost::system::error_code& c,
82 int ev) const noexcept {
83 if (c.category() == system_category()) {
84 if (c.value() == boost::system::errc::no_such_file_or_directory) {
85 if (ev == static_cast<int>(errc::not_in_map) ||
86 ev == static_cast<int>(errc::does_not_exist)) {
87 // Blargh. A bunch of stuff returns ENOENT now, so just to be safe.
88 return true;
89 }
90 }
91 if (c.value() == boost::system::errc::io_error) {
92 if (ev == static_cast<int>(errc::failure)) {
93 return true;
94 }
95 }
96 if (c.value() == boost::system::errc::file_exists) {
97 if (ev == static_cast<int>(errc::exists)) {
98 return true;
99 }
100 }
101 if (c.value() == boost::system::errc::no_space_on_device ||
102 c.value() == boost::system::errc::invalid_argument) {
103 if (ev == static_cast<int>(errc::limit_exceeded)) {
104 return true;
105 }
106 }
107 if (c.value() == boost::system::errc::operation_not_permitted) {
108 if (ev == static_cast<int>(ceph::errc::conflict)) {
109 return true;
110 }
111 }
112 }
113 return false;
114 }
115
116 int ceph_error_category::from_code(int ev) const noexcept {
117 if (ev == 0)
118 return 0;
119
120 switch (static_cast<errc>(ev)) {
121 case errc::not_in_map:
122 case errc::does_not_exist:
123 // What we use now.
124 return -ENOENT;
125 case errc::failure:
126 return -EIO;
127 case errc::exists:
128 return -EEXIST;
129 case errc::limit_exceeded:
130 return -EIO;
131 case errc::auth:
132 return -EACCES;
133 case errc::conflict:
134 return -EINVAL;
135 }
136 return -EDOM;
137 }
138
139 const error_category& ceph_category() noexcept {
140 static const ceph_error_category c;
141 return c;
142 }
143
144
145 // This is part of the glue for hooking new code to old. Since
146 // Context* and other things give us integer codes from errno, wrap
147 // them in an error_code.
148 [[nodiscard]] boost::system::error_code to_error_code(int ret) noexcept
149 {
150 if (ret == 0)
151 return {};
152 return { std::abs(ret), boost::system::system_category() };
153 }
154
155 // This is more complicated. For the case of categories defined
156 // elsewhere, we have to convert everything here.
157 [[nodiscard]] int from_error_code(boost::system::error_code e) noexcept
158 {
159 if (!e)
160 return 0;
161
162 auto c = dynamic_cast<const converting_category*>(&e.category());
163 // For categories we define
164 if (c)
165 return c->from_code(e.value());
166
167 // For categories matching values of errno
168 if (e.category() == boost::system::system_category() ||
169 e.category() == boost::system::generic_category() ||
170 // ASIO uses the system category for these and matches system
171 // error values.
172 e.category() == boost::asio::error::get_netdb_category() ||
173 e.category() == boost::asio::error::get_addrinfo_category())
174 return -e.value();
175
176 if (e.category() == boost::asio::error::get_misc_category()) {
177 // These values are specific to asio
178 switch (e.value()) {
179 case boost::asio::error::already_open:
180 return -EIO;
181 case boost::asio::error::eof:
182 return -EIO;
183 case boost::asio::error::not_found:
184 return -ENOENT;
185 case boost::asio::error::fd_set_failure:
186 return -EINVAL;
187 }
188 }
189 // Add any other categories we use here.
190
191 // Marcus likes this as a sentinel for 'Error code? What error code?'
192 return -EDOM;
193 }
194 }
195 #pragma GCC diagnostic pop
196 #pragma clang diagnostic pop