From: Scott Cantor Date: Wed, 24 Jan 2007 22:51:14 +0000 (+0000) Subject: Add version tracking to storage service API. X-Git-Tag: 1.0-alpha1~112 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=commitdiff_plain;h=5325bc9b7b426ae67a4b4511c9604ad61fb9ddf3 Add version tracking to storage service API. --- diff --git a/xmltooling/impl/MemoryStorageService.cpp b/xmltooling/impl/MemoryStorageService.cpp index a7e8768..4e5bef8 100644 --- a/xmltooling/impl/MemoryStorageService.cpp +++ b/xmltooling/impl/MemoryStorageService.cpp @@ -41,18 +41,18 @@ namespace xmltooling { virtual ~MemoryStorageService(); void createString(const char* context, const char* key, const char* value, time_t expiration); - bool readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL); - bool updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0); + int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0); + int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0); bool deleteString(const char* context, const char* key); void createText(const char* context, const char* key, const char* value, time_t expiration) { return createString(context, key, value, expiration); } - bool readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL) { - return readString(context, key, pvalue, pexpiration); + int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) { + return readString(context, key, pvalue, pexpiration, version); } - bool updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0) { - return updateString(context, key, value, expiration); + int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) { + return updateString(context, key, value, expiration, version); } bool deleteText(const char* context, const char* key) { return deleteString(context, key); @@ -68,10 +68,11 @@ namespace xmltooling { void cleanup(); struct XMLTOOL_DLLLOCAL Record { - Record() : expiration(0) {} - Record(string s, time_t t) : data(s), expiration(t) {} + Record() : expiration(0), version(1) {} + Record(const string& s, time_t t) : data(s), expiration(t), version(1) {} string data; time_t expiration; + int version; }; struct XMLTOOL_DLLLOCAL Context { @@ -158,15 +159,14 @@ void MemoryStorageService::cleanup() #ifdef _DEBUG NDC ndc("cleanup"); #endif - - Mutex* mutex = Mutex::create(); + auto_ptr mutex(Mutex::create()); mutex->lock(); m_log.info("cleanup thread started...running every %d seconds", m_cleanupInterval); while (!shutdown) { - shutdown_wait->timedwait(mutex, m_cleanupInterval); + shutdown_wait->timedwait(mutex.get(), m_cleanupInterval); if (shutdown) break; @@ -182,7 +182,6 @@ void MemoryStorageService::cleanup() m_log.info("cleanup thread finished"); mutex->unlock(); - delete mutex; Thread::exit(NULL); } @@ -242,24 +241,26 @@ void MemoryStorageService::createString(const char* context, const char* key, co m_log.debug("inserted record (%s) in context (%s)", key, context); } -bool MemoryStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration) +int MemoryStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) { Context& ctx = getContext(context); SharedLock wrapper(ctx.m_lock); map::iterator i=ctx.m_dataMap.find(key); if (i==ctx.m_dataMap.end()) - return false; + return 0; else if (time(NULL) >= i->second.expiration) - return false; + return 0; + if (i->second.version == version) + return version; // nothing's changed, so just echo back the version if (pvalue) *pvalue = i->second.data; if (pexpiration) *pexpiration = i->second.expiration; - return true; + return i->second.version; } -bool MemoryStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration) +int MemoryStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) { Context& ctx = getContext(context); @@ -269,12 +270,17 @@ bool MemoryStorageService::updateString(const char* context, const char* key, co map::iterator i=ctx.m_dataMap.find(key); if (i==ctx.m_dataMap.end()) - return false; + return 0; else if (time(NULL) >= i->second.expiration) - return false; - - if (value) + return 0; + + if (version > 0 && version != i->second.version) + return -1; // caller's out of sync + + if (value) { i->second.data = value; + ++(i->second.version); + } if (expiration && expiration != i->second.expiration) { // Update secondary map. @@ -291,7 +297,7 @@ bool MemoryStorageService::updateString(const char* context, const char* key, co } m_log.debug("updated record (%s) in context (%s)", key, context); - return true; + return i->second.version; } bool MemoryStorageService::deleteString(const char* context, const char* key) diff --git a/xmltooling/signature/OpenSSLCredentialResolver.h b/xmltooling/signature/OpenSSLCredentialResolver.h index 77c2b95..6121385 100644 --- a/xmltooling/signature/OpenSSLCredentialResolver.h +++ b/xmltooling/signature/OpenSSLCredentialResolver.h @@ -42,7 +42,7 @@ namespace xmlsignature { /** * Attaches credentials to an OpenSSL SSL context object. - * The resolver is unlockable after attachment. + * The resolver MUST be unlockable after attachment. * * @param ctx an SSL context */ diff --git a/xmltooling/util/StorageService.h b/xmltooling/util/StorageService.h index c96021b..1b2c141 100644 --- a/xmltooling/util/StorageService.h +++ b/xmltooling/util/StorageService.h @@ -59,16 +59,21 @@ namespace xmltooling { /** * Returns an existing "short" record from the storage service. + * + *

The version parameter can be set for "If-Modified-Since" semantics. * * @param context a storage context label * @param key null-terminated unique key of up to 255 bytes * @param pvalue location in which to return the record value * @param pexpiration location in which to return the expiration timestamp - * @return true iff a valid record exists and was returned + * @param version if > 0, only copy back data if newer than supplied version + * @return the version of the record read back, or 0 if no record exists * * @throws IOException raised if errors occur in the read process */ - virtual bool readString(const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL)=0; + virtual int readString( + const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL, int version=0 + )=0; /** * Updates an existing "short" record in the storage service. @@ -77,11 +82,15 @@ namespace xmltooling { * @param key null-terminated unique key of up to 255 bytes * @param value null-terminated value of up to 255 bytes to store, or NULL to leave alone * @param expiration a new expiration timestamp, or 0 to leave alone - * @return true iff the record exists and was updated + * @param version if > 0, only update if the current version matches this value + * @return the version of the record after update, 0 if no record exists, or -1 if the version + * parameter is non-zero and does not match the current version before update (so the caller is out of sync) * * @throws IOException raised if errors occur in the update process */ - virtual bool updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0)=0; + virtual int updateString( + const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0 + )=0; /** * Deletes an existing "short" record from the storage service. @@ -108,16 +117,21 @@ namespace xmltooling { /** * Returns an existing "long" record from the storage service. + * + *

The version parameter can be set for "If-Modified-Since" semantics. * * @param context a storage context label * @param key null-terminated unique key of up to 255 bytes * @param pvalue location in which to return the record value * @param pexpiration location in which to return the expiration timestamp - * @return true iff a valid record exists and was returned + * @param version if > 0, only copy back data if newer than supplied version + * @return the version of the record read back, or 0 if no record exists * * @throws IOException raised if errors occur in the read process */ - virtual bool readText(const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL)=0; + virtual int readText( + const char* context, const char* key, std::string* pvalue=NULL, time_t* pexpiration=NULL, int version=0 + )=0; /** * Updates an existing "long" record in the storage service. @@ -126,11 +140,15 @@ namespace xmltooling { * @param key null-terminated unique key of up to 255 bytes * @param value null-terminated value of arbitrary length to store, or NULL to leave alone * @param expiration a new expiration timestamp, or 0 to leave alone - * @return true iff the record exists and was updated + * @param version if > 0, only update if the current version matches this value + * @return the version of the record after update, 0 if no record exists, or -1 if the version + * parameter is non-zero and does not match the current version before update (so the caller is out of sync) * * @throws IOException raised if errors occur in the update process */ - virtual bool updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0)=0; + virtual int updateText( + const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0 + )=0; /** * Deletes an existing "long" record from the storage service.