1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_IMAGE_CACHE_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_IMAGE_CACHE_H 18 19 #include <algorithm> 20 #include <list> 21 #include <mutex> 22 #include <shared_mutex> 23 #include <unordered_map> 24 #include <vector> 25 26 #include "base/log/log.h" 27 #include "base/memory/ace_type.h" 28 #include "base/utils/macros.h" 29 30 namespace OHOS::Ace { 31 32 struct CachedImage; 33 class ImageObject; 34 template<typename T> 35 struct CacheNode { CacheNodeCacheNode36 CacheNode(const std::string& key, const T& obj) 37 : cacheKey(key), cacheObj(obj) 38 {} 39 std::string cacheKey; 40 T cacheObj; 41 }; 42 43 struct CachedImageData : public AceType { 44 DECLARE_ACE_TYPE(CachedImageData, AceType); 45 public: 46 CachedImageData() = default; 47 virtual ~CachedImageData() = default; 48 virtual size_t GetSize() = 0; 49 virtual const uint8_t* GetData() = 0; 50 }; 51 52 struct CacheImageDataNode { CacheImageDataNodeCacheImageDataNode53 CacheImageDataNode(const std::string& key, const RefPtr<CachedImageData>& imageData) 54 : imageDataKey(key), imageDataPtr(imageData) 55 {} 56 std::string imageDataKey; 57 RefPtr<CachedImageData> imageDataPtr; 58 }; 59 60 struct FileInfo { FileInfoFileInfo61 FileInfo(const std::string& path, size_t size, time_t time) 62 : filePath(path), fileSize(size), accessTime(time) 63 {} 64 65 // file information will be sort by access time. 66 bool operator<(const FileInfo& otherFile) const 67 { 68 return accessTime < otherFile.accessTime; 69 } 70 std::string filePath; 71 size_t fileSize; 72 time_t accessTime; 73 }; 74 75 class ACE_EXPORT ImageCache : public AceType { 76 DECLARE_ACE_TYPE(ImageCache, AceType); 77 78 public: 79 static RefPtr<ImageCache> Create(); 80 ImageCache() = default; 81 virtual ~ImageCache() = default; 82 void CacheImage(const std::string& key, const std::shared_ptr<CachedImage>& image); 83 std::shared_ptr<CachedImage> GetCacheImage(const std::string& key); 84 85 void CacheImageData(const std::string& key, const RefPtr<CachedImageData>& imageData); 86 RefPtr<CachedImageData> GetCacheImageData(const std::string& key); 87 88 void CacheImgObj(const std::string& key, const RefPtr<ImageObject>& imgObj); 89 RefPtr<ImageObject> GetCacheImgObj(const std::string& key); 90 91 static void SetCacheFileInfo(); 92 static void WriteCacheFile(const std::string& url, const void * const data, const size_t size); 93 SetCapacity(size_t capacity)94 void SetCapacity(size_t capacity) 95 { 96 LOGI("Set Capacity : %{public}d", static_cast<int32_t>(capacity)); 97 capacity_ = capacity; 98 } 99 SetDataCacheLimit(size_t sizeLimit)100 void SetDataCacheLimit(size_t sizeLimit) 101 { 102 LOGI("Set data size cache limit : %{public}d", static_cast<int32_t>(sizeLimit)); 103 dataSizeLimit_ = sizeLimit; 104 } 105 GetCapacity()106 size_t GetCapacity() const 107 { 108 return capacity_; 109 } 110 GetCachedImageCount()111 size_t GetCachedImageCount() const 112 { 113 std::lock_guard<std::mutex> lock(cacheListMutex_); 114 return cacheList_.size(); 115 } 116 SetImageCacheFilePath(const std::string & cacheFilePath)117 static void SetImageCacheFilePath(const std::string& cacheFilePath) 118 { 119 std::unique_lock<std::shared_mutex> lock(cacheFilePathMutex_); 120 if (cacheFilePath_.empty()) { 121 cacheFilePath_ = cacheFilePath; 122 } 123 } 124 GetImageCacheFilePath()125 static std::string GetImageCacheFilePath() 126 { 127 std::shared_lock<std::shared_mutex> lock(cacheFilePathMutex_); 128 return cacheFilePath_; 129 } 130 GetImageCacheFilePath(const std::string & url)131 static std::string GetImageCacheFilePath(const std::string& url) 132 { 133 std::shared_lock<std::shared_mutex> lock(cacheFilePathMutex_); 134 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) 135 return cacheFilePath_ + "/" + std::to_string(std::hash<std::string> {}(url)); 136 #elif defined(MAC_PLATFORM) 137 return "/tmp/" + std::to_string(std::hash<std::string> {}(url)); 138 #elif defined(WINDOWS_PLATFORM) 139 char *pathvar; 140 pathvar = getenv("TEMP"); 141 if (!pathvar) { 142 return std::string("C:\\Windows\\Temp") + "\\" + std::to_string(std::hash<std::string> {}(url)); 143 } 144 return std::string(pathvar) + "\\" + std::to_string(std::hash<std::string> {}(url)); 145 #endif 146 } 147 SetCacheFileLimit(size_t cacheFileLimit)148 static void SetCacheFileLimit(size_t cacheFileLimit) 149 { 150 LOGI("Set file cache limit size : %{public}d", static_cast<int32_t>(cacheFileLimit)); 151 cacheFileLimit_ = cacheFileLimit; 152 } 153 SetClearCacheFileRatio(float clearRatio)154 static void SetClearCacheFileRatio(float clearRatio) 155 { 156 // clearRatio must in (0, 1]. 157 if (clearRatio < 0) { 158 clearRatio = 0.1f; 159 } else if (clearRatio > 1) { 160 clearRatio = 1.0f; 161 } 162 clearCacheFileRatio_ = clearRatio; 163 } 164 165 static bool GetFromCacheFile(const std::string& filePath); 166 167 virtual void Clear() = 0; 168 169 virtual RefPtr<CachedImageData> GetDataFromCacheFile(const std::string& filePath) = 0; 170 171 static void Purge(); 172 173 protected: 174 static void ClearCacheFile(const std::vector<std::string>& removeFiles); 175 176 template<typename T> 177 static void CacheWithCountLimitLRU( 178 const std::string& key, 179 const T& cacheObj, 180 std::list<CacheNode<T>>& cacheList, 181 std::unordered_map<std::string, typename std::list<CacheNode<T>>::iterator>& cache, 182 const std::atomic<size_t>& capacity); 183 184 template<typename T> 185 static T GetCacheObjWithCountLimitLRU( 186 const std::string& key, 187 std::list<CacheNode<T>>& cacheList, 188 std::unordered_map<std::string, typename std::list<CacheNode<T>>::iterator>& cache); 189 190 static bool GetFromCacheFileInner(const std::string& filePath); 191 192 bool processImageDataCacheInner(size_t dataSize); 193 194 mutable std::mutex cacheListMutex_; 195 std::list<CacheNode<std::shared_ptr<CachedImage>>> cacheList_; 196 197 std::mutex imageCacheMutex_; 198 std::unordered_map<std::string, std::list<CacheNode<std::shared_ptr<CachedImage>>>::iterator> imageCache_; 199 200 std::atomic<size_t> capacity_ = 0; // by default memory cache can store 0 images. 201 202 mutable std::mutex dataCacheListMutex_; 203 std::list<CacheImageDataNode> dataCacheList_; 204 205 std::mutex imageDataCacheMutex_; 206 std::unordered_map<std::string, std::list<CacheImageDataNode>::iterator> imageDataCache_; 207 208 std::atomic<size_t> dataSizeLimit_ = 0; // by default, image data before decoded cache is 0 MB.; 209 std::atomic<size_t> curDataSize_ = 0; 210 211 std::mutex cacheImgObjListMutex_; 212 std::list<CacheNode<RefPtr<ImageObject>>> cacheImgObjList_; 213 std::mutex imgObjCacheMutex_; 214 std::unordered_map<std::string, std::list<CacheNode<RefPtr<ImageObject>>>::iterator> imgObjCache_; 215 std::atomic<size_t> imgObjCapacity_ = 2000; // imgObj is cached after clear image data. 216 217 static std::shared_mutex cacheFilePathMutex_; 218 static std::string cacheFilePath_; 219 220 static std::atomic<size_t> cacheFileLimit_; 221 222 static std::atomic<float> clearCacheFileRatio_; 223 224 static std::mutex cacheFileSizeMutex_; 225 static int32_t cacheFileSize_; 226 227 static std::mutex cacheFileInfoMutex_; 228 static std::list<FileInfo> cacheFileInfo_; 229 static bool hasSetCacheFileInfo_; 230 }; 231 232 } // namespace OHOS::Ace 233 234 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_IMAGE_CACHE_H 235