+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "asset.h"
-#include "assets.h"
-#include "bcsignals.h"
-#include "cache.h"
-#include "condition.h"
-#include "datatype.h"
-#include "edl.h"
-#include "edlsession.h"
-#include "file.h"
-#include "filesystem.h"
-#include "format.inc"
-#include "mutex.h"
-#include "thread.h"
-#include "preferences.h"
-
-#include <string.h>
-
-// edl came from a command which won't exist anymore
-CICache::CICache(Preferences *preferences)
- : List<CICacheItem>()
-{
- this->preferences = preferences;
- edl = 0;
- check_out_lock = new Condition(0, "CICache::check_out_lock", 0);
- total_lock = new Mutex("CICache::total_lock");
-}
-
-CICache::~CICache()
-{
- while(last)
- {
- CICacheItem *item = last;
-//printf("CICache::~CICache: %s\n", item->asset->path);
- remove_pointer(item);
- item->Garbage::remove_user();
- }
- delete check_out_lock;
- delete total_lock;
-}
-
-
-
-
-
-
-File* CICache::check_out(Asset *asset, EDL *edl, int block)
-{
- CICacheItem *current = 0;
- long tid = (long)Thread::get_self();
- if( !tid ) tid = 1;
-
- while(1)
- {
- File *file = 0;
- total_lock->lock("CICache::check_out");
-// Scan directory for item
- current = first;
- while(current && strcmp(current->asset->path, asset->path) != 0)
- current = NEXT;
- if(!current) { // Create new item
- current = new CICacheItem(this, edl, asset);
- append(current); current->checked_out = tid;
- file = current->file;
- total_lock->unlock();
- int result = file->open_file(preferences, asset, 1, 0);
- if( result ) {
-SET_TRACE
- delete file;
- file = 0;
- }
- total_lock->lock("CICache::check_out 2");
- if( !file ) {
- remove_pointer(current);
- current->file = 0;
- current->Garbage::remove_user();
- current = 0;
- }
- else
- current->Garbage::add_user();
- }
- else {
- file = current->file;
- if(!current->checked_out) {
-// Return existing/new item
- current->Garbage::add_user();
- current->age = EDL::next_id();
- current->checked_out = tid;
- }
- else
- current = 0;
- }
- total_lock->unlock();
- if(current || !file || !block) break;
-// Try again after blocking
- check_out_lock->lock("CICache::check_out");
- }
-
-//printf("check out %p %lx %s\n", current, tid, asset->path);
- return current ? current->file : 0;
-}
-
-int CICache::check_in(Asset *asset)
-{
- total_lock->lock("CICache::check_in");
- CICacheItem *current = first;
- while(current && strcmp(current->asset->path, asset->path) != 0)
- current = NEXT;
- if(current && current->checked_out) {
- current->checked_out = 0;
- current->Garbage::remove_user();
- }
- total_lock->unlock();
-
-// Release for blocking check_out operations
- check_out_lock->unlock();
-//printf("check in %p %lx %s\n", current, (long)Thread::get_self(), asset->path);
- age();
- return 0;
-}
-
-void CICache::remove_all()
-{
- CICacheItem *current, *temp;
- List<CICacheItem> removed;
- total_lock->lock("CICache::remove_all");
- for(current=first; current; current=temp)
- {
- temp = NEXT;
-// Must not be checked out because we need the pointer to check back in.
-// Really need to give the user the CacheItem.
- if(!current->checked_out)
- {
-//printf("CICache::remove_all: %s\n", current->asset->path);
- remove_pointer(current);
- removed.append(current);
- }
- }
- total_lock->unlock();
- while( (current=removed.first) != 0 )
- {
- removed.remove_pointer(current);
- current->Garbage::remove_user();
- }
-}
-
-int CICache::delete_entry(char *path)
-{
- total_lock->lock("CICache::delete_entry");
- CICacheItem *current = first;
- while( current && strcmp(current->asset->path, path) !=0 )
- current = NEXT;
- if(current && !current->checked_out)
- remove_pointer(current);
- else
- current = 0;
-//printf("CICache::delete_entry: %s\n", current->asset->path);
- total_lock->unlock();
- if(current)
- current->Garbage::remove_user();
- return 0;
-}
-
-int CICache::delete_entry(Asset *asset)
-{
- return delete_entry(asset->path);
-}
-
-int CICache::age()
-{
-// delete old assets if memory usage is exceeded
- int64_t prev_memory_usage = 0;
- int result = 0;
- while( !result ) {
- int64_t memory_usage = get_memory_usage(1);
- if( prev_memory_usage == memory_usage ) break;
- if( preferences->cache_size >= memory_usage ) break;
-//printf("CICache::age 3 %p " _LD " " _LD "\n", this, memory_usage, preferences->cache_size);
- prev_memory_usage = memory_usage;
- result = delete_oldest();
- }
- return result;
-}
-
-int64_t CICache::get_memory_usage(int use_lock)
-{
- CICacheItem *current;
- int64_t result = 0;
- if(use_lock) total_lock->lock("CICache::get_memory_usage");
- for(current = first; current; current = NEXT)
- {
- File *file = current->file;
- if(file) result += file->get_memory_usage();
- }
- if(use_lock) total_lock->unlock();
- return result;
-}
-
-int CICache::get_oldest()
-{
- CICacheItem *current;
- int oldest = 0x7fffffff;
- total_lock->lock("CICache::get_oldest");
- for(current = last; current; current = PREVIOUS)
- {
- if(current->age < oldest)
- {
- oldest = current->age;
- }
- }
- total_lock->unlock();
-
- return oldest;
-}
-
-int CICache::delete_oldest()
-{
- int result = 0;
- total_lock->lock("CICache::delete_oldest");
- CICacheItem *oldest = 0;
-// at least 2
- if( first != last ) {
- CICacheItem *current = first;
- oldest = current;
- while( (current=NEXT) != 0 ) {
- if( current->age < oldest->age )
- oldest = current;
- }
-// Got the oldest file. Try requesting cache purge from it.
- if( oldest->file )
- oldest->file->purge_cache();
-// Delete the file if cache already empty and not checked out.
- if( !oldest->checked_out )
- remove_pointer(oldest);
- else
- oldest = 0;
- }
-// settle for just deleting one frame
- else if( first )
- result = first->file->delete_oldest();
- total_lock->unlock();
- if( oldest ) {
- oldest->Garbage::remove_user();
- result = 1;
- }
- return result;
-}
-
-int CICache::dump()
-{
- CICacheItem *current;
- total_lock->lock("CICache::dump");
- printf("CICache::dump total size " _LD "\n", get_memory_usage(0));
- for(current = first; current; current = NEXT)
- {
- printf("cache item %p asset %p %s age=%d\n",
- current, current->asset,
- current->asset->path, current->age);
- }
- total_lock->unlock();
- return 0;
-}
-
-
-
-
-
-
-
-
-
-CICacheItem::CICacheItem()
-: Garbage("CICacheItem"), ListItem<CICacheItem>()
-{
-}
-
-
-CICacheItem::CICacheItem(CICache *cache, EDL *edl, Asset *asset)
- : Garbage("CICacheItem"), ListItem<CICacheItem>()
-{
- age = EDL::next_id();
-
- this->asset = new Asset;
-
- item_lock = new Condition(1, "CICacheItem::item_lock", 0);
-
-
-// Must copy Asset since this belongs to an EDL which won't exist forever.
- this->asset->copy_from(asset, 1);
- this->cache = cache;
- checked_out = 0;
-
-
- file = new File;
- int cpus = cache->preferences->processors;
- file->set_processors(cpus);
- file->set_preload(edl->session->playback_preload);
- file->set_subtitle(edl->session->decode_subtitles ?
- edl->session->subtitle_number : -1);
- file->set_program(edl->session->program_no);
- file->set_interpolate_raw(edl->session->interpolate_raw);
- file->set_white_balance_raw(edl->session->white_balance_raw);
-
-SET_TRACE
-}
-
-CICacheItem::~CICacheItem()
-{
- if(file) delete file;
- if(asset) asset->Garbage::remove_user();
- if(item_lock) delete item_lock;
-}