Voreen - Volume Rendering Engine Voreen - Volume Rendering Engine
Voreen - Volume Rendering Engine Westfälische Wilhelms-Universität Münster
  • About
  • Gallery
  • Download
  • Documentation
  • Publications
  • Community

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List

include/voreen/core/io/cache.h

00001 /**********************************************************************
00002  *                                                                    *
00003  * Voreen - The Volume Rendering Engine                               *
00004  *                                                                    *
00005  * Copyright (C) 2005-2010 The Voreen Team. <http://www.voreen.org>   *
00006  *                                                                    *
00007  * This file is part of the Voreen software package. Voreen is free   *
00008  * software: you can redistribute it and/or modify it under the terms *
00009  * of the GNU General Public License version 2 as published by the    *
00010  * Free Software Foundation.                                          *
00011  *                                                                    *
00012  * Voreen is distributed in the hope that it will be useful,          *
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of     *
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the       *
00015  * GNU General Public License for more details.                       *
00016  *                                                                    *
00017  * You should have received a copy of the GNU General Public License  *
00018  * in the file "LICENSE.txt" along with this program.                 *
00019  * If not, see <http://www.gnu.org/licenses/>.                        *
00020  *                                                                    *
00021  * The authors reserve all rights not expressly granted herein. For   *
00022  * non-commercial academic use see the license exception specified in *
00023  * the file "LICENSE-academic.txt". To get information about          *
00024  * commercial licensing please contact the authors.                   *
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() { /* dtor has nothing to do */ }
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     // Do nothing if this cache is disabled in general or in particular,
00340     // or the parameters are bad.
00341     //
00342     if ((isEnabled() == false) || (processor == 0) || (port == 0))
00343         return 0;
00344 
00345     // 1. Check whether the cached data already exist in the local object map and
00346     // return them if so.
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         //std::cout << "find(): found object in local map!";
00354         cacheIndex_.incrementRefCounter(key);
00355         return (it->second)->object_;
00356     }
00357 
00358     // 2. If the data were not in the local object map, look up the cache index entry.
00359     // If the there is not even a cache index entry, the data are not cached at all
00360     // and 0 is returned.
00361     //
00362     const std::string filename = cacheIndex_.findFilename(processor, port, inportConfig);
00363     if (filename.empty() == true)
00364         return 0;
00365 
00366     // 3. Otherwise, if there is a cache index entry, load the concerned object and
00367     // store it in the local object map for future lookups.
00368     //
00369     T* object = loadObject(filename);
00370     if (object != 0) {
00371         //std::cout << "find(): found cache index entry for object!";
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     // Do nothing if caching is disabled in general or in particular, or if one of the
00381     // parameters is bad.
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         // try to find an entry for that processor and port with the current
00398         // configuration on the inports in the index of the cache
00399         //
00400         std::string filename = cacheIndex_.findFilename(processor, concernedPorts[i], inportConfig);
00401         bool requiresNewEntry = filename.empty();
00402 
00403         // save the object itself and add entry to the cache's index. if filename is not empty,
00404         // the file will be replaced. otherwise a new file will be created and the filename
00405         // which will be generated is retruned.
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             // cleanup cache
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         // add or replace the internal 'copy' of the object
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             //std::cout << "update(): replacing existing data...";
00429             delete (res.first)->second;
00430             (res.first)->second = new CacheObject<T>(object, false);
00431         }
00432     }
00433     return result;
00434 }
00435 
00436 // private methods
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         // 1. Erase the object from the local object map
00445         //
00446         objectMap_.erase(dumps[i].first);
00447 
00448         // 2. Delete the file from the cache's directory
00449         //
00450         std::string& file = dumps[i].second;
00451         //std::cout << "cleanup(): deleting file '" << file << "'...";
00452         tgt::FileSystem::deleteFile(file);
00453 
00454         // If file is a .dat file, also try to delete related .raw file
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 }   // namespace
00466 
00467 #endif
  • Getting Started
  • Video Tutorials
  • Build Instructions
  • Adding a Module
  • Programming Tutorials
  • API Documentation
  • FAQ
edit