00001 #include "asset.h"
00002 #include "assets.h"
00003 #include "bcsignals.h"
00004 #include "cache.h"
00005 #include "condition.h"
00006 #include "datatype.h"
00007 #include "edl.h"
00008 #include "edlsession.h"
00009 #include "file.h"
00010 #include "filesystem.h"
00011 #include "mutex.h"
00012 #include "preferences.h"
00013
00014 #include <string.h>
00015
00016
00017 CICache::CICache(Preferences *preferences,
00018 ArrayList<PluginServer*> *plugindb)
00019 : List<CICacheItem>()
00020 {
00021 this->plugindb = plugindb;
00022 this->preferences = preferences;
00023 check_out_lock = new Condition(0, "CICache::check_out_lock", 0);
00024 total_lock = new Mutex("CICache::total_lock");
00025 }
00026
00027 CICache::~CICache()
00028 {
00029 while(last)
00030 {
00031 CICacheItem *item = last;
00032
00033 remove_pointer(item);
00034 Garbage::delete_object(item);
00035 }
00036 delete check_out_lock;
00037 delete total_lock;
00038 }
00039
00040
00041
00042
00043
00044
00045 File* CICache::check_out(Asset *asset, EDL *edl, int block)
00046 {
00047 CICacheItem *current, *new_item = 0;
00048
00049 while(1)
00050 {
00051
00052 int got_it = 0;
00053 total_lock->lock("CICache::check_out");
00054 for(current = first; current && !got_it; current = NEXT)
00055 {
00056 if(!strcmp(current->asset->path, asset->path))
00057 {
00058 got_it = 1;
00059 break;
00060 }
00061 }
00062
00063
00064 if(got_it)
00065 {
00066 if(!current->checked_out)
00067 {
00068
00069 current->age = EDL::next_id();
00070 current->checked_out = 1;
00071 current->GarbageObject::add_user();
00072 total_lock->unlock();
00073 return current->file;
00074 }
00075 }
00076 else
00077 {
00078
00079 new_item = append(new CICacheItem(this, edl, asset));
00080
00081 if(new_item->file)
00082 {
00083
00084 new_item->age = EDL::next_id();
00085 new_item->checked_out = 1;
00086 new_item->GarbageObject::add_user();
00087 total_lock->unlock();
00088 return new_item->file;
00089 }
00090
00091 else
00092 {
00093 remove_pointer(new_item);
00094 Garbage::delete_object(new_item);
00095 total_lock->unlock();
00096 return 0;
00097 }
00098 }
00099
00100
00101 total_lock->unlock();
00102 if(block)
00103 check_out_lock->lock("CICache::check_out");
00104 else
00105 return 0;
00106 }
00107
00108 return 0;
00109 }
00110
00111 int CICache::check_in(Asset *asset)
00112 {
00113 CICacheItem *current;
00114 int got_it = 0;
00115
00116 total_lock->lock("CICache::check_in");
00117 for(current = first; current; current = NEXT)
00118 {
00119
00120
00121 if(!strcmp(current->asset->path, asset->path))
00122 {
00123 current->checked_out = 0;
00124 current->GarbageObject::remove_user();
00125
00126 break;
00127 }
00128 }
00129 total_lock->unlock();
00130
00131
00132 check_out_lock->unlock();
00133
00134 age();
00135 return 0;
00136 }
00137
00138 void CICache::remove_all()
00139 {
00140 total_lock->lock("CICache::remove_all");
00141 CICacheItem *current, *temp;
00142 for(current = first; current; current = temp)
00143 {
00144 temp = current->next;
00145
00146
00147 if(!current->checked_out)
00148 {
00149
00150 remove_pointer(current);
00151 Garbage::delete_object(current);
00152 }
00153 }
00154 total_lock->unlock();
00155 }
00156
00157 int CICache::delete_entry(char *path)
00158 {
00159 total_lock->lock("CICache::delete_entry");
00160 for(CICacheItem *current = first; current; current = NEXT)
00161 {
00162 if(!strcmp(current->asset->path, path))
00163 {
00164 if(!current->checked_out)
00165 {
00166
00167 remove_pointer(current);
00168 Garbage::delete_object(current);
00169 break;
00170 }
00171 }
00172 }
00173 total_lock->unlock();
00174 return 0;
00175 }
00176
00177 int CICache::delete_entry(Asset *asset)
00178 {
00179 total_lock->lock("CICache::delete_entry");
00180 int result = 0;
00181 CICacheItem *current, *temp;
00182
00183 for(current = first; current; current = NEXT)
00184 {
00185 if(!strcmp(current->asset->path, asset->path))
00186 {
00187 if(!current->checked_out)
00188 {
00189
00190 remove_pointer(current);
00191 Garbage::delete_object(current);
00192 break;
00193 }
00194 }
00195 }
00196
00197 total_lock->unlock();
00198 return 0;
00199 }
00200
00201 int CICache::age()
00202 {
00203 CICacheItem *current;
00204
00205
00206 int64_t prev_memory_usage;
00207 int64_t memory_usage;
00208 int result = 0;
00209 do
00210 {
00211 memory_usage = get_memory_usage(1);
00212
00213 if(memory_usage > preferences->cache_size)
00214 {
00215
00216 result = delete_oldest();
00217 }
00218 prev_memory_usage = memory_usage;
00219 memory_usage = get_memory_usage(0);
00220 }while(prev_memory_usage != memory_usage &&
00221 memory_usage > preferences->cache_size &&
00222 !result);
00223
00224 }
00225
00226 int64_t CICache::get_memory_usage(int use_lock)
00227 {
00228 CICacheItem *current;
00229 int64_t result = 0;
00230 if(use_lock) total_lock->lock("CICache::get_memory_usage");
00231 for(current = first; current; current = NEXT)
00232 {
00233 File *file = current->file;
00234 if(file) result += file->get_memory_usage();
00235 }
00236 if(use_lock) total_lock->unlock();
00237 return result;
00238 }
00239
00240 int CICache::get_oldest()
00241 {
00242 CICacheItem *current;
00243 int oldest = 0x7fffffff;
00244 total_lock->lock("CICache::get_oldest");
00245 for(current = last; current; current = PREVIOUS)
00246 {
00247 if(current->age < oldest)
00248 {
00249 oldest = current->age;
00250 }
00251 }
00252 total_lock->unlock();
00253
00254 return oldest;
00255 }
00256
00257 int CICache::delete_oldest()
00258 {
00259 CICacheItem *current;
00260 int lowest_age = 0x7fffffff;
00261 CICacheItem *oldest = 0;
00262
00263 total_lock->lock("CICache::delete_oldest");
00264
00265 for(current = last; current; current = PREVIOUS)
00266 {
00267 if(current->age < lowest_age)
00268 {
00269 oldest = current;
00270 lowest_age = current->age;
00271 }
00272 }
00273
00274
00275 if(oldest)
00276 {
00277
00278
00279 if(!oldest->file || oldest->file->purge_cache())
00280 {
00281
00282
00283 if(!oldest->checked_out)
00284 {
00285
00286 remove_pointer(oldest);
00287
00288 Garbage::delete_object(oldest);
00289
00290 }
00291
00292 }
00293
00294 total_lock->unlock();
00295
00296 return 0;
00297 }
00298 else
00299 {
00300 total_lock->unlock();
00301
00302 return 1;
00303 }
00304 }
00305
00306 int CICache::dump()
00307 {
00308 CICacheItem *current;
00309 total_lock->lock("CICache::dump");
00310 printf("CICache::dump total size %lld\n", get_memory_usage(0));
00311 for(current = first; current; current = NEXT)
00312 {
00313 printf("cache item %x asset %x %s age=%d\n",
00314 current,
00315 current->asset,
00316 current->asset->path,
00317 current->age);
00318 }
00319 total_lock->unlock();
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 CICacheItem::CICacheItem()
00331 : ListItem<CICacheItem>(), GarbageObject("CICacheItem")
00332 {
00333 }
00334
00335
00336 CICacheItem::CICacheItem(CICache *cache, EDL *edl, Asset *asset)
00337 : ListItem<CICacheItem>(), GarbageObject("CICacheItem")
00338 {
00339 int result = 0;
00340 age = EDL::next_id();
00341
00342 this->asset = new Asset;
00343
00344 item_lock = new Condition(1, "CICacheItem::item_lock", 0);
00345
00346
00347
00348 *this->asset = *asset;
00349 this->cache = cache;
00350 checked_out = 0;
00351
00352
00353 file = new File;
00354 file->set_processors(cache->preferences->processors);
00355 file->set_preload(edl->session->playback_preload);
00356 file->set_subtitle(edl->session->decode_subtitles ?
00357 edl->session->subtitle_number : -1);
00358 file->set_interpolate_raw(edl->session->interpolate_raw);
00359 file->set_white_balance_raw(edl->session->white_balance_raw);
00360
00361
00362
00363 this->asset->divx_use_deblocking = edl->session->mpeg4_deblock;
00364
00365
00366
00367 if(result = file->open_file(cache->preferences, this->asset, 1, 0, -1, -1))
00368 {
00369 SET_TRACE
00370 delete file;
00371 SET_TRACE
00372 file = 0;
00373 }
00374
00375 }
00376
00377 CICacheItem::~CICacheItem()
00378 {
00379 if(file) delete file;
00380 if(asset) Garbage::delete_object(asset);
00381 if(item_lock) delete item_lock;
00382 }