00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef VRN_CACHE_H
00029 #define VRN_CACHE_H
00030
00031 #include "voreen/core/io/cacheindex.h"
00032 #include "voreen/core/ports/allports.h"
00033 #include "voreen/core/datastructures/volume/volumehandle.h"
00034 #include "voreen/core/voreenapplication.h"
00035 #include "tgt/filesystem.h"
00036 #include <typeinfo>
00037
00038 namespace voreen {
00039
00040 class Processor;
00041
00051 class CacheBase {
00052 public:
00065 CacheBase(const std::string& cachedObjectsClassName, const std::type_info& assignedPortType);
00066
00067 virtual ~CacheBase() { }
00068
00072 const std::type_info& getAssignedPortType() const;
00073
00078 std::vector<Port*> getCacheConcernedOutports(Processor* const processor) const;
00079
00084 const std::string& getCachedObjectsClassName() const;
00085
00094 std::string getProcessorsInportConfig(const Processor* processor) const;
00095
00100 bool isCompatible(Processor* const processor) const;
00101
00108 bool isEnabled() const;
00109
00115 void setEnabled(const bool enable);
00116
00122 static bool isCachingEnabled() { return cachingEnabled_; }
00123
00129 static void setCachingEnabled(const bool enable) { cachingEnabled_ = enable; }
00130
00131 protected:
00132 virtual std::string portContentToString(Port* const port) const = 0;
00133
00134 protected:
00135 const std::type_info& assignedPortType_;
00136 const std::string cachedObjectsClassName_;
00137 bool isEnabled_;
00138
00139 private:
00140 static bool cachingEnabled_;
00141 };
00142
00143
00144
00149 template<typename S>
00150 struct CacheObject {
00151 explicit CacheObject(S* object, const bool originsCache)
00152 : object_(object), originsCache_(originsCache)
00153 {
00154 }
00155
00156 ~CacheObject() {
00157 if (originsCache_ == true)
00158 delete object_;
00159 }
00160
00161 S* object_;
00162 bool originsCache_;
00163 };
00164
00168 template<>
00169 struct CacheObject<int> {
00170 explicit CacheObject(int object, const bool)
00171 : object_(object)
00172 {
00173 }
00174
00175 ~CacheObject() {}
00176
00177 int object_;
00178 };
00179
00180
00181
00193 template<typename T>
00194 class Cache : public CacheBase {
00195 public:
00199 Cache(const std::string& cachedObjectsClassName, const std::type_info& assignedPortType);
00200
00207 virtual ~Cache();
00208
00224 T* find(Processor* const processor, Port* const port);
00225
00242 bool update(Processor* const processor);
00243
00244 protected:
00251 virtual T* getPortData(Port* const port) const {
00252 GenericPort<T>* gp = dynamic_cast< GenericPort<T>* >(port);
00253 if(gp)
00254 return gp->getData();
00255 else
00256 return 0;
00257 }
00258
00267 virtual T* loadObject(const std::string& filename) const = 0;
00268
00289 virtual std::string saveObject(T* object, const std::string& directory,
00290 const std::string& filename) = 0;
00291
00292 protected:
00298 typedef std::map<std::string, CacheObject<T>* > ObjectMap;
00299 ObjectMap objectMap_;
00300
00301 CacheIndex& cacheIndex_;
00302
00303 private:
00310 void cleanup();
00311
00312 private:
00313 static const std::string loggerCat_;
00314 const std::string cacheFolder_;
00315 };
00316
00317 template<typename T>
00318 Cache<T>::Cache(const std::string& cachedObjectsClassName, const std::type_info& assignedPortType)
00319 : CacheBase(cachedObjectsClassName, assignedPortType),
00320 objectMap_(),
00321 cacheIndex_(CacheIndex::getInstance()),
00322 cacheFolder_(VoreenApplication::app()->getCachePath())
00323 {
00324 }
00325
00326 template<typename T>
00327 Cache<T>::~Cache() {
00328 typename Cache<T>::ObjectMap::iterator it = objectMap_.begin();
00329 for ( ; it != objectMap_.end(); ++it) {
00330 delete it->second;
00331 it->second = 0;
00332 }
00333 objectMap_.clear();
00334 }
00335
00336 template<typename T>
00337 T* Cache<T>::find(Processor* const processor, Port* const port)
00338 {
00339
00340
00341
00342 if ((isEnabled() == false) || (processor == 0) || (port == 0))
00343 return 0;
00344
00345
00346
00347
00348 std::string inportConfig = getProcessorsInportConfig(processor);
00349 CacheIndex::IndexKey key = CacheIndex::generateCacheIndexKey(processor, port, inportConfig);
00350 std::string keyStr = key.first + "." + key.second;
00351 typename Cache<T>::ObjectMap::const_iterator it = objectMap_.find(keyStr);
00352 if (it != objectMap_.end()) {
00353
00354 cacheIndex_.incrementRefCounter(key);
00355 return (it->second)->object_;
00356 }
00357
00358
00359
00360
00361
00362 const std::string filename = cacheIndex_.findFilename(processor, port, inportConfig);
00363 if (filename.empty() == true)
00364 return 0;
00365
00366
00367
00368
00369 T* object = loadObject(filename);
00370 if (object != 0) {
00371
00372 std::pair<typename Cache<T>::ObjectMap::iterator, bool> res =
00373 objectMap_.insert(std::make_pair(keyStr, new CacheObject<T>(object, true)));
00374 }
00375 return object;
00376 }
00377
00378 template<typename T>
00379 bool Cache<T>::update(Processor* const processor) {
00380
00381
00382
00383 if ((isEnabled() == false) || (processor == 0))
00384 return false;
00385
00386 std::string inportConfig = getProcessorsInportConfig(processor);
00387 if (inportConfig.empty() == true)
00388 return false;
00389
00390 std::vector<Port*> concernedPorts = getCacheConcernedOutports(processor);
00391 bool result = (! concernedPorts.empty());
00392 for (size_t i = 0; i < concernedPorts.size(); ++i) {
00393 T* object = getPortData(concernedPorts[i]);
00394 if (object == 0)
00395 continue;
00396
00397
00398
00399
00400 std::string filename = cacheIndex_.findFilename(processor, concernedPorts[i], inportConfig);
00401 bool requiresNewEntry = filename.empty();
00402
00403
00404
00405
00406
00407 filename = saveObject(object, cacheFolder_, filename);
00408 result = (result && (! filename.empty()));
00409 std::string key;
00410 if ((result == true) && (requiresNewEntry == true)) {
00411 key = cacheIndex_.insert(processor, concernedPorts[i], cachedObjectsClassName_,
00412 inportConfig, filename);
00413
00414 cleanup();
00415 }
00416
00417 if ((key.empty() == true) && (requiresNewEntry == true)) {
00418 LFATAL("update(): Insertion of cache index failed!");
00419 return false;
00420 }
00421
00422
00423
00424 std::pair<typename Cache<T>::ObjectMap::iterator, bool> res =
00425 objectMap_.insert(std::make_pair(key, new CacheObject<T>(object, false)));
00426
00427 if (res.second == false) {
00428
00429 delete (res.first)->second;
00430 (res.first)->second = new CacheObject<T>(object, false);
00431 }
00432 }
00433 return result;
00434 }
00435
00436
00437
00438
00439 template<typename T>
00440 void Cache<T>::cleanup() {
00441 std::vector<std::pair<std::string, std::string> > dumps = cacheIndex_.cleanup();
00442 for (size_t i = 0; i < dumps.size(); ++i) {
00443
00444
00445
00446 objectMap_.erase(dumps[i].first);
00447
00448
00449
00450 std::string& file = dumps[i].second;
00451
00452 tgt::FileSystem::deleteFile(file);
00453
00454
00455
00456 if (tgt::FileSystem::fileExtension(file) == "dat") {
00457 file.replace(file.size() - 3, 3, "raw");
00458 tgt::FileSystem::deleteFile(file);
00459 }
00460 }
00461 }
00462
00463 template<typename T> const std::string Cache<T>::loggerCat_("Cache<T>");
00464
00465 }
00466
00467 #endif