images_pages_cache.cpp

Go to the documentation of this file.
00001 /*
00002  * File Name: images_pages_cache.cpp
00003  */
00004 
00005 /*
00006  * This file is part of uds-plugin-images.
00007  *
00008  * uds-plugin-images is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * uds-plugin-images is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #include "images_pages_cache.h"
00028 #include "log.h"
00029 
00030 namespace images
00031 {
00032 
00033 PagesCache::PagesCache(void)
00034 : total_length(DEFAULT_MEMORY_LIMIT)
00035 , used_length(0)
00036 , pages()
00037 , cache_mutex(0)
00038 {
00039     cache_mutex = g_mutex_new();
00040 }
00041 
00042 PagesCache::~PagesCache(void)
00043 {
00044     g_mutex_lock(cache_mutex);
00045     clear();
00046     g_mutex_unlock(cache_mutex);
00047     g_mutex_free(cache_mutex);
00048 }
00049 
00050 bool PagesCache::set_memory_limit(const int bytes)
00051 {
00052     g_mutex_lock(cache_mutex);
00053 
00054     if (total_length > static_cast<unsigned int>(bytes))
00055     {
00056         //remove the redundant pages
00057         while (used_length > static_cast<unsigned int>(bytes))
00058         {
00059             if (!remove_page())
00060             {
00061                 g_mutex_unlock(cache_mutex);
00062                 return false;
00063             }
00064         }
00065     }
00066 
00067     total_length = static_cast<unsigned int>(bytes);
00068     
00069     g_mutex_unlock(cache_mutex);
00070     return true;
00071 }
00072 
00073 bool PagesCache::make_enough_memory(const gint64 length)
00074 {
00075     bool ok = true;
00076 
00077     g_mutex_lock(cache_mutex);
00078     LOGPRINTF("used [%d] total [%d] request [%lld]", used_length, total_length, length);
00079     
00080     while ( ok && length > static_cast<gint64>(total_length - used_length) )
00081     {
00082         if (!remove_page())
00083         {
00084             // Remove fails, because:
00085             // 1. There is no any cached images any more.
00086             // 2. The image is in use and can't be removed.
00087             ok = false;
00088         }
00089     }
00090 
00091     g_mutex_unlock(cache_mutex);
00092     return ok;
00093 }
00094 
00095 bool PagesCache::add_page(ImagePage * p)
00096 {
00097     if (!p) { return false; }
00098 
00099     const int length = p->length();
00100 
00101     // make room in cache, if needed
00102     make_enough_memory( static_cast<gint64>(length) );
00103 
00104     // insert the new page into cache
00105     g_mutex_lock(cache_mutex);
00106     pages[(*p)()] = p;
00107     used_length += length;
00108     g_mutex_unlock(cache_mutex);
00109 
00110     return true;
00111 }
00112 
00113 ImagePage * PagesCache::get_page(const size_t idx)
00114 {
00115     g_mutex_lock(cache_mutex);
00116     
00117     ImagePage * p = 0;
00118     PagesIter iter = pages.find(idx);
00119     if (iter != pages.end())
00120     {
00121         p = iter->second;
00122     }
00123 
00124     g_mutex_unlock(cache_mutex);
00125     return p;
00126 }
00127 
00128 void PagesCache::lock(void)
00129 {
00130     g_mutex_lock(cache_mutex);
00131 }
00132 
00133 void PagesCache::unlock(void)
00134 {
00135     g_mutex_unlock(cache_mutex);
00136 }
00137 
00138 void PagesCache::clear(void)
00139 {
00140     PagesIter begin = pages.begin();
00141     PagesIter end = pages.end();
00142     PagesIter iter = begin;
00143     for(; iter != end; ++iter)
00144     {
00145         delete iter->second;
00146     }
00147     pages.clear();
00148     used_length = 0;
00149 }
00150 
00151 bool PagesCache::remove_page(void)
00152 {
00153     if (pages.empty())
00154     {
00155         return false;
00156     }
00157 
00158     // remove the out-of-date page based on the remove strategy
00159     PagesIter begin = pages.begin();
00160     PagesIter end = pages.end();
00161     PagesIter iter = begin;
00162     PagesIter remove_iter = iter;
00163 
00164     while(iter != end)
00165     {
00166         if ((*iter->second) < (*remove_iter->second))
00167         {
00168             remove_iter = iter;
00169         }
00170         iter++;
00171     }
00172 
00173     bool b_removed;
00174     if (!remove_iter->second->get_in_use_flag())
00175     {
00176         // sub the used_length
00177         used_length -= remove_iter->second->length();
00178         
00179         // delete the page
00180         delete remove_iter->second;
00181         pages.erase(remove_iter);
00182 
00183         b_removed = true;
00184     }
00185     else
00186     {
00187         b_removed = false;
00188     }
00189 
00190     return b_removed;
00191 }
00192 };
00193 
00194 
Generated by  doxygen 1.6.2-20100208