reSIProcate/DialogUsageManager  9694
InMemoryRegistrationDatabase.cxx
Go to the documentation of this file.
00001 #include <ctime>
00002 
00003 #include "resip/dum/InMemoryRegistrationDatabase.hxx"
00004 #include "rutil/Timer.hxx"
00005 #include "rutil/Logger.hxx"
00006 #include "rutil/WinLeakCheck.hxx"
00007 
00008 using namespace resip;
00009 
00010 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
00011 
00012 InMemoryRegistrationDatabase::InMemoryRegistrationDatabase(bool checkExpiry) :
00013    mCheckExpiry(checkExpiry)
00014 {
00015 }
00016 
00017 InMemoryRegistrationDatabase::~InMemoryRegistrationDatabase()
00018 {
00019    for( database_map_t::const_iterator it = mDatabase.begin();
00020         it != mDatabase.end(); it++)
00021    {
00022       delete it->second;
00023    }
00024    mDatabase.clear();
00025 }
00026 
00027 void 
00028 InMemoryRegistrationDatabase::addAor(const Uri& aor,
00029                                        const ContactList& contacts)
00030 {
00031   Lock g(mDatabaseMutex);
00032   mDatabase[aor] = new ContactList(contacts);
00033 }
00034 
00035 void 
00036 InMemoryRegistrationDatabase::removeAor(const Uri& aor)
00037 {
00038   database_map_t::iterator i;
00039 
00040   Lock g(mDatabaseMutex);
00041   i = mDatabase.find(aor);
00042   //DebugLog (<< "Removing registration bindings " << aor);
00043   if (i != mDatabase.end())
00044   {
00045      if (i->second)
00046      {
00047         DebugLog (<< "Removed " << i->second->size() << " entries");
00048         delete i->second;
00049         // Setting this to 0 causes it to be removed when we unlock the AOR.
00050         i->second = 0;
00051      }
00052   }
00053 }
00054 
00055 void
00056 InMemoryRegistrationDatabase::getAors(InMemoryRegistrationDatabase::UriList& container)
00057 {
00058    container.clear();
00059    Lock g(mDatabaseMutex);
00060    for( database_map_t::const_iterator it = mDatabase.begin();
00061         it != mDatabase.end(); it++)
00062    {
00063       container.push_back(it->first);
00064    }
00065 }
00066 
00067 bool 
00068 InMemoryRegistrationDatabase::aorIsRegistered(const Uri& aor)
00069 {
00070   Lock g(mDatabaseMutex);
00071   database_map_t::iterator i = findNotExpired(aor);
00072   if (i == mDatabase.end() || i->second == 0)
00073   {
00074     return false;
00075   }
00076   return true;
00077 }
00078 
00079 void
00080 InMemoryRegistrationDatabase::lockRecord(const Uri& aor)
00081 {
00082   Lock g2(mLockedRecordsMutex);
00083 
00084   {
00085     Lock g1(mDatabaseMutex);
00086     // This forces insertion if the record does not yet exist.
00087     mDatabase[aor];
00088   }
00089 
00090   while (mLockedRecords.count(aor))
00091   {
00092     mRecordUnlocked.wait(mLockedRecordsMutex);
00093   }
00094 
00095   mLockedRecords.insert(aor);
00096 }
00097 
00098 void
00099 InMemoryRegistrationDatabase::unlockRecord(const Uri& aor)
00100 {
00101   Lock g2(mLockedRecordsMutex);
00102 
00103   {
00104     Lock g1(mDatabaseMutex);
00105     // If the pointer is null, we remove the record from the map.
00106     database_map_t::iterator i = mDatabase.find(aor);
00107 
00108     // The record must have been inserted when we locked it in the first place
00109     assert (i != mDatabase.end());
00110 
00111     if (i->second == 0)
00112     {
00113       mDatabase.erase(i);
00114     }
00115   }
00116 
00117   mLockedRecords.erase(aor);
00118   mRecordUnlocked.broadcast();
00119 }
00120 
00121 RegistrationPersistenceManager::update_status_t 
00122 InMemoryRegistrationDatabase::updateContact(const resip::Uri& aor, 
00123                                              const ContactInstanceRecord& rec) 
00124 {
00125   ContactList *contactList = 0;
00126 
00127   {
00128     Lock g(mDatabaseMutex);
00129 
00130     database_map_t::iterator i;
00131     i = mDatabase.find(aor);
00132     if (i == mDatabase.end() || i->second == 0)
00133     {
00134       contactList = new ContactList();
00135       mDatabase[aor] = contactList;
00136     }
00137     else
00138     {
00139       contactList = i->second;
00140     }
00141 
00142   }
00143 
00144   assert(contactList);
00145 
00146   ContactList::iterator j;
00147 
00148   // See if the contact is already present. We use URI matching rules here.
00149   for (j = contactList->begin(); j != contactList->end(); j++)
00150   {
00151     if (*j == rec)
00152     {
00153       *j=rec;
00154       return CONTACT_UPDATED;
00155     }
00156   }
00157 
00158   // This is a new contact, so we add it to the list.
00159   contactList->push_back(rec);
00160   return CONTACT_CREATED;
00161 }
00162 
00163 void 
00164 InMemoryRegistrationDatabase::removeContact(const Uri& aor, 
00165                                              const ContactInstanceRecord& rec)
00166 {
00167   ContactList *contactList = 0;
00168 
00169   {
00170     Lock g(mDatabaseMutex);
00171 
00172     database_map_t::iterator i;
00173     i = mDatabase.find(aor);
00174     if (i == mDatabase.end() || i->second == 0)
00175     {
00176       return;
00177     }
00178     contactList = i->second;
00179   }
00180 
00181   ContactList::iterator j;
00182 
00183   // See if the contact is present. We use URI matching rules here.
00184   for (j = contactList->begin(); j != contactList->end(); j++)
00185   {
00186     if (*j == rec)
00187     {
00188       contactList->erase(j);
00189       if (contactList->empty())
00190       {
00191         removeAor(aor);
00192       }
00193       return;
00194     }
00195   }
00196 }
00197 
00198 void
00199 InMemoryRegistrationDatabase::getContacts(const Uri& aor, ContactList& container)
00200 {
00201   Lock g(mDatabaseMutex);
00202   database_map_t::iterator i = findNotExpired(aor);
00203   if (i == mDatabase.end() || i->second == 0)
00204   {
00205       container.clear();
00206       return;
00207   }
00208    container = *(i->second);
00209 }
00210 
00211 class RemoveIfExpired
00212 {
00213 protected:
00214     UInt64 now;
00215 public:
00216     RemoveIfExpired()
00217     {
00218        now = Timer::getTimeSecs();
00219     }
00220     bool operator () (const ContactInstanceRecord& rec)
00221     {
00222        return expired(rec);
00223     }
00224     bool expired(const ContactInstanceRecord& rec)
00225     {
00226       if(rec.mRegExpires <= now) 
00227       {
00228          DebugLog(<< "ContactInstanceRecord expired: " << rec.mContact);
00229          return true;
00230       }
00231       return false;
00232     }
00233 };
00234 
00235 bool expired(const ContactInstanceRecord& rec)
00236 {
00237    RemoveIfExpired rei;
00238    return rei.expired(rec);
00239 }
00240 
00241 InMemoryRegistrationDatabase::database_map_t::iterator
00242 InMemoryRegistrationDatabase::findNotExpired(const Uri& aor) 
00243 {
00244    database_map_t::iterator i;
00245    i = mDatabase.find(aor);
00246    if (i == mDatabase.end() || i->second == 0) 
00247    {
00248       return i;
00249    }
00250    if(mCheckExpiry)
00251    {
00252       ContactList *contacts = i->second;
00253 #ifdef __SUNPRO_CC
00254       contacts->remove_if(expired);
00255 #else
00256       contacts->remove_if(RemoveIfExpired());
00257 #endif
00258    }
00259    return i;
00260 }
00261 
00262 /* ====================================================================
00263  * The Vovida Software License, Version 1.0 
00264  * 
00265  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00266  * 
00267  * Redistribution and use in source and binary forms, with or without
00268  * modification, are permitted provided that the following conditions
00269  * are met:
00270  * 
00271  * 1. Redistributions of source code must retain the above copyright
00272  *    notice, this list of conditions and the following disclaimer.
00273  * 
00274  * 2. Redistributions in binary form must reproduce the above copyright
00275  *    notice, this list of conditions and the following disclaimer in
00276  *    the documentation and/or other materials provided with the
00277  *    distribution.
00278  * 
00279  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00280  *    and "Vovida Open Communication Application Library (VOCAL)" must
00281  *    not be used to endorse or promote products derived from this
00282  *    software without prior written permission. For written
00283  *    permission, please contact vocal@vovida.org.
00284  *
00285  * 4. Products derived from this software may not be called "VOCAL", nor
00286  *    may "VOCAL" appear in their name, without prior written
00287  *    permission of Vovida Networks, Inc.
00288  * 
00289  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00290  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00291  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00292  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00293  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00294  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00295  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00296  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00297  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00298  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00299  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00300  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00301  * DAMAGE.
00302  * 
00303  * ====================================================================
00304  * 
00305  * This software consists of voluntary contributions made by Vovida
00306  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00307  * Inc.  For more information on Vovida Networks, Inc., please see
00308  * <http://www.vovida.org/>.
00309  *
00310  */