• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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