1 /* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation, nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #include <string>
31 #include <algorithm>
32 #include <iterator>
33 #include <DataItemIndex.h>
34 #include <platform_lib_log_util.h>
35 #include <IDataItemObserver.h>
36 #include <DataItemId.h>
37 
38 using namespace std;
39 using namespace loc_core;
40 
41 template <typename CT, typename DIT>
DataItemIndex()42 inline DataItemIndex <CT,DIT> :: DataItemIndex () {}
43 
44 template <typename CT, typename DIT>
~DataItemIndex()45 inline DataItemIndex <CT,DIT> :: ~DataItemIndex () {}
46 
47 template <typename CT, typename DIT>
getListOfSubscribedClients(DIT id,list<CT> & out)48 void DataItemIndex <CT,DIT> :: getListOfSubscribedClients
49  (
50     DIT id,
51     list <CT> & out
52 )
53 {
54     typename map < DIT, list <CT> > :: iterator cdiIter =
55         mClientsPerDataItemMap.find (id);
56     if (cdiIter != mClientsPerDataItemMap.end ()) {
57         out = cdiIter->second;
58     }
59 }
60 
61 
62 template <typename CT, typename DIT>
remove(DIT id)63 int DataItemIndex <CT,DIT> :: remove (DIT id) {
64     int result = 0;
65     ENTRY_LOG ();
66     mClientsPerDataItemMap.erase (id);
67     EXIT_LOG_WITH_ERROR ("%d",result);
68     return result;
69 }
70 
71 template <typename CT, typename DIT>
remove(const list<CT> & r,list<DIT> & out)72 void DataItemIndex <CT,DIT> :: remove (const list <CT> & r, list <DIT> & out) {
73     ENTRY_LOG ();
74     typename map < DIT, list <CT> > :: iterator cdiIter =
75         mClientsPerDataItemMap.begin ();
76     while (cdiIter != mClientsPerDataItemMap.end()) {
77         typename list <CT> :: const_iterator it = r.begin ();
78         for (; it != r.end (); ++it) {
79             typename list <CT> :: iterator iter =
80                 find
81                 (
82                     cdiIter->second.begin (),
83                     cdiIter->second.end (),
84                     *it
85                 );
86             if (iter != cdiIter->second.end ()) {
87                 cdiIter->second.erase (iter);
88             }
89         }
90 
91         if (cdiIter->second.empty ()) {
92             out.push_back (cdiIter->first);
93             // Post-increment operator increases the iterator but returns the
94             // prevous one that will be invalidated by erase()
95             mClientsPerDataItemMap.erase (cdiIter++);
96         } else {
97             ++cdiIter;
98         }
99     }
100     EXIT_LOG_WITH_ERROR ("%d",0);
101 }
102 
103 template <typename CT, typename DIT>
remove(DIT id,const list<CT> & r,list<CT> & out)104 void DataItemIndex <CT,DIT> :: remove
105 (
106     DIT id,
107     const list <CT> & r,
108     list <CT> & out
109 )
110 {
111     ENTRY_LOG ();
112 
113     typename map < DIT, list <CT> > :: iterator cdiIter =
114         mClientsPerDataItemMap.find (id);
115     if (cdiIter != mClientsPerDataItemMap.end ()) {
116         set_intersection (cdiIter->second.begin (), cdiIter->second.end (),
117                          r.begin (), r.end (),
118                          inserter (out, out.begin ()));
119         if (!out.empty ()) {
120             typename list <CT> :: iterator it = out.begin ();
121             for (; it != out.end (); ++it) {
122                 cdiIter->second.erase (find (cdiIter->second.begin (),
123                                             cdiIter->second.end (),
124                                             *it));
125             }
126         }
127         if (cdiIter->second.empty ()) {
128             mClientsPerDataItemMap.erase (cdiIter);
129             EXIT_LOG_WITH_ERROR ("%d",0);
130         }
131     }
132     EXIT_LOG_WITH_ERROR ("%d",0);
133 }
134 
135 template <typename CT, typename DIT>
add(DIT id,const list<CT> & l,list<CT> & out)136 void DataItemIndex <CT,DIT> :: add
137 (
138     DIT id,
139     const list <CT> & l,
140     list <CT> & out
141 )
142 {
143     ENTRY_LOG ();
144     list <CT> difference;
145     typename map < DIT, list <CT> > :: iterator cdiIter =
146         mClientsPerDataItemMap.find (id);
147     if (cdiIter != mClientsPerDataItemMap.end ()) {
148         set_difference (l.begin (), l.end (),
149                        cdiIter->second.begin (), cdiIter->second.end (),
150                        inserter (difference, difference.begin ()));
151         if (!difference.empty ()) {
152             difference.sort ();
153             out = difference;
154             cdiIter->second.merge (difference);
155         }
156     } else {
157         out = l;
158         pair < DIT, list <CT> > cndipair (id, out);
159         mClientsPerDataItemMap.insert (cndipair);
160     }
161     EXIT_LOG_WITH_ERROR ("%d",0);
162 }
163 
164 template <typename CT, typename DIT>
add(CT client,const list<DIT> & l,list<DIT> & out)165 void DataItemIndex <CT,DIT> :: add
166 (
167     CT client,
168     const list <DIT> & l,
169     list <DIT> & out
170 )
171 {
172     ENTRY_LOG ();
173     typename map < DIT, list <CT> > :: iterator cdiIter;
174     typename list <DIT> :: const_iterator it = l.begin ();
175     for (; it != l.end (); ++it) {
176         cdiIter = mClientsPerDataItemMap.find (*it);
177         if (cdiIter == mClientsPerDataItemMap.end ()) {
178             out.push_back (*it);
179             pair < DIT, list <CT> > cndiPair (*it, list <CT> (1, client));
180             mClientsPerDataItemMap.insert (cndiPair);
181         } else {
182           typename list<CT> :: iterator clientIter =
183               find
184               (
185                 cdiIter->second.begin (),
186                 cdiIter->second.end (),
187                 client
188               );
189             if (clientIter == cdiIter->second.end()) {
190               cdiIter->second.push_back (client);
191             }
192         }
193     }
194     EXIT_LOG_WITH_ERROR ("%d",0);
195 }
196 
197 // Explicit instantiation must occur in same namespace where class is defined
198 namespace loc_core
199 {
200   template class DataItemIndex <IDataItemObserver *, DataItemId>;
201   template class DataItemIndex <string, DataItemId>;
202 }
203