2 ==================================================================================
3 Copyright (c) 2019-2020 AT&T Intellectual Property.
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
9 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
21 * Author: Ashwin Shridharan, Shraboni Jana
26 #ifndef SUBSCRIPTION_HANDLER
27 #define SUBSCRIPTION_HANDLER
30 #include <mdclog/mdclog.h>
32 #include <condition_variable>
33 #include <unordered_map>
39 #include <rmr/RIC_message_types.h>
40 #include "e2ap_action.hpp"
41 #include "e2ap_subscription_request.hpp"
42 #include "e2sm_subscription.hpp"
44 #define SUBSCR_SUCCESS 1
45 #define SUBSCR_ERR_TX -1
46 #define SUBSCR_ERR_TIMEOUT -2
47 #define SUBSCR_ERR_FAIL -3
48 #define SUBSCR_ERR_UNKNOWN -4
49 #define SUBSCR_ERR_DUPLICATE -5
56 virtual ~TransmitterBase() {}
59 const T& getParam() const; //to be implemented after Parameter
61 template<class T, class U>
62 void setParam(const U& rhs); //to be implemented after Parameter
66 class Transmitter : public TransmitterBase
69 Transmitter(const T& tx) :obj(tx) {}
70 const T& getParam() const {return obj;}
71 void setParam(const T& tx) {obj=tx;}
76 //Here's the trick: dynamic_cast rather than virtual
77 template<class T> const T& TransmitterBase::getParam() const
79 return dynamic_cast<const Transmitter<T>&>(*this).getParam();
81 template<class T, class U> void TransmitterBase::setParam(const U& rhs)
83 dynamic_cast<Transmitter<T>&>(*this).setParam(rhs);
92 }Subscription_Status_Types;
95 using transaction_identifier = std::string;
96 using transaction_status = Subscription_Status_Types;
98 class SubscriptionHandler {
102 SubscriptionHandler(unsigned int timeout_seconds = 30);
104 template <typename AppTransmitter>
105 int manage_subscription_request(transaction_identifier, AppTransmitter &&);
107 template <typename AppTransmitter>
108 int manage_subscription_delete_request(transaction_identifier, AppTransmitter &&);
110 void manage_subscription_response(int message_type, transaction_identifier id);
112 int get_request_status(transaction_identifier);
113 bool set_request_status(transaction_identifier, transaction_status);
114 bool is_request_entry(transaction_identifier);
115 void set_timeout(unsigned int);
117 void set_ignore_subs_resp(bool b){_ignore_subs_resp = b;};
119 void print_subscription_status(){ for(auto it:status_table){std::cout << it.first << "::" << it.second << std::endl;}};
123 bool add_request_entry(transaction_identifier, transaction_status);
124 bool delete_request_entry(transaction_identifier);
126 template <typename AppTransmitter>
127 bool add_transmitter_entry(transaction_identifier, AppTransmitter&&);
129 std::unordered_map<transaction_identifier, TransmitterBase> trans_table;
130 std::unordered_map<transaction_identifier, transaction_status> status_table;
132 std::unique_ptr<std::mutex> _data_lock;
133 std::unique_ptr<std::condition_variable> _cv;
135 std::chrono::seconds _time_out;
137 bool _ignore_subs_resp = false;
140 template <typename AppTransmitter>
141 bool SubscriptionHandler::add_transmitter_entry(transaction_identifier id, AppTransmitter &&trans){
142 mdclog_write(MDCLOG_INFO,"Entry added for Transaction ID: %s",id.c_str());
144 // add entry in hash table if it does not exist
145 auto search = trans_table.find(id);
146 if(search != trans_table.end()){
150 Transmitter<AppTransmitter> tptr(trans);
151 trans_table[id] = tptr;
156 //this will work for both sending subscription request and subscription delete request.
157 //The handler is oblivious of the message content and follows the transaction id.
158 template<typename AppTransmitter>
159 int SubscriptionHandler::manage_subscription_request(transaction_identifier rmr_trans_id, AppTransmitter && tx){
161 // put entry in request table
163 std::lock_guard<std::mutex> lock(*(_data_lock.get()));
165 res = add_request_entry(rmr_trans_id, request_pending);
167 mdclog_write(MDCLOG_ERR, "%s, %d : Error adding new subscription request %s to queue because request with identical key already present", __FILE__, __LINE__, rmr_trans_id);
168 return SUBSCR_ERR_DUPLICATE;
174 std::unique_lock<std::mutex> _local_lock(*(_data_lock.get()));
181 delete_request_entry(rmr_trans_id);
182 mdclog_write(MDCLOG_ERR, "%s, %d :: Error transmitting subscription request %s", __FILE__, __LINE__, rmr_trans_id.c_str() );
183 return SUBSCR_ERR_TX;
185 mdclog_write(MDCLOG_INFO, "%s, %d :: Transmitted subscription request for trans_id %s", __FILE__, __LINE__, rmr_trans_id.c_str() );
186 add_transmitter_entry(rmr_trans_id, tx);
190 // record time stamp ..
191 auto start = std::chrono::system_clock::now();
192 std::chrono::milliseconds t_out(_time_out);
194 //the wait functionality has been removed.
197 _local_lock.unlock();
198 // std::cout <<"Returning res = " << res << " for request = " << rmr_trans_id << std::endl;