r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / cache.C
blob79d04ea2ae55b9f7d021421e3be485f2dd29f6f1
1 #include "asset.h"
2 #include "assets.h"
3 #include "cache.h"
4 #include "datatype.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "file.h"
8 #include "filesystem.h"
9 #include "mutex.h"
10 #include "preferences.h"
12 #include <string.h>
14 // edl came from a command which won't exist anymore
15 CICache::CICache(EDL *edl, 
16         Preferences *preferences,
17         ArrayList<PluginServer*> *plugindb)
18  : List<CICacheItem>()
20         this->edl = new EDL;
21         this->edl->create_objects();
22         *this->edl = *edl;
23         this->plugindb = plugindb;
24         this->preferences = preferences;
25         check_in_lock = new Mutex("CICache::check_in_lock");
26         check_out_lock = new Mutex("CICache::check_out_lock");
27         total_lock = new Mutex("CICache::total_lock");
30 CICache::~CICache()
32         while(last) delete last;
33         delete edl;
34         delete check_in_lock;
35         delete check_out_lock;
36         delete total_lock;
39 void CICache::set_edl(EDL *edl)
41         *this->edl = *edl;
44 void CICache::update(File* &file)
46 // Check if exists
47         for(CICacheItem *current = first; current; current = NEXT)
48         {
49                 if(!current->asset->test_path(file->asset->path))
50                 {
51                         if(file != current->file)
52                         {
53                                 delete file;
54                                 file = current->file;
55                         }
56                         return;
57                 }
58         }
60         CICacheItem *item;
61         append(item = new CICacheItem(this, file));
62         item->asset = new Asset(*(file->asset));
63         file->set_asset(item->asset);
66 File* CICache::check_out(Asset *asset)
68         File *result = 0;
70         check_out_lock->lock("CICache::check_out");
72 // search for it in the cache
73         CICacheItem *current, *new_item = 0;
75         for(current = first; current && !new_item; current = NEXT)
76         {
77                 if(!strcmp(current->asset->path, asset->path))
78                 {
79                         current->counter = 0;
80                         new_item = current;
81                 }
82         }
84 // didn't find it so create a new one
85         if(!new_item)
86         {
87                 new_item = append(new CICacheItem(this, asset));
88         }
90         if(new_item)
91         {
92                 if(new_item->file)
93                 {
94 // opened successfully
95                         new_item->item_lock->lock();
96                         new_item->checked_out = 1;
98                         result = new_item->file;
99                 }
100                 else
101                 {
102 // failed
103                         delete new_item;
104                         new_item = 0;
105                 }
106         }
108         check_out_lock->unlock();
110         return result;
113 int CICache::check_in(Asset *asset)
115         check_in_lock->lock();
117         CICacheItem *current;
118         int result = 0;
119         total_lock->lock("CICache::check_in");
120         for(current = first; current && !result; current = NEXT)
121         {
122 // Pointers are different
123                 if(!strcmp(current->asset->path, asset->path))
124                 {
125                         current->checked_out = 0;
126                         current->item_lock->unlock();
127                         result = 1;
128                 }
129         }
130         total_lock->unlock();
132         check_in_lock->unlock();
134         age();
135 //dump();
136         return result;
139 int CICache::delete_entry(char *path)
141         Asset *asset = edl->assets->get_asset(path);
142         if(asset) delete_entry(asset);
143         return 0;
146 int CICache::delete_entry(Asset *asset)
148         lock_all();
149         int result = 0;
150         CICacheItem *current, *temp;
152         for(current = first; current; current = temp)
153         {
154                 temp = NEXT;
155                 if(current->asset->equivalent(*asset, 0, 0))
156                 {
157                         if(!current->checked_out)
158                         {
159                                 delete current;
160                         }
161                         else
162                         {
163                                 printf("CICache::delete_entry asset checked out\n");
164                         }
165                 }
166                 current = temp;
167         }
169         unlock_all();
170         return 0;
173 int CICache::age()
175         check_out_lock->lock("CICache::age");
176         CICacheItem *current;
178         for(current = first; current; current = NEXT)
179         {
180                 current->counter++;
181         }
183 // delete old assets if memory usage is exceeded
184         int64_t memory_usage;
185         int result = 0;
186         do
187         {
188                 memory_usage = get_memory_usage();
189                 
190                 if(memory_usage > preferences->cache_size)
191                 {
192                         result = delete_oldest();
193                 }
194         }while(memory_usage > preferences->cache_size && !result);
196         check_out_lock->unlock();
199 int64_t CICache::get_memory_usage()
201         CICacheItem *current;
202         int64_t result = 0;
203         
204         for(current = first; current; current = NEXT)
205         {
206                 result++;
207         }
208         
209         return result;
212 int CICache::delete_oldest()
214         CICacheItem *current;
215         int highest_counter = 1;
216         CICacheItem *oldest = 0;
218         for(current = last; current; current =  PREVIOUS)
219         {
220                 if(current->counter >= highest_counter)
221                 {
222                         oldest = current;
223                         highest_counter = current->counter;
224                 }
225         }
227         if(highest_counter > 1 && oldest && !oldest->checked_out)
228         {
229                 total_lock->lock("CICache::delete_oldest");
230                 delete oldest;
231                 total_lock->unlock();
232                 return 0;    // success
233         }
234         else
235         {
236                 return 1;    // nothing was old enough to delete
237         }
240 int CICache::dump()
242         lock_all();
243         CICacheItem *current;
245         for(current = first; current; current = NEXT)
246         {
247                 printf("cache item %x\n", current);
248                 printf("        asset %x\n", current->asset);
249                 printf("        %s\n", current->asset->path);
250                 printf("        counter %lld\n", current->counter);
251         }
252         
253         printf("total size %lld\n", get_memory_usage());
254         unlock_all();
257 int CICache::lock_all()
259         check_in_lock->lock("CICache::lock_all");
260         check_out_lock->lock("CICache::lock_all");
263 int CICache::unlock_all()
265         check_in_lock->unlock();
266         check_out_lock->unlock();
279 // File not already opened.
280 CICacheItem::CICacheItem(CICache *cache, Asset *asset)
281  : ListItem<CICacheItem>()
283         int result = 0;
284         counter = 0;
285         this->asset = new Asset;
286         item_lock = new Mutex("CICacheItem::item_lock");
287         
288 // Must copy Asset since this belongs to an EDL which won't exist forever.
289         *this->asset = *asset;
290         this->cache = cache;
291         checked_out = 0;
293         file = new File;
294         file->set_processors(cache->preferences->processors);
295         file->set_preload(cache->edl->session->playback_preload);
298 // Copy decoding parameters from session to asset so file can see them.
299         this->asset->divx_use_deblocking = cache->edl->session->mpeg4_deblock;
303         if(result = file->open_file(cache->plugindb, this->asset, 1, 0, -1, -1))
304         {
305                 delete file;
306                 file = 0;
307         }
310 // File already opened
311 CICacheItem::CICacheItem(CICache *cache, File *file)
312  : ListItem<CICacheItem>()
314         counter = 0;
315         this->asset = new Asset;
316         item_lock = new Mutex("CICacheItem::item_lock");
317         *this->asset = *file->asset;
318         this->file = file;
319         this->cache = cache;
320         checked_out = 0;
322         file->set_processors(cache->preferences->processors);
323         file->set_preload(cache->edl->session->playback_preload);
326 CICacheItem::~CICacheItem()
328         delete file;
329         delete asset;
330         delete item_lock;