diff options
author | lloyd <[email protected]> | 2008-11-11 18:03:44 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-11-11 18:03:44 +0000 |
commit | 6a1e19928007c0047518e8e15b92bba116bf7a58 (patch) | |
tree | 70ce4ccb0f859884dac49895ebcff3e1d00b6b2e /src | |
parent | a26685bf9feee9b9457bd1313b3943701aa37367 (diff) |
Add a new cache at the level of Algorithm_Factory. Intent is to replace
the caches included in the Engines, allowing faster search/query along
and making the Engine implementations mostly or entirely stateless, also
removing the need for a two-phase initialization there.
Stil buggy + incomplete.
Diffstat (limited to 'src')
-rw-r--r-- | src/algo_factory/algo_cache.h | 111 | ||||
-rw-r--r-- | src/algo_factory/algo_factory.cpp | 30 | ||||
-rw-r--r-- | src/algo_factory/algo_factory.h | 8 | ||||
-rw-r--r-- | src/algo_factory/info.txt | 1 |
4 files changed, 149 insertions, 1 deletions
diff --git a/src/algo_factory/algo_cache.h b/src/algo_factory/algo_cache.h new file mode 100644 index 000000000..ab6778d14 --- /dev/null +++ b/src/algo_factory/algo_cache.h @@ -0,0 +1,111 @@ +/** +* An algorithm cache (used by Algorithm_Factory) +*/ + +#ifndef BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ +#define BOTAN_ALGORITHM_CACHE_TEMPLATE_H__ + +#include <botan/scan_name.h> +#include <botan/mutex.h> +#include <stdexcept> +#include <map> +#include <string> + +namespace Botan { + +template<typename T> +class Algorithm_Cache + { + public: + const T* get(const SCAN_Name& request); + void add(T* algo, const std::string& provider); + + Algorithm_Cache(Mutex* m) : mutex(m) {} + ~Algorithm_Cache(); + private: + Mutex* mutex; + std::map<std::string, std::map<std::string, T*> > algorithms; + typedef typename std::map<std::string, std::map<std::string, T*> >::iterator algorithms_iterator; + typedef typename std::map<std::string, T*>::iterator provider_iterator; + }; + +/** +* Look for an algorithm implementation in the cache +*/ +template<typename T> +const T* Algorithm_Cache<T>::get(const SCAN_Name& request) + { + Mutex_Holder lock(mutex); + + algorithms_iterator algo = algorithms.find(request.as_string()); + + if(algo == algorithms.end()) + return 0; + + const std::string requested_provider = request.providers_string(); + + if(requested_provider != "") + { + provider_iterator provider = algo->second.find(requested_provider); + + if(provider != algo->second.end()) + return provider->second; + } + else // no specific provider requested: pick one + { + provider_iterator provider = algo->second.begin(); + + while(provider != algo->second.end()) + ++provider; + + provider = algo->second.begin(); + // @fixme: Just picks the lexicographically first one + if(provider != algo->second.end()) + return provider->second; + } + + return 0; // cache miss + } + +/** +* Add an implementation to the cache +*/ +template<typename T> +void Algorithm_Cache<T>::add(T* algo, const std::string& provider) + { + if(!algo) + return; + + Mutex_Holder lock(mutex); + + delete algorithms[algo->name()][provider]; + algorithms[algo->name()][provider] = algo; + } + +/** +* Algorithm_Cache<T> Destructor +*/ +template<typename T> +Algorithm_Cache<T>::~Algorithm_Cache() + { + algorithms_iterator algo = algorithms.begin(); + + while(algo != algorithms.end()) + { + provider_iterator provider = algo->second.begin(); + + while(provider != algo->second.end()) + { + delete provider->second; + ++provider; + } + + ++algo; + } + + delete mutex; + } + +} + +#endif diff --git a/src/algo_factory/algo_factory.cpp b/src/algo_factory/algo_factory.cpp index b8c428432..1f49a0d48 100644 --- a/src/algo_factory/algo_factory.cpp +++ b/src/algo_factory/algo_factory.cpp @@ -17,6 +17,13 @@ Algorithm Factory namespace Botan { +Algorithm_Factory::Algorithm_Factory(Mutex_Factory& mf) : + mutex_factory(mf), + hash_cache(mf.make()) + { + + } + /** * Delete all engines */ @@ -176,6 +183,7 @@ void Algorithm_Factory::add_stream_cipher(StreamCipher* hash) const HashFunction* Algorithm_Factory::prototype_hash_function(const SCAN_Name& request) { +#if 1 for(u32bit i = 0; i != engines.size(); ++i) { if(request.provider_allowed(engines[i]->provider_name())) @@ -189,6 +197,28 @@ Algorithm_Factory::prototype_hash_function(const SCAN_Name& request) } return 0; +#else + const HashFunction* cache_hit = hash_cache.get(request); + if(cache_hit) + return cache_hit; + + // Search for all providers of this algorithm and add them to the cache + for(u32bit i = 0; i != engines.size(); ++i) + { + const std::string provider = engines[i]->provider_name(); + HashFunction* impl = engines[i]->find_hash(request, *this); + + if(impl) + hash_cache.add(impl, provider); + } + + /* Now try the cache search again (if the providers don't match up + with ones that exist in this build, this might still fail and + return 0). + */ + + return hash_cache.get(request); +#endif } /** diff --git a/src/algo_factory/algo_factory.h b/src/algo_factory/algo_factory.h index f29683b79..2bbfde7d1 100644 --- a/src/algo_factory/algo_factory.h +++ b/src/algo_factory/algo_factory.h @@ -6,13 +6,18 @@ #ifndef BOTAN_ALGORITHM_FACTORY_H__ #define BOTAN_ALGORITHM_FACTORY_H__ +#include <botan/algo_cache.h> #include <botan/scan_name.h> #include <botan/mutex.h> #include <string> #include <vector> +#include <map> namespace Botan { +/** +* Forward declarations (don't need full definitions here) +*/ class BlockCipher; class StreamCipher; class HashFunction; @@ -24,7 +29,7 @@ class MessageAuthenticationCode; class BOTAN_DLL Algorithm_Factory { public: - Algorithm_Factory(Mutex_Factory& mf) : mutex_factory(mf) {} + Algorithm_Factory(Mutex_Factory& mf); ~Algorithm_Factory(); void add_engine(class Engine*); @@ -68,6 +73,7 @@ class BOTAN_DLL Algorithm_Factory class Engine* get_engine_n(u32bit) const; std::vector<class Engine*> engines; + Algorithm_Cache<HashFunction> hash_cache; }; } diff --git a/src/algo_factory/info.txt b/src/algo_factory/info.txt index f26b09566..34f2a94cc 100644 --- a/src/algo_factory/info.txt +++ b/src/algo_factory/info.txt @@ -11,4 +11,5 @@ utils <add> algo_factory.cpp algo_factory.h +algo_cache.h </add> |