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 #include <algorithm>
30 #include <iterator>
31 #include <string>
32 #include <platform_lib_log_util.h>
33 #include <ClientIndex.h>
34 #include <IDataItemObserver.h>
35 #include <DataItemId.h>
36 
37 using namespace std;
38 using namespace loc_core;
39 
40 template <typename CT, typename DIT>
ClientIndex()41 inline ClientIndex <CT,DIT> :: ClientIndex () {}
42 
43 template <typename CT, typename DIT>
~ClientIndex()44 inline ClientIndex <CT,DIT> :: ~ClientIndex () {}
45 
46 template <typename CT, typename DIT>
isSubscribedClient(CT client)47 bool ClientIndex <CT,DIT> :: isSubscribedClient (CT client) {
48     bool result = false;
49     ENTRY_LOG ();
50     typename map < CT, list <DIT> > :: iterator it =
51         mDataItemsPerClientMap.find (client);
52     if (it != mDataItemsPerClientMap.end ()) {
53         result = true;
54     }
55     EXIT_LOG_WITH_ERROR ("%d",result);
56     return result;
57 }
58 
59 template <typename CT, typename DIT>
getSubscribedList(CT client,list<DIT> & out)60 void ClientIndex <CT,DIT> :: getSubscribedList (CT client, list <DIT> & out) {
61     ENTRY_LOG ();
62     typename map < CT, list <DIT> > :: iterator it =
63         mDataItemsPerClientMap.find (client);
64     if (it != mDataItemsPerClientMap.end ()) {
65         out = it->second;
66     }
67     EXIT_LOG_WITH_ERROR ("%d",0);
68 }
69 
70 template <typename CT, typename DIT>
remove(CT client)71 int ClientIndex <CT,DIT> :: remove (CT client) {
72     int result = 0;
73     ENTRY_LOG ();
74     mDataItemsPerClientMap.erase (client);
75     EXIT_LOG_WITH_ERROR ("%d",result);
76     return result;
77 }
78 
79 template <typename CT, typename DIT>
remove(const list<DIT> & r,list<CT> & out)80 void ClientIndex <CT,DIT> :: remove (const list <DIT> & r, list <CT> & out) {
81     ENTRY_LOG ();
82     typename map < CT, list <DIT> > :: iterator dicIter =
83         mDataItemsPerClientMap.begin ();
84     while (dicIter != mDataItemsPerClientMap.end()) {
85         typename list <DIT> :: const_iterator it = r.begin ();
86         for (; it != r.end (); ++it) {
87             typename list <DIT> :: iterator iter =
88                 find (dicIter->second.begin (), dicIter->second.end (), *it);
89             if (iter != dicIter->second.end ()) {
90                 dicIter->second.erase (iter);
91             }
92         }
93         if (dicIter->second.empty ()) {
94             out.push_back (dicIter->first);
95             // Post-increment operator increases the iterator but returns the
96             // prevous one that will be invalidated by erase()
97             mDataItemsPerClientMap.erase (dicIter++);
98         } else {
99             ++dicIter;
100         }
101     }
102     EXIT_LOG_WITH_ERROR ("%d",0);
103 }
104 
105 template <typename CT, typename DIT>
remove(CT client,const list<DIT> & r,list<DIT> & out)106 void ClientIndex <CT,DIT> :: remove
107 (
108     CT client,
109     const list <DIT> & r,
110     list <DIT> & out
111 )
112 {
113     ENTRY_LOG ();
114     typename map < CT, list <DIT> > :: iterator dicIter =
115         mDataItemsPerClientMap.find (client);
116     if (dicIter != mDataItemsPerClientMap.end ()) {
117         set_intersection (dicIter->second.begin (), dicIter->second.end (),
118                          r.begin (), r.end (),
119                          inserter (out,out.begin ()));
120         if (!out.empty ()) {
121             typename list <DIT> :: iterator it = out.begin ();
122             for (; it != out.end (); ++it) {
123                 dicIter->second.erase (find (dicIter->second.begin (),
124                                             dicIter->second.end (),
125                                             *it));
126             }
127         }
128         if (dicIter->second.empty ()) {
129             mDataItemsPerClientMap.erase (dicIter);
130             EXIT_LOG_WITH_ERROR ("%d",0);
131         }
132     }
133     EXIT_LOG_WITH_ERROR ("%d",0);
134 }
135 
136 template <typename CT, typename DIT>
add(CT client,const list<DIT> & l,list<DIT> & out)137 void ClientIndex <CT,DIT> :: add
138 (
139     CT client,
140     const list <DIT> & l,
141     list <DIT> & out
142 )
143 {
144     ENTRY_LOG ();
145     list <DIT> difference;
146     typename map < CT, list <DIT> > :: iterator dicIter =
147         mDataItemsPerClientMap.find (client);
148     if (dicIter != mDataItemsPerClientMap.end ()) {
149         set_difference (l.begin (), l.end (),
150                        dicIter->second.begin (), dicIter->second.end (),
151                        inserter (difference,difference.begin ()));
152         if (!difference.empty ()) {
153             difference.sort ();
154             out = difference;
155             dicIter->second.merge (difference);
156             dicIter->second.unique ();
157         }
158     } else {
159         out = l;
160         pair < CT, list <DIT> > dicnpair (client, out);
161         mDataItemsPerClientMap.insert (dicnpair);
162     }
163     EXIT_LOG_WITH_ERROR ("%d",0);
164 }
165 
166 // Explicit instantiation must occur in same namespace where class is defined
167 namespace loc_core
168 {
169   template class ClientIndex <IDataItemObserver *, DataItemId>;
170   template class ClientIndex <string, DataItemId>;
171 }
172