aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-11-11 18:03:44 +0000
committerlloyd <[email protected]>2008-11-11 18:03:44 +0000
commit6a1e19928007c0047518e8e15b92bba116bf7a58 (patch)
tree70ce4ccb0f859884dac49895ebcff3e1d00b6b2e /src
parenta26685bf9feee9b9457bd1313b3943701aa37367 (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.h111
-rw-r--r--src/algo_factory/algo_factory.cpp30
-rw-r--r--src/algo_factory/algo_factory.h8
-rw-r--r--src/algo_factory/info.txt1
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>