Sirikata
|
00001 /* Sirikata Transfer -- Content Transfer management system 00002 * CacheMap.hpp 00003 * 00004 * Copyright (c) 2008, Patrick Reiter Horn 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 /* Created on: Jan 7, 2009 */ 00033 00034 #ifndef SIRIKATA_CacheMap_HPP__ 00035 #define SIRIKATA_CacheMap_HPP__ 00036 00037 #include "CachePolicy.hpp" 00038 #include "CacheLayer.hpp" 00039 #include <boost/thread.hpp> 00040 #include <boost/thread/shared_mutex.hpp> 00041 00042 namespace Sirikata { 00043 namespace Transfer { 00044 00049 class CacheMap : Noncopyable { 00050 public: 00051 typedef CacheLayer::CacheEntry *CacheData; 00052 00053 class read_iterator; 00054 class write_iterator; 00055 00056 private: 00057 typedef CachePolicy::Data *PolicyData; 00058 typedef std::pair<CacheData, std::pair<PolicyData, cache_usize_type> > MapEntry; 00059 typedef std::map<Fingerprint, MapEntry> MapClass; 00060 00061 MapClass mMap; 00062 boost::shared_mutex mMapLock; 00063 00064 CacheLayer *mOwner; 00065 CachePolicy *mPolicy; 00066 00067 inline void destroyCacheLayerEntry(const Fingerprint &id, const CacheData &data, cache_usize_type size) { 00068 mOwner->destroyCacheEntry(id, data, size); 00069 } 00070 00071 public: 00072 CacheMap(CacheLayer *owner, CachePolicy *policy) : 00073 mOwner(owner), mPolicy(policy) { 00074 } 00075 void setOwner(CacheLayer *owner) {//if you can't afford to initialize in initializer list 00076 mOwner=owner; 00077 } 00078 00079 ~CacheMap() { 00080 write_iterator clearIterator(*this); 00081 clearIterator.eraseAll(); 00082 } 00083 00093 inline bool alloc(cache_usize_type required, write_iterator &writer) { 00094 bool cachable = mPolicy->cachable(required); 00095 if (!cachable) { 00096 return false; 00097 } 00098 Fingerprint toDelete; 00099 while (mPolicy->nextItem(required, toDelete)) { 00100 writer.find(toDelete); 00101 writer.erase(); 00102 } 00103 return true; 00104 } 00105 00114 class read_iterator { 00115 CacheMap *mCachemap; 00116 boost::shared_lock<boost::shared_mutex> mLock; 00117 00118 MapClass *mMap; 00119 MapClass::iterator mIter; 00120 00121 public: 00123 read_iterator(CacheMap &m) 00124 : mCachemap(&m), mLock(m.mMapLock), 00125 mMap(&m.mMap), mIter(m.mMap.end()) { 00126 } 00127 00129 inline operator bool () const{ 00130 return (mIter != mMap->end()); 00131 } 00132 00133 inline bool iterate () { 00134 if (mIter == mMap->end()) { 00135 mIter = mMap->begin(); 00136 } else { 00137 ++mIter; 00138 } 00139 return (mIter != mMap->end()); 00140 } 00141 00146 inline bool find(const Fingerprint &id) { 00147 mIter = mMap->find(id); 00148 return (bool)*this; 00149 } 00150 00152 inline CacheData operator* () const { 00153 return (*mIter).second.first; 00154 } 00155 00157 inline const Fingerprint &getId() const { 00158 return (*mIter).first; 00159 } 00160 00162 inline cache_usize_type getSize() const { 00163 return (*mIter).second.second.second; 00164 } 00165 00167 inline PolicyData getPolicyInfo() { 00168 return (*mIter).second.second.first; 00169 } 00170 00172 inline void use() { 00173 mCachemap->mPolicy->use(getId(), getPolicyInfo(), getSize()); 00174 } 00175 }; 00176 00185 class write_iterator : Noncopyable { 00186 CacheMap *mCachemap; 00187 boost::unique_lock<boost::shared_mutex> mLock; 00188 00189 MapClass *mMap; 00190 MapClass::iterator mIter; 00191 00192 public: 00194 write_iterator(CacheMap &m) 00195 : mCachemap(&m), mLock(m.mMapLock), 00196 mMap(&m.mMap), mIter(m.mMap.end()) { 00197 } 00198 00200 inline operator bool () const{ 00201 return (mIter != mMap->end()); 00202 } 00203 00208 bool find(const Fingerprint &id) { 00209 mIter = mMap->find(id); 00210 return (bool)*this; 00211 } 00212 00214 inline CacheData &operator* () { 00215 return (*mIter).second.first; 00216 } 00217 00219 inline const Fingerprint &getId() const { 00220 return (*mIter).first; 00221 } 00222 00224 inline cache_usize_type getSize() const { 00225 return (*mIter).second.second.second; 00226 } 00227 00229 inline PolicyData getPolicyInfo() { 00230 return (*mIter).second.second.first; 00231 } 00232 00234 inline void use() { 00235 mCachemap->mPolicy->use(getId(), getPolicyInfo(), getSize()); 00236 } 00237 00244 inline void update(cache_usize_type newSize) { 00245 cache_usize_type oldSize = getSize(); 00246 (*mIter).second.second.second = newSize; 00247 mCachemap->mPolicy->useAndUpdate(getId(), 00248 getPolicyInfo(), oldSize, newSize); 00249 } 00250 00257 void erase() { 00258 mCachemap->mPolicy->destroy(getId(), getPolicyInfo(), getSize()); 00259 mCachemap->destroyCacheLayerEntry(getId(), (**this), getSize()); 00260 mMap->erase(mIter); 00261 mIter = mMap->end(); 00262 } 00263 00267 void eraseAll() { 00268 for (mIter = mMap->begin(); mIter != mMap->end(); ++mIter) { 00269 mCachemap->mPolicy->destroy(getId(), getPolicyInfo(), getSize()); 00270 mCachemap->destroyCacheLayerEntry(getId(), (**this), getSize()); 00271 } 00272 mMap->clear(); 00273 mIter = mMap->end(); 00274 } 00275 00288 bool insert(const Fingerprint &id, cache_usize_type size) { 00289 std::pair<MapClass::iterator, bool> ins= 00290 mMap->insert(MapClass::value_type(id, 00291 MapEntry(CacheData(), std::pair<PolicyData, cache_usize_type>(PolicyData(), size)))); 00292 mIter = ins.first; 00293 00294 if (ins.second) { 00295 (*mIter).second.second.first = mCachemap->mPolicy->create(id, size); 00296 } 00297 return ins.second; 00298 } 00299 }; 00300 00301 friend class read_iterator; 00302 friend class write_iterator; 00303 00304 }; 00305 00306 } 00307 } 00308 00309 #endif /* SIRIKATA_CacheMap_HPP__ */