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 37using namespace std; 38using namespace loc_core; 39 40template <typename CT, typename DIT> 41inline ClientIndex <CT,DIT> :: ClientIndex () {} 42 43template <typename CT, typename DIT> 44inline ClientIndex <CT,DIT> :: ~ClientIndex () {} 45 46template <typename CT, typename DIT> 47bool 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 59template <typename CT, typename DIT> 60void 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 70template <typename CT, typename DIT> 71int 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 79template <typename CT, typename DIT> 80void 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 105template <typename CT, typename DIT> 106void 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 136template <typename CT, typename DIT> 137void 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 167namespace loc_core 168{ 169 template class ClientIndex <IDataItemObserver *, DataItemId>; 170 template class ClientIndex <string, DataItemId>; 171} 172