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
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
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
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
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
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
00103 delete new_item;
00104 new_item = 0;
00105 }
00106 }
00107
00108
00109
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
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
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
00186 int64_t memory_usage;
00187 int result = 0;
00188 do
00189 {
00190 memory_usage = get_memory_usage();
00191
00192
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
00232 if(oldest)
00233 {
00234 total_lock->lock("CICache::delete_oldest");
00235
00236
00237
00238 if(!oldest->file || oldest->file->purge_cache())
00239 {
00240
00241 if(!oldest->checked_out) delete oldest;
00242 }
00243 total_lock->unlock();
00244 return 0;
00245 }
00246 else
00247 {
00248 return 1;
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
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
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
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
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 }