Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

cache.C

Go to the documentation of this file.
00001 #include "asset.h"
00002 #include "assets.h"
00003 #include "cache.h"
00004 #include "datatype.h"
00005 #include "edl.h"
00006 #include "edlsession.h"
00007 #include "file.h"
00008 #include "filesystem.h"
00009 #include "mutex.h"
00010 #include "preferences.h"
00011 
00012 #include <string.h>
00013 
00014 // edl came from a command which won't exist anymore
00015 CICache::CICache(EDL *edl, 
00016         Preferences *preferences,
00017         ArrayList<PluginServer*> *plugindb)
00018  : List<CICacheItem>()
00019 {
00020         this->edl = new EDL;
00021         this->edl->create_objects();
00022         this->edl->copy_all(edl);
00023         this->plugindb = plugindb;
00024         this->preferences = preferences;
00025         check_in_lock = new Mutex("CICache::check_in_lock");
00026         check_out_lock = new Mutex("CICache::check_out_lock");
00027         total_lock = new Mutex("CICache::total_lock");
00028 }
00029 
00030 CICache::~CICache()
00031 {
00032         while(last) delete last;
00033         delete edl;
00034         delete check_in_lock;
00035         delete check_out_lock;
00036         delete total_lock;
00037 }
00038 
00039 void CICache::set_edl(EDL *edl)
00040 {
00041         this->edl->copy_all(edl);
00042 }
00043 
00044 void CICache::update(File* &file)
00045 {
00046 // Check if exists
00047         for(CICacheItem *current = first; current; current = NEXT)
00048         {
00049                 if(!current->asset->test_path(file->asset->path))
00050                 {
00051                         if(file != current->file)
00052                         {
00053                                 delete file;
00054                                 file = current->file;
00055                         }
00056                         return;
00057                 }
00058         }
00059 
00060         CICacheItem *item;
00061         append(item = new CICacheItem(this, file));
00062         item->asset = new Asset(*(file->asset));
00063         file->set_asset(item->asset);
00064 }
00065 
00066 File* CICache::check_out(Asset *asset)
00067 {
00068         File *result = 0;
00069 
00070         check_out_lock->lock("CICache::check_out");
00071 
00072 // search for it in the cache
00073         CICacheItem *current, *new_item = 0;
00074 
00075         for(current = first; current && !new_item; current = NEXT)
00076         {
00077                 if(!strcmp(current->asset->path, asset->path))
00078                 {
00079                         current->counter = 0;
00080                         new_item = current;
00081                 }
00082         }
00083 
00084 // didn't find it so create a new one
00085         if(!new_item)
00086         {
00087                 new_item = append(new CICacheItem(this, asset));
00088         }
00089 
00090         if(new_item)
00091         {
00092                 if(new_item->file)
00093                 {
00094 // opened successfully
00095                         new_item->item_lock->lock("CICache::check_out");
00096                         new_item->checked_out = 1;
00097 
00098                         result = new_item->file;
00099                 }
00100                 else
00101                 {
00102 // failed
00103                         delete new_item;
00104                         new_item = 0;
00105                 }
00106         }
00107 
00108 
00109 //printf("CICache::check_out %s\n", asset->path);
00110         check_out_lock->unlock();
00111 
00112         return result;
00113 }
00114 
00115 int CICache::check_in(Asset *asset)
00116 {
00117         check_in_lock->lock("CICache::check_in");
00118 
00119         CICacheItem *current;
00120         int result = 0;
00121         total_lock->lock("CICache::check_in");
00122         for(current = first; current && !result; current = NEXT)
00123         {
00124 // Pointers are different
00125                 if(!strcmp(current->asset->path, asset->path))
00126                 {
00127                         current->checked_out = 0;
00128                         current->item_lock->unlock();
00129                         result = 1;
00130                 }
00131         }
00132         total_lock->unlock();
00133 
00134         check_in_lock->unlock();
00135 
00136         age();
00137 //dump();
00138         return result;
00139 }
00140 
00141 int CICache::delete_entry(char *path)
00142 {
00143         Asset *asset = edl->assets->get_asset(path);
00144         if(asset) delete_entry(asset);
00145         return 0;
00146 }
00147 
00148 int CICache::delete_entry(Asset *asset)
00149 {
00150         lock_all();
00151         int result = 0;
00152         CICacheItem *current, *temp;
00153 
00154         for(current = first; current; current = temp)
00155         {
00156                 temp = NEXT;
00157                 if(current->asset->equivalent(*asset, 0, 0))
00158                 {
00159                         if(!current->checked_out)
00160                         {
00161                                 delete current;
00162                         }
00163                         else
00164                         {
00165                                 printf("CICache::delete_entry asset checked out\n");
00166                         }
00167                 }
00168                 current = temp;
00169         }
00170 
00171         unlock_all();
00172         return 0;
00173 }
00174 
00175 int CICache::age()
00176 {
00177         check_out_lock->lock("CICache::age");
00178         CICacheItem *current;
00179 
00180         for(current = first; current; current = NEXT)
00181         {
00182                 current->counter++;
00183         }
00184 
00185 // delete old assets if memory usage is exceeded
00186         int64_t memory_usage;
00187         int result = 0;
00188         do
00189         {
00190                 memory_usage = get_memory_usage();
00191                 
00192 //printf("CICache::age 3 %p %lld %lld\n", this, memory_usage, preferences->cache_size);
00193                 if(memory_usage > preferences->cache_size)
00194                 {
00195                         result = delete_oldest();
00196                 }
00197         }while(memory_usage > preferences->cache_size && !result);
00198 
00199         check_out_lock->unlock();
00200 }
00201 
00202 int64_t CICache::get_memory_usage()
00203 {
00204         CICacheItem *current;
00205         int64_t result = 0;
00206         
00207         for(current = first; current; current = NEXT)
00208         {
00209                 File *file = current->file;
00210                 if(file) result += file->get_memory_usage();
00211         }
00212         
00213         return result;
00214 }
00215 
00216 int CICache::delete_oldest()
00217 {
00218         CICacheItem *current;
00219         int highest_counter = 1;
00220         CICacheItem *oldest = 0;
00221 
00222         for(current = last; current; current =  PREVIOUS)
00223         {
00224                 if(current->counter >= highest_counter)
00225                 {
00226                         oldest = current;
00227                         highest_counter = current->counter;
00228                 }
00229         }
00230 
00231 //      if(highest_counter > 1 && oldest)
00232         if(oldest)
00233         {
00234                 total_lock->lock("CICache::delete_oldest");
00235 
00236 
00237 // Got the oldest file.  Try requesting cache purge.
00238                 if(!oldest->file || oldest->file->purge_cache())
00239                 {
00240 // Delete the file if cache already empty and not checked out.
00241                         if(!oldest->checked_out) delete oldest;
00242                 }
00243                 total_lock->unlock();
00244                 return 0;    // success
00245         }
00246         else
00247         {
00248                 return 1;    // nothing was old enough to delete
00249         }
00250 }
00251 
00252 int CICache::dump()
00253 {
00254         lock_all();
00255         CICacheItem *current;
00256 
00257         printf("CICache::dump total size %lld\n", get_memory_usage());
00258         for(current = first; current; current = NEXT)
00259         {
00260                 printf("cache item %x asset %x %s counter %lld\n", 
00261                         current, 
00262                         current->asset,
00263                         current->asset->path, 
00264                         current->counter);
00265         }
00266         
00267         unlock_all();
00268 }
00269 
00270 int CICache::lock_all()
00271 {
00272         check_in_lock->lock("CICache::lock_all");
00273         check_out_lock->lock("CICache::lock_all");
00274 }
00275 
00276 int CICache::unlock_all()
00277 {
00278         check_in_lock->unlock();
00279         check_out_lock->unlock();
00280 }
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 // File not already opened.
00293 CICacheItem::CICacheItem(CICache *cache, Asset *asset)
00294  : ListItem<CICacheItem>()
00295 {
00296         int result = 0;
00297         counter = 0;
00298         this->asset = new Asset;
00299         item_lock = new Mutex("CICacheItem::item_lock");
00300         
00301 // Must copy Asset since this belongs to an EDL which won't exist forever.
00302         *this->asset = *asset;
00303         this->cache = cache;
00304         checked_out = 0;
00305 
00306         file = new File;
00307         file->set_processors(cache->preferences->processors);
00308         file->set_preload(cache->edl->session->playback_preload);
00309 
00310 
00311 // Copy decoding parameters from session to asset so file can see them.
00312         this->asset->divx_use_deblocking = cache->edl->session->mpeg4_deblock;
00313 
00314 
00315 
00316         if(result = file->open_file(cache->preferences, this->asset, 1, 0, -1, -1))
00317         {
00318                 delete file;
00319                 file = 0;
00320         }
00321 }
00322 
00323 // File already opened
00324 CICacheItem::CICacheItem(CICache *cache, File *file)
00325  : ListItem<CICacheItem>()
00326 {
00327         counter = 0;
00328         this->asset = new Asset;
00329         item_lock = new Mutex("CICacheItem::item_lock");
00330         *this->asset = *file->asset;
00331         this->file = file;
00332         this->cache = cache;
00333         checked_out = 0;
00334 
00335         file->set_processors(cache->preferences->processors);
00336         file->set_preload(cache->edl->session->playback_preload);
00337 }
00338 
00339 CICacheItem::~CICacheItem()
00340 {
00341         delete file;
00342         delete asset;
00343         delete item_lock;
00344 }

Generated on Sun Jan 8 13:38:51 2006 for Cinelerra-svn by  doxygen 1.4.4