RIC:1060: Change in PTL
[ric-plt/sdl.git] / src / errorqueries.cpp
1 /*
2    Copyright (c) 2018-2019 Nokia.
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8        http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 */
16
17 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20 */
21
22 #include <sstream>
23 #include "config.h"
24 #include <sdl/errorqueries.hpp>
25 #include "private/createlogger.hpp"
26 #include "private/error.hpp"
27
28 using namespace shareddatalayer;
29
30 namespace
31 {
32     class SharedDataLayerErrorCategory : public std::error_category
33     {
34     public:
35       SharedDataLayerErrorCategory() = default;
36       const char* name() const noexcept override;
37       std::string message(int condition) const override;
38       bool equivalent(const std::error_code& ec, int condition) const noexcept override;
39     };
40
41     const char* SharedDataLayerErrorCategory::name() const noexcept
42     {
43         return "shareddatalayer-errorcodes";
44     }
45
46     std::string SharedDataLayerErrorCategory::message(int condition) const
47     {
48         switch (static_cast<shareddatalayer::Error>(condition))
49         {
50             case shareddatalayer::Error::SUCCESS:
51                 return std::error_code().message();
52             case shareddatalayer::Error::NOT_CONNECTED:
53                 return "shareddatalayer not connected to backend data storage";
54             case shareddatalayer::Error::OPERATION_INTERRUPTED:
55                 return "shareddatalayer sent the request to backend data storage but did not receive reply";
56             case shareddatalayer::Error::BACKEND_FAILURE:
57                 return "backend data storage failed to process the request";
58             case shareddatalayer::Error::REJECTED_BY_BACKEND:
59                 return "backend data storage rejected the request";
60             case shareddatalayer::Error::REJECTED_BY_SDL:
61                 return "SDL rejected the request";
62             default:
63                 return "description missing for SharedDataLayerErrorCategory error: " + std::to_string(condition);
64         }
65     }
66
67     const std::error_category& getSharedDataLayerErrorCategory() noexcept
68     {
69         static const SharedDataLayerErrorCategory theSharedDataLayerErrorCategory;
70         return theSharedDataLayerErrorCategory;
71     }
72
73
74     bool SharedDataLayerErrorCategory::equivalent(const std::error_code& ec, int condition) const noexcept
75     {
76         /* Reasoning for possibly not self-evident mappings:
77             - InternalError::BACKEND_NOT_READY is mapped to shareddatalayer::Error::NOT_CONNECTED
78               even though we are connected to backend in that situation. Client handling for InternalError::BACKEND_NOT_READY
79               situation is identical than handling for other shareddatalayer::Error::NOT_CONNECTED client error cases.
80               To have minimal amount of  client error codes we map it to that.
81             - InternalError::SDL_ERROR_CODE_LOGIC_ERROR is mapped to shareddatalayer::Error::BACKEND_FAILURE.
82               That internal failure should never happen. If it does happen, we cannot know here which kind of error
83               has really happened. Thus we map to the most severe client error code (other places will write logs about this).
84          */
85         switch (static_cast<shareddatalayer::Error>(condition))
86         {
87             case shareddatalayer::Error::SUCCESS:
88                 return ec == InternalError::SUCCESS ||
89                        ec == std::error_code();
90             case shareddatalayer::Error::NOT_CONNECTED:
91                 return ec == InternalError::SDL_NOT_CONNECTED_TO_BACKEND ||
92                        ec == InternalError::BACKEND_NOT_READY ||
93                        ec == InternalError::SDL_NOT_READY;
94             case shareddatalayer::Error::OPERATION_INTERRUPTED:
95                 return ec == InternalError::BACKEND_CONNECTION_LOST;
96             case shareddatalayer::Error::BACKEND_FAILURE:
97                 return ec == InternalError::BACKEND_ERROR ||
98                        ec == InternalError::SDL_ERROR_CODE_LOGIC_ERROR;
99             case shareddatalayer::Error::REJECTED_BY_BACKEND:
100                 return ec == InternalError::BACKEND_REJECTED_REQUEST;
101             case shareddatalayer::Error::REJECTED_BY_SDL:
102                 return ec == InternalError::SDL_RECEIVED_INVALID_PARAMETER;
103             default:
104                 /* Since clients can compare shareddatalayer::Error conditions against any std::error_code based ec, this error log
105                  * can occur without fault in SDL implementation. If error log appears:
106                  *  - First check is the problematic ec set in SDL implementation
107                  *      - If yes, do needed updates to SDL (update error mappings for given ec or change SDL to set some error_code)
108                  *      - If no, ask client to check why they are comparing non-SDL originated error_code against shareddatalayer::Error
109                  */
110                 std::ostringstream msg;
111                 msg << "SharedDataLayerErrorCategory::equivalent no mapping for error: " << ec.category().name()
112                     << ec.value();
113                 logErrorOnce(msg.str());
114                 return false;
115         }
116     }
117 }
118
119 namespace shareddatalayer
120 {
121     std::error_condition make_error_condition(shareddatalayer::Error errorCode)
122     {
123       return {static_cast<int>(errorCode), getSharedDataLayerErrorCategory()};
124     }
125 }