1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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 MESSAGE_H
17 #define MESSAGE_H
18 
19 #include <new>
20 #include <string>
21 #include <cstdint>
22 #include "db_errno.h"
23 #include "macro_utils.h"
24 #include "object_holder.h"
25 #include "object_holder_typed.h"
26 #include "communicator_type_define.h"
27 
28 namespace DistributedDB {
29 constexpr uint32_t INVALID_MESSAGE_ID = 0;
30 constexpr uint16_t TYPE_INVALID = 0;
31 constexpr uint16_t TYPE_REQUEST = 1;
32 constexpr uint16_t TYPE_RESPONSE = 2;
33 constexpr uint16_t TYPE_NOTIFY = 3;
34 constexpr uint32_t NO_ERROR = 0;
35 constexpr uint16_t MSG_VERSION_BASE = 0;
36 constexpr uint16_t MSG_VERSION_EXT = 1;
37 
38 class Message {
39 public:
40     Message() = default;
41 
Message(uint32_t inMsgId)42     explicit Message(uint32_t inMsgId)
43     {
44         messageId_ = inMsgId;
45     }
46 
~Message()47     ~Message()
48     {
49         if (holderPtr_ != nullptr) {
50             delete holderPtr_;
51             holderPtr_ = nullptr;
52         }
53     }
54 
55     DISABLE_COPY_ASSIGN_MOVE(Message);
56 
57     // For user convenience, inObj can be a stack object, provided that it supports copy construct
58     // Set Object again will delete object that set before if successfully, otherwise impact no change
59     template<typename T>
SetCopiedObject(const T & inObj)60     int SetCopiedObject(const T &inObj)
61     {
62         T *copiedObject = new (std::nothrow) T(inObj);
63         if (copiedObject == nullptr) {
64             return -E_OUT_OF_MEMORY;
65         }
66         ObjectHolder *tmpHolderPtr = new (std::nothrow) ObjectHolderTyped<T>(copiedObject);
67         if (tmpHolderPtr == nullptr) {
68             delete copiedObject;
69             return -E_OUT_OF_MEMORY;
70         }
71         if (holderPtr_ != nullptr) {
72             delete holderPtr_;
73         }
74         holderPtr_ = tmpHolderPtr;
75         return E_OK;
76     }
77 
78     // By calling this method successfully, The ownership of inObj will be taken up by this class
79     // Thus this class is responsible for delete the inObj
80     // If calling this method unsuccessfully, The ownership of inObj is not changed
81     // Set Object again will delete object that set before if successfully, otherwise impact no change
82     template<typename T>
SetExternalObject(T * & inObj)83     int SetExternalObject(T *&inObj)
84     {
85         if (inObj == nullptr) {
86             return -E_INVALID_ARGS;
87         }
88         ObjectHolder *tmpHolderPtr = new (std::nothrow) ObjectHolderTyped<T>(inObj);
89         if (tmpHolderPtr == nullptr) {
90             return -E_OUT_OF_MEMORY;
91         }
92         if (holderPtr_ != nullptr) {
93             delete holderPtr_;
94         }
95         holderPtr_ = tmpHolderPtr;
96         inObj = nullptr;
97         return E_OK;
98     }
99 
100     // Calling this method in form of GetObject<T>() to specify return type based on the MessageId
101     template<typename T>
GetObject()102     const T *GetObject() const
103     {
104         if (holderPtr_ == nullptr) {
105             return nullptr;
106         }
107         ObjectHolderTyped<T> *realHolderPtr = static_cast<ObjectHolderTyped<T> *>(holderPtr_);
108         return realHolderPtr->GetObject();
109     }
110 
SetMessageType(uint16_t inMsgType)111     int SetMessageType(uint16_t inMsgType)
112     {
113         if (inMsgType != TYPE_REQUEST && inMsgType != TYPE_RESPONSE && inMsgType != TYPE_NOTIFY) {
114             return -E_INVALID_ARGS;
115         }
116         messageType_ = inMsgType;
117         return E_OK;
118     }
119 
SetMessageId(uint32_t inMessageId)120     void SetMessageId(uint32_t inMessageId)
121     {
122         messageId_ = inMessageId;
123     }
124 
SetSessionId(uint32_t inSessionId)125     void SetSessionId(uint32_t inSessionId)
126     {
127         sessionId_ = inSessionId;
128     }
129 
SetSequenceId(uint32_t inSequenceId)130     void SetSequenceId(uint32_t inSequenceId)
131     {
132         sequenceId_ = inSequenceId;
133     }
134 
SetErrorNo(uint32_t inErrorNo)135     void SetErrorNo(uint32_t inErrorNo)
136     {
137         errorNo_ = inErrorNo;
138     }
139 
SetTarget(const std::string & inTarget)140     void SetTarget(const std::string &inTarget)
141     {
142         target_ = inTarget;
143     }
144 
SetPriority(Priority inPriority)145     void SetPriority(Priority inPriority)
146     {
147         prio_ = inPriority;
148     }
149 
SetVersion(uint16_t inVersion)150     void SetVersion(uint16_t inVersion)
151     {
152         if (inVersion != MSG_VERSION_BASE && inVersion != MSG_VERSION_EXT) {
153             return;
154         }
155         version_ = inVersion;
156     }
157 
GetMessageType()158     uint16_t GetMessageType() const
159     {
160         return messageType_;
161     }
162 
GetMessageId()163     uint32_t GetMessageId() const
164     {
165         return messageId_;
166     }
167 
GetSessionId()168     uint32_t GetSessionId() const
169     {
170         return sessionId_;
171     }
172 
GetSequenceId()173     uint32_t GetSequenceId() const
174     {
175         return sequenceId_;
176     }
177 
GetErrorNo()178     uint32_t GetErrorNo() const
179     {
180         return errorNo_;
181     }
182 
GetTarget()183     std::string GetTarget() const
184     {
185         return target_;
186     }
187 
GetPriority()188     Priority GetPriority() const
189     {
190         return prio_;
191     }
192 
GetVersion()193     uint16_t GetVersion() const
194     {
195         return version_;
196     }
197 
IsFeedbackError()198     bool IsFeedbackError() const
199     {
200         return (errorNo_ == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo_ == E_FEEDBACK_COMMUNICATOR_NOT_FOUND);
201     }
202 
203 private:
204     // Field or content that will be serialized for bytes transfer
205     uint16_t version_ = MSG_VERSION_BASE;
206     uint16_t messageType_ = TYPE_INVALID;
207     uint32_t messageId_ = INVALID_MESSAGE_ID;
208     uint32_t sessionId_ = 0;    // Distinguish different conversation
209     uint32_t sequenceId_ = 0;   // Distinguish different message even in same session with same content in retry case
210     uint32_t errorNo_ = NO_ERROR;
211     ObjectHolder *holderPtr_ = nullptr;
212 
213     // Field carry supplemental info
214     std::string target_;
215     Priority prio_ = Priority::LOW;
216 };
217 } // namespace DistributedDB
218 
219 #endif // MESSAGE_H
220