Adjust default cache timeout based on cache subclass.
[shibboleth/sp.git] / shibsp / impl / RemotedSessionCache.cpp
index 51028ac..6f2d8cc 100644 (file)
@@ -31,7 +31,6 @@
 \r
 #include <ctime>\r
 #include <sstream>\r
-#include <log4cpp/Category.hh>\r
 #include <xmltooling/XMLToolingConfig.h>\r
 #include <xmltooling/util/DateTime.h>\r
 #include <xmltooling/util/NDC.h>\r
@@ -39,7 +38,6 @@
 \r
 using namespace shibsp;\r
 using namespace xmltooling;\r
-using namespace log4cpp;\r
 using namespace std;\r
 \r
 namespace shibsp {\r
@@ -63,7 +61,7 @@ namespace shibsp {
         ~RemotedSession() {\r
             delete m_lock;\r
             m_obj.destroy();\r
-            for_each(m_attributes.begin(), m_attributes.end(), cleanup_pair<string,Attribute>());\r
+            for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<Attribute>());\r
         }\r
         \r
         Lockable* lock() {\r
@@ -74,6 +72,9 @@ namespace shibsp {
             m_lock->unlock();\r
         }\r
 \r
+        const char* getID() const {\r
+            return m_obj.name();\r
+        }\r
         const char* getApplicationID() const {\r
             return m_obj["application_id"].string();\r
         }\r
@@ -83,6 +84,9 @@ namespace shibsp {
         const char* getEntityID() const {\r
             return m_obj["entity_id"].string();\r
         }\r
+        const char* getProtocol() const {\r
+            return m_obj["protocol"].string();\r
+        }\r
         const char* getAuthnInstant() const {\r
             return m_obj["authn_instant"].string();\r
         }\r
@@ -95,11 +99,23 @@ namespace shibsp {
         const char* getAuthnContextDeclRef() const {\r
             return m_obj["authncontext_decl"].string();\r
         }\r
-        const multimap<string,Attribute*>& getAttributes() const {\r
+        const vector<Attribute*>& getAttributes() const {\r
             if (m_attributes.empty())\r
                 unmarshallAttributes();\r
             return m_attributes;\r
         }\r
+        const multimap<string,const Attribute*>& getIndexedAttributes() const {\r
+            if (m_attributeIndex.empty()) {\r
+                if (m_attributes.empty())\r
+                    unmarshallAttributes();\r
+                for (vector<Attribute*>::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a) {\r
+                    const vector<string>& aliases = (*a)->getAliases();\r
+                    for (vector<string>::const_iterator alias = aliases.begin(); alias != aliases.end(); ++alias)\r
+                        m_attributeIndex.insert(make_pair(*alias, *a));\r
+                }\r
+            }\r
+            return m_attributeIndex;\r
+        }\r
         const vector<const char*>& getAssertionIDs() const {\r
             if (m_ids.empty()) {\r
                 DDF ids = m_obj["assertions"];\r
@@ -121,7 +137,8 @@ namespace shibsp {
 \r
         int m_version;\r
         mutable DDF m_obj;\r
-        mutable multimap<string,Attribute*> m_attributes;\r
+        mutable vector<Attribute*> m_attributes;\r
+        mutable multimap<string,const Attribute*> m_attributeIndex;\r
         mutable vector<const char*> m_ids;\r
         time_t m_expires,m_lastAccess;\r
         RemotedCache* m_cache;\r
@@ -135,7 +152,7 @@ namespace shibsp {
         ~RemotedCache();\r
     \r
         Session* find(const char* key, const Application& application, const char* client_addr=NULL, time_t* timeout=NULL);\r
-        void remove(const char* key, const Application& application, const char* client_addr);\r
+        void remove(const char* key, const Application& application);\r
         \r
         void cleanup();\r
     \r
@@ -166,7 +183,7 @@ void RemotedSession::unmarshallAttributes() const
     while (!attr.isnull()) {\r
         try {\r
             attribute = Attribute::unmarshall(attr);\r
-            m_attributes.insert(make_pair(attribute->getId(),attribute));\r
+            m_attributes.push_back(attribute);\r
             if (m_cache->m_log.isDebugEnabled())\r
                 m_cache->m_log.debug("unmarshalled attribute (ID: %s) with %d value%s",\r
                     attribute->getId(), attr.first().integer(), attr.first().integer()!=1 ? "s" : "");\r
@@ -184,7 +201,7 @@ void RemotedSession::validate(const Application& application, const char* client
     // Basic expiration?\r
     time_t now = time(NULL);\r
     if (now > m_expires) {\r
-        m_cache->m_log.info("session expired (ID: %s)", m_obj.name());\r
+        m_cache->m_log.info("session expired (ID: %s)", getID());\r
         throw opensaml::RetryableProfileException("Your session has expired, and you must re-authenticate.");\r
     }\r
 \r
@@ -207,7 +224,7 @@ void RemotedSession::validate(const Application& application, const char* client
     DDF in("touch::"REMOTED_SESSION_CACHE"::SessionCache"), out;\r
     DDFJanitor jin(in);\r
     in.structure();\r
-    in.addmember("key").string(m_obj.name());\r
+    in.addmember("key").string(getID());\r
     in.addmember("version").integer(m_obj["version"].integer());\r
     if (*timeout) {\r
         // On 64-bit Windows, time_t doesn't fit in a long, so I'm using ISO timestamps.  \r
@@ -233,8 +250,9 @@ void RemotedSession::validate(const Application& application, const char* client
     if (out.isstruct()) {\r
         // We got an updated record back.\r
         m_ids.clear();\r
-        for_each(m_attributes.begin(), m_attributes.end(), cleanup_const_pair<string,Attribute>());\r
+        for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<Attribute>());\r
         m_attributes.clear();\r
+        m_attributeIndex.clear();\r
         m_obj.destroy();\r
         m_obj = out;\r
     }\r
@@ -243,7 +261,7 @@ void RemotedSession::validate(const Application& application, const char* client
 }\r
 \r
 RemotedCache::RemotedCache(const DOMElement* e)\r
-    : SessionCache(e), m_log(Category::getInstance(SHIBSP_LOGCAT".SessionCache")), m_root(e), m_lock(NULL), shutdown(false)\r
+    : SessionCache(e, 900), m_log(Category::getInstance(SHIBSP_LOGCAT".SessionCache")), m_root(e), m_lock(NULL), shutdown(false)\r
 {\r
     if (!SPConfig::getConfig().getServiceProvider()->getListenerService())\r
         throw ConfigurationException("RemotedCacheService requires a ListenerService, but none available.");\r
@@ -283,6 +301,7 @@ Session* RemotedCache::find(const char* key, const Application& application, con
         DDFJanitor jin(in);\r
         in.structure();\r
         in.addmember("key").string(key);\r
+        in.addmember("application_id").string(application.getId());\r
         if (timeout && *timeout) {\r
             // On 64-bit Windows, time_t doesn't fit in a long, so I'm using ISO timestamps.  \r
 #ifndef HAVE_GMTIME_R\r
@@ -349,14 +368,14 @@ Session* RemotedCache::find(const char* key, const Application& application, con
     }\r
     catch (...) {\r
         session->unlock();\r
-        remove(key, application, client_addr);\r
+        remove(key, application);\r
         throw;\r
     }\r
     \r
     return session;\r
 }\r
 \r
-void RemotedCache::remove(const char* key, const Application& application, const char* client_addr)\r
+void RemotedCache::remove(const char* key, const Application& application)\r
 {\r
     // Take care of local copy.\r
     dormant(key);\r
@@ -367,7 +386,6 @@ void RemotedCache::remove(const char* key, const Application& application, const
     in.structure();\r
     in.addmember("key").string(key);\r
     in.addmember("application_id").string(application.getId());\r
-    in.addmember("client_addr").string(client_addr);\r
     \r
     DDF out = application.getServiceProvider().getListenerService()->send(in);\r
     out.destroy();\r