r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / cache.C
blobce284689b3fe5ff3af7792ba57d1a76661a0b84b
1 #include "assets.h"
2 #include "cache.h"
3 #include "datatype.h"
4 #include "edl.h"
5 #include "edlsession.h"
6 #include "file.h"
7 #include "filesystem.h"
8 #include "preferences.h"
10 #include <string.h>
12 // edl came from a command which won't exist anymore
13 CICache::CICache(EDL *edl, 
14         Preferences *preferences,
15         ArrayList<PluginServer*> *plugindb)
16  : List<CICacheItem>()
18         this->edl = new EDL;
19         this->edl->create_objects();
20         *this->edl = *edl;
21         this->plugindb = plugindb;
22         this->preferences = preferences;
25 CICache::~CICache()
27         while(last) delete last;
28         delete edl;
31 void CICache::set_edl(EDL *edl)
33         *this->edl = *edl;
36 void CICache::update(File* &file)
38 // Check if exists
39         for(CICacheItem *current = first; current; current = NEXT)
40         {
41                 if(!current->asset->test_path(file->asset->path))
42                 {
43                         if(file != current->file)
44                         {
45                                 delete file;
46                                 file = current->file;
47                         }
48                         return;
49                 }
50         }
52         CICacheItem *item;
53         append(item = new CICacheItem(this, file));
54         item->asset = new Asset(*(file->asset));
55         file->set_asset(item->asset);
58 File* CICache::check_out(Asset *asset)
60         File *result = 0;
62         check_out_lock.lock();
64 //printf("CICache::check_out 1 %s\n", asset->path);
65 // search for it in the cache
66         CICacheItem *current, *new_item = 0;
67 //printf("CICache::check_out 1 %s\n", asset->path);
69         for(current = first; current && !new_item; current = NEXT)
70         {
71                 if(!strcmp(current->asset->path, asset->path))
72                 {
73                         current->counter = 0;
74                         new_item = current;
75                 }
76         }
77 //printf("CICache::check_out 1 %s\n", asset->path);
79 // didn't find it so create a new one
80         if(!new_item)
81         {
82                 new_item = append(new CICacheItem(this, asset));
83         }
85 //printf("CICache::check_out 1 %s\n", asset->path);
86         if(new_item)
87         {
88                 if(new_item->file)
89                 {
90 // opened successfully
91                         new_item->item_lock.lock();
92                         new_item->checked_out = 1;
94                         result = new_item->file;
95                 }
96                 else
97                 {
98 // failed
99                         delete new_item;
100                         new_item = 0;
101                 }
102         }
103 //printf("CICache::check_out 1 %s\n", asset->path);
105         check_out_lock.unlock();
106 //printf("CICache::check_out 100 %s\n", asset->path);
108         return result;
111 int CICache::check_in(Asset *asset)
113         check_in_lock.lock();
115         CICacheItem *current;
116         int result = 0;
117         total_lock.lock();
118         for(current = first; current && !result; current = NEXT)
119         {
120 // Pointers are different
121                 if(!strcmp(current->asset->path, asset->path))
122                 {
123                         current->checked_out = 0;
124                         current->item_lock.unlock();
125                         result = 1;
126                 }
127         }
128         total_lock.unlock();
130         check_in_lock.unlock();
132         age();
133 //dump();
134         return result;
137 int CICache::delete_entry(char *path)
139         Asset *asset = edl->assets->get_asset(path);
140         if(asset) delete_entry(asset);
141         return 0;
144 int CICache::delete_entry(Asset *asset)
146         lock_all();
147         int result = 0;
148         CICacheItem *current, *temp;
150         for(current = first; current; current = temp)
151         {
152                 temp = NEXT;
153                 if(current->asset->equivalent(*asset, 0, 0))
154                 {
155                         if(!current->checked_out)
156                         {
157                                 delete current;
158                         }
159                         else
160                         {
161                                 printf("CICache::delete_entry asset checked out\n");
162                         }
163                 }
164                 current = temp;
165         }
167         unlock_all();
168         return 0;
171 int CICache::age()
173         check_out_lock.lock();
174         CICacheItem *current;
176         for(current = first; current; current = NEXT)
177         {
178                 current->counter++;
179         }
181 // delete old assets if memory usage is exceeded
182         int64_t memory_usage;
183         int result = 0;
184         do
185         {
186                 memory_usage = get_memory_usage();
187                 
188                 if(memory_usage > preferences->cache_size)
189                 {
190                         result = delete_oldest();
191                 }
192         }while(memory_usage > preferences->cache_size && !result);
194         check_out_lock.unlock();
197 int64_t CICache::get_memory_usage()
199         CICacheItem *current;
200         int64_t result = 0;
201         
202         for(current = first; current; current = NEXT)
203         {
204                 result++;
205         }
206         
207         return result;
210 int CICache::delete_oldest()
212         CICacheItem *current;
213         int highest_counter = 1;
214         CICacheItem *oldest = 0;
216         for(current = last; current; current =  PREVIOUS)
217         {
218                 if(current->counter >= highest_counter)
219                 {
220                         oldest = current;
221                         highest_counter = current->counter;
222                 }
223         }
225         if(highest_counter > 1 && oldest && !oldest->checked_out)
226         {
227                 total_lock.lock();
228                 delete oldest;
229                 total_lock.unlock();
230                 return 0;    // success
231         }
232         else
233         {
234                 return 1;    // nothing was old enough to delete
235         }
238 int CICache::dump()
240         lock_all();
241         CICacheItem *current;
243         for(current = first; current; current = NEXT)
244         {
245                 printf("cache item %x\n", current);
246                 printf("        asset %x\n", current->asset);
247                 printf("        %s\n", current->asset->path);
248                 printf("        counter %lld\n", current->counter);
249         }
250         
251         printf("total size %lld\n", get_memory_usage());
252         unlock_all();
255 int CICache::lock_all()
257         check_in_lock.lock();
258         check_out_lock.lock();
261 int CICache::unlock_all()
263         check_in_lock.unlock();
264         check_out_lock.unlock();
277 // File not already opened.
278 CICacheItem::CICacheItem(CICache *cache, Asset *asset)
279  : ListItem<CICacheItem>()
281 //printf("CICacheItem::CICacheItem 1\n");
282         int result = 0;
283         counter = 0;
284         this->asset = new Asset;
285         
286 // Must copy Asset since this belongs to an EDL which won't exist forever.
287 //printf("CICacheItem::CICacheItem 1\n");
288         *this->asset = *asset;
289 //printf("CICacheItem::CICacheItem 1\n");
290         this->cache = cache;
291         checked_out = 0;
293         file = new File;
294 //printf("CICacheItem::CICacheItem 1\n");
295         file->set_processors(cache->edl->session->smp ? 2: 1);
296 //printf("CICacheItem::CICacheItem 1\n");
297         file->set_preload(cache->edl->session->playback_preload);
298 //printf("CICacheItem::CICacheItem 1\n");
301 // Copy decoding parameters from session to asset so file can see them.
302         this->asset->divx_use_deblocking = cache->edl->session->mpeg4_deblock;
304 //printf("CICacheItem::CICacheItem 1\n");
307         if(result = file->open_file(cache->plugindb, this->asset, 1, 0, -1, -1))
308         {
309                 delete file;
310                 file = 0;
311         }
314 // File already opened
315 CICacheItem::CICacheItem(CICache *cache, File *file)
316  : ListItem<CICacheItem>()
318         counter = 0;
319         this->asset = new Asset;
320         *this->asset = *file->asset;
321         this->file = file;
322         this->cache = cache;
323         checked_out = 0;
325         file->set_processors(cache->edl->session->smp ? 2: 1);
326         file->set_preload(cache->edl->session->playback_preload);
329 CICacheItem::~CICacheItem()
331         delete file;
332         delete asset;