1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2017 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 #pragma once
18 
19 #include <platform/dynamic.h>
20 
21 #include <cstdint>
22 #include <system_error>
23 #include <string>
24 
25 namespace cb {
26 namespace mcbp {
27 /**
28  * Definition of the valid response status numbers.
29  *
30  * A well written client should be "future proof" by handling new
31  * error codes to be defined. Note that new error codes means that
32  * the requested operation wasn't performed.
33  */
34 enum class Status : uint16_t {
35     /** The operation completed successfully */
36     Success = 0x00,
37     /** The key does not exists */
38     KeyEnoent = 0x01,
39     /** The key exists in the cluster (with another CAS value) */
40     KeyEexists = 0x02,
41     /** The document exceeds the maximum size */
42     E2big = 0x03,
43     /** Invalid request */
44     Einval = 0x04,
45     /** The document was not stored for some reason. This is
46      * currently a "catch all" for number or error situations, and
47      * should be split into multiple error codes. */
48     NotStored = 0x05,
49     /** Non-numeric server-side value for incr or decr */
50     DeltaBadval = 0x06,
51     /** The server is not responsible for the requested vbucket */
52     NotMyVbucket = 0x07,
53     /** Not connected to a bucket */
54     NoBucket = 0x08,
55     /** The requested resource is locked */
56     Locked = 0x09,
57     /** The authentication context is stale. You should reauthenticate*/
58     AuthStale = 0x1f,
59     /** Authentication failure (invalid user/password combination,
60      * OR an internal error in the authentication library. Could
61      * be a misconfigured SASL configuration. See server logs for
62      * more information.) */
63     AuthError = 0x20,
64     /** Authentication OK so far, please continue */
65     AuthContinue = 0x21,
66     /** The requested value is outside the legal range
67      * (similar to EINVAL, but more specific) */
68     Erange = 0x22,
69     /** Roll back to an earlier version of the vbucket UUID
70      * (_currently_ only used by DCP for agreeing on selecting a
71      * starting point) */
72     Rollback = 0x23,
73     /** No access (could be opcode, value, bucket etc) */
74     Eaccess = 0x24,
75     /** The Couchbase cluster is currently initializing this
76      * node, and the Cluster manager has not yet granted all
77      * users access to the cluster. */
78     NotInitialized = 0x25,
79     /** The server have no idea what this command is for */
80     UnknownCommand = 0x81,
81     /** Not enough memory */
82     Enomem = 0x82,
83     /** The server does not support this command */
84     NotSupported = 0x83,
85     /** An internal error in the server */
86     Einternal = 0x84,
87     /** The system is currently too busy to handle the request.
88      * it is _currently_ only being used by the scrubber in
89      * default_engine to run a task there may only be one of
90      * (subsequent requests to start it would return ebusy until
91      * it's done). */
92     Ebusy = 0x85,
93     /** A temporary error condition occurred. Retrying the
94      * operation may resolve the problem. This could be that the
95      * server is in a degraded situation (like running warmup on
96      * the node), the vbucket could be in an "incorrect" state, a
97      * temporary failure from the underlying persistence layer,
98      * etc).
99      */
100     Etmpfail = 0x86,
101 
102     /**
103      * There is something wrong with the syntax of the provided
104      * XATTR.
105      */
106     XattrEinval = 0x87,
107 
108     /**
109      * Operation attempted with an unknown collection.
110      */
111     UnknownCollection = 0x88,
112 
113     /**
114      * Operation attempted and requires that the collections manifest is set.
115      */
116     NoCollectionsManifest = 0x89,
117 
118     /*
119      * Sub-document specific responses.
120      */
121 
122     /** The provided path does not exist in the document. */
123     SubdocPathEnoent = 0xc0,
124 
125     /** One of path components treats a non-dictionary as a dictionary, or
126      * a non-array as an array.
127      * [Arithmetic operations only] The value the path points to is not
128      * a number. */
129     SubdocPathMismatch = 0xc1,
130 
131     /** The path’s syntax was incorrect. */
132     SubdocPathEinval = 0xc2,
133 
134     /** The path provided is too large; either the string is too long,
135      * or it contains too many components. */
136     SubdocPathE2big = 0xc3,
137 
138     /** The document has too many levels to parse. */
139     SubdocDocE2deep = 0xc4,
140 
141     /** [For mutations only] The value provided will invalidate the JSON if
142      * inserted. */
143     SubdocValueCantinsert = 0xc5,
144 
145     /** The existing document is not valid JSON. */
146     SubdocDocNotJson = 0xc6,
147 
148     /** [For arithmetic ops] The existing number is out of the valid range
149      * for arithmetic ops (cannot be represented as an int64_t). */
150     SubdocNumErange = 0xc7,
151 
152     /** [For arithmetic ops] The delta supplied is invalid. It is either
153      * 0, not an integer, or out of the int64 range */
154     SubdocDeltaEinval = 0xc8,
155 
156     /** [For mutations only] The requested operation requires the path to
157      * not already exist, but it exists. */
158     SubdocPathEexists = 0xc9,
159 
160     /** [For mutations only] Inserting the value would cause the document
161      * to be too deep. */
162     SubdocValueEtoodeep = 0xca,
163 
164     /** [For multi-path commands only] An invalid combination of commands
165      * was specified. */
166     SubdocInvalidCombo = 0xcb,
167 
168     /** [For multi-path commands only] Specified key was successfully
169      * found, but one or more path operations failed. Examine the individual
170      * lookup_result (MULTI_LOOKUP) / mutation_result (MULTI_MUTATION)
171      * structures for details. */
172     SubdocMultiPathFailure = 0xcc,
173 
174     /**
175      * The operation completed successfully, but operated on a deleted
176      * document.
177      */
178     SubdocSuccessDeleted = 0xcd,
179 
180     /**
181      * The combination of the subdoc flags for the xattrs doesn't make
182      * any sense
183      */
184     SubdocXattrInvalidFlagCombo = 0xce,
185 
186     /**
187      * Only a single xattr key may be accessed at the same time.
188      */
189     SubdocXattrInvalidKeyCombo = 0xcf,
190 
191     /**
192      * The server has no knowledge of the requested macro
193      */
194     SubdocXattrUnknownMacro = 0xd0,
195 
196     /**
197      * The server has no knowledge of the requested virtual xattr
198      */
199     SubdocXattrUnknownVattr = 0xd1,
200 
201     /**
202      * Virtual xattrs can't be modified
203      */
204     SubdocXattrCantModifyVattr = 0xd2,
205 
206     /**
207      * [For multi-path commands only] Specified key was found as a
208      * Deleted document, but one or more path operations
209      * failed. Examine the individual lookup_result (MULTI_LOOKUP) /
210      * mutation_result (MULTI_MUTATION) structures for details.
211      */
212     SubdocMultiPathFailureDeleted = 0xd3,
213 
214     /**
215      * According to the spec all xattr commands should come first,
216      * followed by the commands for the document body
217      */
218     SubdocInvalidXattrOrder = 0xd4,
219 
220     /*************************************************************************/
221 
222     /**
223      * Number of valid elements in the enumeration (as used by Couchbase).
224      * Note there are additional values reserved for user application below).
225      */
226     COUNT,
227 
228     /**
229      * The following range of 256 error codes is reserved for end-user
230      * applications (e.g. proxies). Couchbase itself does not return them.
231      */
232     ReservedUserStart = 0xff00,
233     ReservedUserEnd = 0xffff
234 };
235 
236 const std::error_category& error_category() NOEXCEPT;
237 
238 class error : public std::system_error {
239 public:
error(Status ev, const std::string& what_arg)240     error(Status ev, const std::string& what_arg)
241         : system_error(int(ev), error_category(), what_arg) {
242     }
243 
error(Status ev, const char* what_arg)244     error(Status ev, const char* what_arg)
245         : system_error(int(ev), error_category(), what_arg) {
246     }
247 };
248 
make_error_condition(Status e)249 static inline std::error_condition make_error_condition(Status e) {
250     return std::error_condition(int(e), error_category());
251 }
252 
253 /**
254  * Check if the provided status code represents success or a failure
255  *
256  * @param status the status code code to check
257  * @return true if the status code represents a successful critera
258  *         false if the status code represents a failure and the payload
259  *               should be replaced with the standard payload containing
260  *               the error context and UUID (if set)
261  */
262 bool isStatusSuccess(Status status);
263 
264 } // namespace mcbp
265 } // namespace cb
266 
267 /**
268  * Get a textual representation of the given error code
269  */
270 std::string to_string(cb::mcbp::Status status);
271 
272 namespace std {
273 
274 template <>
275 struct is_error_condition_enum<cb::mcbp::Status> : public true_type {};
276 
277 } // namespace std
278