11#include " orch.h"
22#include " logger.h"
33
4+ #include < sstream>
5+ #include < iostream>
6+
47using namespace swss ;
58
69Orch::Orch (DBConnector *db, string tableName) :
@@ -13,7 +16,8 @@ Orch::Orch(DBConnector *db, string tableName) :
1316Orch::Orch (DBConnector *db, vector<string> &tableNames) :
1417 m_db(db)
1518{
16- for ( auto it = tableNames.begin (); it != tableNames.end (); it++) {
19+ for ( auto it = tableNames.begin (); it != tableNames.end (); it++)
20+ {
1721 Consumer consumer (new ConsumerTable (m_db, *it));
1822 m_consumerMap.insert (ConsumerMapPair (*it, consumer));
1923 }
@@ -22,9 +26,8 @@ Orch::Orch(DBConnector *db, vector<string> &tableNames) :
2226Orch::~Orch ()
2327{
2428 delete (m_db);
25- for (auto it : m_consumerMap) {
29+ for (auto it : m_consumerMap)
2630 delete it.second .m_consumer ;
27- }
2831}
2932
3033std::vector<Selectable *> Orch::getSelectables ()
@@ -48,10 +51,21 @@ bool Orch::hasSelectable(ConsumerTable *selectable) const
4851 return false ;
4952}
5053
54+ void Orch::dumpTuple (Consumer &consumer, KeyOpFieldsValuesTuple &tuple)
55+ {
56+ string debug_msg = " Full table content: " + consumer.m_consumer ->getTableName () + " key : " + kfvKey (tuple) + " op : " + kfvOp (tuple);
57+ for (auto i = kfvFieldsValues (tuple).begin (); i != kfvFieldsValues (tuple).end (); i++)
58+ {
59+ debug_msg += " " + fvField (*i) + " : " + fvValue (*i);
60+ }
61+ SWSS_LOG_DEBUG (" %s\n " , debug_msg.c_str ());
62+ }
63+
5164bool Orch::execute (string tableName)
5265{
5366 auto consumer_it = m_consumerMap.find (tableName);
54- if (consumer_it == m_consumerMap.end ()) {
67+ if (consumer_it == m_consumerMap.end ())
68+ {
5569 SWSS_LOG_ERROR (" Unrecognized tableName:%s\n " , tableName.c_str ());
5670 return false ;
5771 }
@@ -62,16 +76,10 @@ bool Orch::execute(string tableName)
6276
6377 string key = kfvKey (new_data);
6478 string op = kfvOp (new_data);
65-
66- #ifdef DEBUG
67- string debug = " Table : " + consumer.m_consumer .getTableName () + " key : " + kfvKey (new_data) + " op : " + kfvOp (new_data);
68- for (auto i = kfvFieldsValues (new_data).begin (); i != kfvFieldsValues (new_data).end (); i++)
69- debug += " " + fvField (*i) + " : " + fvValue (*i);
70- SWSS_LOG_DEBUG (" %s\n " , debug.c_str ());
71- #endif
79+ dumpTuple (consumer, new_data);
7280
7381 /* If a new task comes or if a DEL task comes, we directly put it into consumer.m_toSync map */
74- if ( consumer.m_toSync .find (key) == consumer.m_toSync .end () || op == DEL_COMMAND)
82+ if ( consumer.m_toSync .find (key) == consumer.m_toSync .end () || op == DEL_COMMAND)
7583 {
7684 consumer.m_toSync [key] = new_data;
7785 }
@@ -93,7 +101,7 @@ bool Orch::execute(string tableName)
93101 while (iu != existing_values.end ())
94102 {
95103 string ofield = fvField (*iu);
96- if (field == ofield)
104+ if (field == ofield)
97105 iu = existing_values.erase (iu);
98106 else
99107 iu++;
@@ -103,7 +111,119 @@ bool Orch::execute(string tableName)
103111 consumer.m_toSync [key] = KeyOpFieldsValuesTuple (key, op, existing_values);
104112 }
105113
106- if (!consumer.m_toSync .empty ())
114+ if (!consumer.m_toSync .empty ())
115+ doTask (consumer);
116+
117+ return true ;
118+ }
119+ bool Orch::tokenizeString (string str, const string &separator, vector<string> &tokens)
120+ {
121+ SWSS_LOG_ENTER ();
122+ if (0 == separator.size ())
123+ {
124+ SWSS_LOG_ERROR (" Invalid separator passed in:%s\n " , separator.c_str ());
125+ return false ;
126+ }
127+ if (string::npos == str.find (separator))
128+ {
129+ SWSS_LOG_ERROR (" Specified separator:%s not found in input:%s\n " , separator.c_str (), str.c_str ());
130+ return false ;
131+ }
132+ istringstream ss (str);
133+ string tmp;
134+ while (getline (ss, tmp, separator[0 ]))
135+ {
136+ SWSS_LOG_DEBUG (" extracted token:%s" , tmp.c_str ());
137+ tokens.push_back (tmp);
138+ }
139+ return true ;
140+ }
141+
142+ /*
143+ - Validates reference has proper format which is [table_name:object_name]
144+ - validates table_name exists
145+ - validates object with object_name exists
146+ */
147+ bool Orch::parseReference (type_map &type_maps, string &ref_in, string &type_name, string &object_name)
148+ {
149+ SWSS_LOG_ENTER ();
150+ SWSS_LOG_DEBUG (" input:%s" , ref_in.c_str ());
151+ if (ref_in.size () < 3 )
152+ {
153+ SWSS_LOG_ERROR (" invalid reference received:%s\n " , ref_in.c_str ());
154+ return false ;
155+ }
156+ if ((ref_in[0 ] != ref_start) && (ref_in[ref_in.size ()-1 ] != ref_end))
157+ {
158+ SWSS_LOG_ERROR (" malformed reference:%s. Must be surrounded by [ ]\n " , ref_in.c_str ());
159+ return false ;
160+ }
161+ string ref_content = ref_in.substr (1 , ref_in.size () - 2 );
162+ vector<string> tokens;
163+ if (!tokenizeString (ref_content, delimiter, tokens))
164+ {
165+ return false ;
166+ }
167+ if (tokens.size () != 2 )
168+ {
169+ SWSS_LOG_ERROR (" malformed reference:%s. Must contain 2 tokens\n " , ref_content.c_str ());
170+ return false ;
171+ }
172+ auto type_it = type_maps.find (tokens[0 ]);
173+ if (type_it == type_maps.end ())
174+ {
175+ SWSS_LOG_ERROR (" not recognized type:%s\n " , tokens[0 ].c_str ());
176+ return false ;
177+ }
178+ auto obj_map = type_maps[tokens[0 ]];
179+ auto obj_it = obj_map->find (tokens[1 ]);
180+ if (obj_it == obj_map->end ())
181+ {
182+ SWSS_LOG_ERROR (" map:%s does not contain object with name:%s\n " , tokens[0 ].c_str (), tokens[1 ].c_str ());
183+ return false ;
184+ }
185+ type_name = tokens[0 ];
186+ object_name = tokens[1 ];
187+ SWSS_LOG_DEBUG (" parsed: type_name:%s, object_name:%s" , type_name.c_str (), object_name.c_str ());
188+ return true ;
189+ }
190+
191+ ref_resolve_status Orch::resolveFieldRefValue (
192+ type_map &type_maps,
193+ const string &field_name,
194+ KeyOpFieldsValuesTuple &tuple,
195+ sai_object_id_t &sai_object)
196+ {
197+ SWSS_LOG_ENTER ();
198+ size_t count = 0 ;
199+ for (auto i = kfvFieldsValues (tuple).begin (); i != kfvFieldsValues (tuple).end (); i++)
200+ {
201+ if (fvField (*i) == field_name)
202+ {
203+ SWSS_LOG_DEBUG (" field:%s, value:%s" , fvField (*i).c_str (), fvValue (*i).c_str ());
204+ if (count > 1 )
205+ {
206+ SWSS_LOG_ERROR (" Singleton field with name:%s must have only 1 instance, actual count:%d\n " , field_name.c_str (), count);
207+ return ref_resolve_status::multiple_instances;
208+ }
209+ string ref_type_name, object_name;
210+ if (!parseReference (type_maps, fvValue (*i), ref_type_name, object_name))
211+ {
212+ return ref_resolve_status::not_resolved;
213+ }
214+ sai_object = (*(type_maps[ref_type_name]))[object_name];
215+ count++;
216+ }
217+ }
218+ if (0 == count)
219+ {
220+ SWSS_LOG_NOTICE (" field with name:%s not found\n " , field_name.c_str ());
221+ return ref_resolve_status::field_not_found;
222+ }
223+ return ref_resolve_status::success;
224+ }
225+
226+ if (!consumer.m_toSync.empty())
107227 doTask (consumer);
108228
109229 return true ;
@@ -113,7 +233,63 @@ void Orch::doTask()
113233{
114234 for (auto it : m_consumerMap)
115235 {
116- if (!it.second .m_toSync .empty ())
236+ if (!it.second .m_toSync .empty ())
117237 doTask (it.second );
118238 }
119- }
239+ }
240+
241+ // example: [BUFFER_PROFILE_TABLE:e_port.profile0],[BUFFER_PROFILE_TABLE:e_port.profile1]
242+ ref_resolve_status Orch::resolveFieldRefArray (
243+ type_map &type_maps,
244+ const string &field_name,
245+ KeyOpFieldsValuesTuple &tuple,
246+ vector<sai_object_id_t > &sai_object_arr)
247+ {
248+ SWSS_LOG_ENTER ();
249+ size_t count = 0 ;
250+ sai_object_arr.clear ();
251+ for (auto i = kfvFieldsValues (tuple).begin (); i != kfvFieldsValues (tuple).end (); i++)
252+ {
253+ if (fvField (*i) == field_name)
254+ {
255+ if (count > 1 )
256+ {
257+ SWSS_LOG_ERROR (" Singleton field with name:%s must have only 1 instance, actual count:%d\n " , field_name.c_str (), count);
258+ return ref_resolve_status::multiple_instances;
259+ }
260+ string ref_type_name, object_name;
261+ string list = fvValue (*i);
262+ vector<string> list_items;
263+ if (list.find (list_item_delimiter) != string::npos)
264+ {
265+ if (!tokenizeString (list, list_item_delimiter, list_items))
266+ {
267+ SWSS_LOG_ERROR (" Failed to tokenize buffer profile list:%s\n " , list.c_str ());
268+ return ref_resolve_status::failure;
269+ }
270+ }
271+ else
272+ {
273+ list_items.push_back (list);
274+ }
275+ for (size_t ind = 0 ; ind < list_items.size (); ind++)
276+ {
277+ if (!parseReference (type_maps, list_items[ind], ref_type_name, object_name))
278+ {
279+ SWSS_LOG_ERROR (" Failed to parse profile reference:%s\n " , list_items[ind].c_str ());
280+ return ref_resolve_status::not_resolved;
281+ }
282+ sai_object_id_t sai_obj = (*(type_maps[ref_type_name]))[object_name];
283+ SWSS_LOG_DEBUG (" Resolved to sai_object:0x%llx, type:%s, name:%s" , sai_obj, ref_type_name.c_str (), object_name.c_str ());
284+ sai_object_arr.push_back (sai_obj);
285+ }
286+ count++;
287+ }
288+ }
289+ if (0 == count)
290+ {
291+ SWSS_LOG_NOTICE (" field with name:%s not found\n " , field_name.c_str ());
292+ return ref_resolve_status::field_not_found;
293+ }
294+ return ref_resolve_status::success;
295+ }
0 commit comments