• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 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
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_CORE_LIB_CORE_ERRORS_H_
17 #define TENSORFLOW_CORE_LIB_CORE_ERRORS_H_
18 
19 #include <sstream>
20 
21 #include "tensorflow/core/lib/core/status.h"
22 #include "tensorflow/core/lib/strings/str_util.h"
23 #include "tensorflow/core/lib/strings/strcat.h"
24 #include "tensorflow/core/platform/logging.h"
25 #include "tensorflow/core/platform/macros.h"
26 
27 namespace tensorflow {
28 namespace errors {
29 
30 typedef ::tensorflow::error::Code Code;
31 
32 namespace internal {
33 
34 // The DECLARE_ERROR macro below only supports types that can be converted
35 // into StrCat's AlphaNum. For the other types we rely on a slower path
36 // through std::stringstream. To add support of a new type, it is enough to
37 // make sure there is an operator<<() for it:
38 //
39 //   std::ostream& operator<<(std::ostream& os, const MyType& foo) {
40 //     os << foo.ToString();
41 //     return os;
42 //   }
43 // Eventually absl::strings will have native support for this and we will be
44 // able to completely remove PrepareForStrCat().
45 template <typename T>
46 typename std::enable_if<!std::is_constructible<strings::AlphaNum, T>::value,
47                         string>::type
PrepareForStrCat(const T & t)48 PrepareForStrCat(const T& t) {
49   std::stringstream ss;
50   ss << t;
51   return ss.str();
52 }
PrepareForStrCat(const strings::AlphaNum & a)53 inline const strings::AlphaNum& PrepareForStrCat(const strings::AlphaNum& a) {
54   return a;
55 }
56 
57 }  // namespace internal
58 
59 // Append some context to an error message.  Each time we append
60 // context put it on a new line, since it is possible for there
61 // to be several layers of additional context.
62 template <typename... Args>
AppendToMessage(::tensorflow::Status * status,Args...args)63 void AppendToMessage(::tensorflow::Status* status, Args... args) {
64   *status = ::tensorflow::Status(
65       status->code(),
66       ::tensorflow::strings::StrCat(status->error_message(), "\n\t", args...));
67 }
68 
69 // For propagating errors when calling a function.
70 #define TF_RETURN_IF_ERROR(...)                          \
71   do {                                                   \
72     const ::tensorflow::Status _status = (__VA_ARGS__);  \
73     if (TF_PREDICT_FALSE(!_status.ok())) return _status; \
74   } while (0)
75 
76 #define TF_RETURN_WITH_CONTEXT_IF_ERROR(expr, ...)                  \
77   do {                                                              \
78     ::tensorflow::Status _status = (expr);                          \
79     if (TF_PREDICT_FALSE(!_status.ok())) {                          \
80       ::tensorflow::errors::AppendToMessage(&_status, __VA_ARGS__); \
81       return _status;                                               \
82     }                                                               \
83   } while (0)
84 
85 // Convenience functions for generating and using error status.
86 // Example usage:
87 //   status.Update(errors::InvalidArgument("The ", foo, " isn't right."));
88 //   if (errors::IsInvalidArgument(status)) { ... }
89 //   switch (status.code()) { case error::INVALID_ARGUMENT: ... }
90 
91 #define DECLARE_ERROR(FUNC, CONST)                                       \
92   template <typename... Args>                                            \
93   ::tensorflow::Status FUNC(Args... args) {                              \
94     return ::tensorflow::Status(                                         \
95         ::tensorflow::error::CONST,                                      \
96         ::tensorflow::strings::StrCat(                                   \
97             ::tensorflow::errors::internal::PrepareForStrCat(args)...)); \
98   }                                                                      \
99   inline bool Is##FUNC(const ::tensorflow::Status& status) {             \
100     return status.code() == ::tensorflow::error::CONST;                  \
101   }
102 
DECLARE_ERROR(Cancelled,CANCELLED)103 DECLARE_ERROR(Cancelled, CANCELLED)
104 DECLARE_ERROR(InvalidArgument, INVALID_ARGUMENT)
105 DECLARE_ERROR(NotFound, NOT_FOUND)
106 DECLARE_ERROR(AlreadyExists, ALREADY_EXISTS)
107 DECLARE_ERROR(ResourceExhausted, RESOURCE_EXHAUSTED)
108 DECLARE_ERROR(Unavailable, UNAVAILABLE)
109 DECLARE_ERROR(FailedPrecondition, FAILED_PRECONDITION)
110 DECLARE_ERROR(OutOfRange, OUT_OF_RANGE)
111 DECLARE_ERROR(Unimplemented, UNIMPLEMENTED)
112 DECLARE_ERROR(Internal, INTERNAL)
113 DECLARE_ERROR(Aborted, ABORTED)
114 DECLARE_ERROR(DeadlineExceeded, DEADLINE_EXCEEDED)
115 DECLARE_ERROR(DataLoss, DATA_LOSS)
116 DECLARE_ERROR(Unknown, UNKNOWN)
117 DECLARE_ERROR(PermissionDenied, PERMISSION_DENIED)
118 DECLARE_ERROR(Unauthenticated, UNAUTHENTICATED)
119 
120 #undef DECLARE_ERROR
121 
122 // Produces a formatted string pattern from the name which can uniquely identify
123 // this node upstream to produce an informative error message. The pattern
124 // followed is: {{node <name>}}
125 // Note: The pattern below determines the regex _NODEDEF_NAME_RE in the file
126 // tensorflow/python/client/session.py
127 // LINT.IfChange
128 inline string FormatNodeNameForError(const string& name) {
129   return strings::StrCat("{{node ", name, "}}");
130 }
131 // LINT.ThenChange(//tensorflow/python/client/session.py)
132 template <typename T>
FormatNodeNamesForError(const T & names)133 string FormatNodeNamesForError(const T& names) {
134   return ::tensorflow::str_util::Join(
135       names, ", ", [](string* output, const string& s) {
136         ::tensorflow::strings::StrAppend(output, FormatNodeNameForError(s));
137       });
138 }
139 // LINT.IfChange
FormatColocationNodeForError(const string & name)140 inline string FormatColocationNodeForError(const string& name) {
141   return strings::StrCat("{{colocation_node ", name, "}}");
142 }
143 // LINT.ThenChange(//tensorflow/python/framework/error_interpolation.py)
144 template <typename T>
FormatColocationNodeForError(const T & names)145 string FormatColocationNodeForError(const T& names) {
146   return ::tensorflow::str_util::Join(
147       names, ", ", [](string* output, const string& s) {
148         ::tensorflow::strings::StrAppend(output,
149                                          FormatColocationNodeForError(s));
150       });
151 }
152 
FormatFunctionForError(const string & name)153 inline string FormatFunctionForError(const string& name) {
154   return strings::StrCat("{{function_node ", name, "}}");
155 }
156 
157 // The CanonicalCode() for non-errors.
158 using ::tensorflow::error::OK;
159 
160 }  // namespace errors
161 }  // namespace tensorflow
162 
163 #endif  // TENSORFLOW_CORE_LIB_CORE_ERRORS_H_
164