|
reSIProcate/DialogUsageManager
9694
|
00001 #include "resip/dum/InMemorySyncRegDb.hxx" 00002 #include "rutil/Timer.hxx" 00003 #include "rutil/Logger.hxx" 00004 #include "rutil/WinLeakCheck.hxx" 00005 00006 using namespace resip; 00007 00008 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM 00009 00010 class RemoveIfRequired 00011 { 00012 protected: 00013 UInt64 mNow; 00014 unsigned int mRemoveLingerSecs; 00015 public: 00016 RemoveIfRequired(UInt64& now, unsigned int removeLingerSecs) : 00017 mNow(now), 00018 mRemoveLingerSecs(removeLingerSecs) {} 00019 bool operator () (const ContactInstanceRecord& rec) 00020 { 00021 return mustRemove(rec); 00022 } 00023 bool mustRemove(const ContactInstanceRecord& rec) 00024 { 00025 if((rec.mRegExpires <= mNow) && ((mNow - rec.mLastUpdated) > mRemoveLingerSecs)) 00026 { 00027 DebugLog(<< "ContactInstanceRecord removed after linger: " << rec.mContact); 00028 return true; 00029 } 00030 return false; 00031 } 00032 }; 00033 00034 /* Solaris with libCstd seems to choke on the use of an 00035 object (such as RemoveIfRequired) as a predicate for remove_if. 00036 Therefore, this wrapper function implements a workaround, 00037 iterating the list explicitly and using erase(). */ 00038 void 00039 contactsRemoveIfRequired(ContactList& contacts, UInt64& now, 00040 unsigned int removeLingerSecs) 00041 { 00042 RemoveIfRequired rei(now, removeLingerSecs); 00043 #ifdef __SUNPRO_CC 00044 for(ContactList::iterator i = contacts.begin(); i != contacts.end(); ) 00045 { 00046 if(rei.mustRemove(*i)) 00047 i = contacts.erase(i); 00048 else 00049 ++i; 00050 } 00051 #else 00052 contacts.remove_if(rei); 00053 #endif 00054 } 00055 00056 InMemorySyncRegDb::InMemorySyncRegDb(unsigned int removeLingerSecs) : 00057 mRemoveLingerSecs(removeLingerSecs), 00058 mHandler(0) 00059 { 00060 } 00061 00062 InMemorySyncRegDb::~InMemorySyncRegDb() 00063 { 00064 for( database_map_t::const_iterator it = mDatabase.begin(); 00065 it != mDatabase.end(); it++) 00066 { 00067 delete it->second; 00068 } 00069 mDatabase.clear(); 00070 } 00071 00072 void 00073 InMemorySyncRegDb::initialSync(unsigned int connectionId) 00074 { 00075 Lock g(mDatabaseMutex); 00076 UInt64 now = Timer::getTimeSecs(); 00077 for(database_map_t::iterator it = mDatabase.begin(); it != mDatabase.end(); it++) 00078 { 00079 if(it->second) 00080 { 00081 ContactList& contacts = *(it->second); 00082 if(mRemoveLingerSecs > 0) 00083 { 00084 contactsRemoveIfRequired(contacts, now, mRemoveLingerSecs); 00085 } 00086 if(mHandler) mHandler->onInitialSyncAor(connectionId, it->first, contacts); 00087 } 00088 } 00089 } 00090 00091 void 00092 InMemorySyncRegDb::addAor(const Uri& aor, 00093 const ContactList& contacts) 00094 { 00095 Lock g(mDatabaseMutex); 00096 database_map_t::iterator it = mDatabase.find(aor); 00097 if(it != mDatabase.end()) 00098 { 00099 if(it->second) 00100 { 00101 *(it->second) = contacts; 00102 } 00103 else 00104 { 00105 it->second = new ContactList(contacts); 00106 } 00107 } 00108 else 00109 { 00110 mDatabase[aor] = new ContactList(contacts); 00111 } 00112 if(mHandler) mHandler->onAorModified(aor, contacts); 00113 } 00114 00115 void 00116 InMemorySyncRegDb::removeAor(const Uri& aor) 00117 { 00118 database_map_t::iterator i; 00119 00120 Lock g(mDatabaseMutex); 00121 i = mDatabase.find(aor); 00122 //DebugLog (<< "Removing registration bindings " << aor); 00123 if (i != mDatabase.end()) 00124 { 00125 if (i->second) 00126 { 00127 if(mRemoveLingerSecs > 0) 00128 { 00129 ContactList& contacts = *(i->second); 00130 UInt64 now = Timer::getTimeSecs(); 00131 for(ContactList::iterator it = contacts.begin(); it != contacts.end(); it++) 00132 { 00133 // Don't delete record - set expires to 0 00134 it->mRegExpires = 0; 00135 it->mLastUpdated = now; 00136 } 00137 if(mHandler) mHandler->onAorModified(aor, contacts); 00138 } 00139 else 00140 { 00141 delete i->second; 00142 // Setting this to 0 causes it to be removed when we unlock the AOR. 00143 i->second = 0; 00144 ContactList emptyList; 00145 if(mHandler) mHandler->onAorModified(aor, emptyList); 00146 } 00147 } 00148 } 00149 } 00150 00151 void 00152 InMemorySyncRegDb::getAors(InMemorySyncRegDb::UriList& container) 00153 { 00154 container.clear(); 00155 Lock g(mDatabaseMutex); 00156 for( database_map_t::const_iterator it = mDatabase.begin(); 00157 it != mDatabase.end(); it++) 00158 { 00159 container.push_back(it->first); 00160 } 00161 } 00162 00163 bool 00164 InMemorySyncRegDb::aorIsRegistered(const Uri& aor) 00165 { 00166 Lock g(mDatabaseMutex); 00167 database_map_t::iterator i = mDatabase.find(aor); 00168 if (i != mDatabase.end() && i->second == 0) 00169 { 00170 if(mRemoveLingerSecs > 0) 00171 { 00172 ContactList& contacts = *(i->second); 00173 UInt64 now = Timer::getTimeSecs(); 00174 for(ContactList::iterator it = contacts.begin(); it != contacts.end(); it++) 00175 { 00176 if(it->mRegExpires > now) 00177 { 00178 return true; 00179 } 00180 } 00181 } 00182 else 00183 { 00184 return true; 00185 } 00186 } 00187 return false; 00188 } 00189 00190 void 00191 InMemorySyncRegDb::lockRecord(const Uri& aor) 00192 { 00193 Lock g2(mLockedRecordsMutex); 00194 00195 DebugLog(<< "InMemorySyncRegDb::lockRecord: aor=" << aor << " threadid=" << ThreadIf::selfId()); 00196 00197 { 00198 Lock g1(mDatabaseMutex); 00199 // This forces insertion if the record does not yet exist. 00200 mDatabase[aor]; 00201 } 00202 00203 while (mLockedRecords.count(aor)) 00204 { 00205 mRecordUnlocked.wait(mLockedRecordsMutex); 00206 } 00207 00208 mLockedRecords.insert(aor); 00209 } 00210 00211 void 00212 InMemorySyncRegDb::unlockRecord(const Uri& aor) 00213 { 00214 Lock g2(mLockedRecordsMutex); 00215 00216 DebugLog(<< "InMemorySyncRegDb::unlockRecord: aor=" << aor << " threadid=" << ThreadIf::selfId()); 00217 00218 { 00219 Lock g1(mDatabaseMutex); 00220 // If the pointer is null, we remove the record from the map. 00221 database_map_t::iterator i = mDatabase.find(aor); 00222 00223 // The record must have been inserted when we locked it in the first place 00224 assert (i != mDatabase.end()); 00225 00226 if (i->second == 0) 00227 { 00228 mDatabase.erase(i); 00229 } 00230 } 00231 00232 mLockedRecords.erase(aor); 00233 mRecordUnlocked.broadcast(); 00234 } 00235 00236 RegistrationPersistenceManager::update_status_t 00237 InMemorySyncRegDb::updateContact(const resip::Uri& aor, 00238 const ContactInstanceRecord& rec) 00239 { 00240 ContactList *contactList = 0; 00241 00242 { 00243 Lock g(mDatabaseMutex); 00244 00245 database_map_t::iterator i; 00246 i = mDatabase.find(aor); 00247 if (i == mDatabase.end() || i->second == 0) 00248 { 00249 contactList = new ContactList(); 00250 mDatabase[aor] = contactList; 00251 } 00252 else 00253 { 00254 contactList = i->second; 00255 } 00256 } 00257 00258 assert(contactList); 00259 00260 ContactList::iterator j; 00261 00262 // See if the contact is already present. We use URI matching rules here. 00263 for (j = contactList->begin(); j != contactList->end(); j++) 00264 { 00265 if (*j == rec) 00266 { 00267 *j=rec; 00268 if(mHandler && !rec.mSyncContact) mHandler->onAorModified(aor, *contactList); 00269 return CONTACT_UPDATED; 00270 } 00271 } 00272 00273 // This is a new contact, so we add it to the list. 00274 contactList->push_back(rec); 00275 if(mHandler && !rec.mSyncContact) mHandler->onAorModified(aor, *contactList); 00276 return CONTACT_CREATED; 00277 } 00278 00279 void 00280 InMemorySyncRegDb::removeContact(const Uri& aor, 00281 const ContactInstanceRecord& rec) 00282 { 00283 ContactList *contactList = 0; 00284 00285 { 00286 Lock g(mDatabaseMutex); 00287 00288 database_map_t::iterator i; 00289 i = mDatabase.find(aor); 00290 if (i == mDatabase.end() || i->second == 0) 00291 { 00292 return; 00293 } 00294 contactList = i->second; 00295 } 00296 00297 ContactList::iterator j; 00298 00299 // See if the contact is present. We use URI matching rules here. 00300 for (j = contactList->begin(); j != contactList->end(); j++) 00301 { 00302 if (*j == rec) 00303 { 00304 if(mRemoveLingerSecs > 0) 00305 { 00306 j->mRegExpires = 0; 00307 j->mLastUpdated = Timer::getTimeSecs(); 00308 if(mHandler && !rec.mSyncContact) mHandler->onAorModified(aor, *contactList); 00309 } 00310 else 00311 { 00312 contactList->erase(j); 00313 if (contactList->empty()) 00314 { 00315 removeAor(aor); 00316 } 00317 else 00318 { 00319 if(mHandler && !rec.mSyncContact) mHandler->onAorModified(aor, *contactList); 00320 } 00321 } 00322 return; 00323 } 00324 } 00325 } 00326 00327 void 00328 InMemorySyncRegDb::getContacts(const Uri& aor, ContactList& container) 00329 { 00330 Lock g(mDatabaseMutex); 00331 database_map_t::iterator i = mDatabase.find(aor); 00332 if (i == mDatabase.end() || i->second == 0) 00333 { 00334 container.clear(); 00335 return; 00336 } 00337 if(mRemoveLingerSecs > 0) 00338 { 00339 ContactList& contacts = *(i->second); 00340 UInt64 now = Timer::getTimeSecs(); 00341 contactsRemoveIfRequired(contacts, now, mRemoveLingerSecs); 00342 container.clear(); 00343 for(ContactList::iterator it = contacts.begin(); it != contacts.end(); it++) 00344 { 00345 if(it->mRegExpires > now) 00346 { 00347 container.push_back(*it); 00348 } 00349 } 00350 } 00351 else 00352 { 00353 container = *(i->second); 00354 } 00355 } 00356 00357 void 00358 InMemorySyncRegDb::getContactsFull(const Uri& aor, ContactList& container) 00359 { 00360 Lock g(mDatabaseMutex); 00361 database_map_t::iterator i = mDatabase.find(aor); 00362 if (i == mDatabase.end() || i->second == 0) 00363 { 00364 container.clear(); 00365 return; 00366 } 00367 ContactList& contacts = *(i->second); 00368 if(mRemoveLingerSecs > 0) 00369 { 00370 UInt64 now = Timer::getTimeSecs(); 00371 contactsRemoveIfRequired(contacts, now, mRemoveLingerSecs); 00372 } 00373 container = contacts; 00374 } 00375 00376 00377 /* ==================================================================== 00378 * The Vovida Software License, Version 1.0 00379 * 00380 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00381 * 00382 * Redistribution and use in source and binary forms, with or without 00383 * modification, are permitted provided that the following conditions 00384 * are met: 00385 * 00386 * 1. Redistributions of source code must retain the above copyright 00387 * notice, this list of conditions and the following disclaimer. 00388 * 00389 * 2. Redistributions in binary form must reproduce the above copyright 00390 * notice, this list of conditions and the following disclaimer in 00391 * the documentation and/or other materials provided with the 00392 * distribution. 00393 * 00394 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00395 * and "Vovida Open Communication Application Library (VOCAL)" must 00396 * not be used to endorse or promote products derived from this 00397 * software without prior written permission. For written 00398 * permission, please contact vocal@vovida.org. 00399 * 00400 * 4. Products derived from this software may not be called "VOCAL", nor 00401 * may "VOCAL" appear in their name, without prior written 00402 * permission of Vovida Networks, Inc. 00403 * 00404 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00405 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00406 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00407 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00408 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00409 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00410 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00411 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00412 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00413 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00414 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00415 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00416 * DAMAGE. 00417 * 00418 * ==================================================================== 00419 * 00420 * This software consists of voluntary contributions made by Vovida 00421 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00422 * Inc. For more information on Vovida Networks, Inc., please see 00423 * <http://www.vovida.org/>. 00424 * 00425 */
1.7.5.1