source: trunk/libdjvu/DjVuFileCache.cpp @ 280

Last change on this file since 280 was 280, checked in by rbri, 11 years ago

DJVU plugin: djvulibre updated to version 3.5.22

File size: 7.8 KB
Line 
1//C-  -*- C++ -*-
2//C- -------------------------------------------------------------------
3//C- DjVuLibre-3.5
4//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5//C- Copyright (c) 2001  AT&T
6//C-
7//C- This software is subject to, and may be distributed under, the
8//C- GNU General Public License, either Version 2 of the license,
9//C- or (at your option) any later version. The license should have
10//C- accompanied the software or you may obtain a copy of the license
11//C- from the Free Software Foundation at http://www.fsf.org .
12//C-
13//C- This program is distributed in the hope that it will be useful,
14//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
15//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16//C- GNU General Public License for more details.
17//C-
18//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
19//C- Lizardtech Software.  Lizardtech Software has authorized us to
20//C- replace the original DjVu(r) Reference Library notice by the following
21//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
22//C-
23//C-  ------------------------------------------------------------------
24//C- | DjVu (r) Reference Library (v. 3.5)
25//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
26//C- | The DjVu Reference Library is protected by U.S. Pat. No.
27//C- | 6,058,214 and patents pending.
28//C- |
29//C- | This software is subject to, and may be distributed under, the
30//C- | GNU General Public License, either Version 2 of the license,
31//C- | or (at your option) any later version. The license should have
32//C- | accompanied the software or you may obtain a copy of the license
33//C- | from the Free Software Foundation at http://www.fsf.org .
34//C- |
35//C- | The computer code originally released by LizardTech under this
36//C- | license and unmodified by other parties is deemed "the LIZARDTECH
37//C- | ORIGINAL CODE."  Subject to any third party intellectual property
38//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
39//C- | non-exclusive license to make, use, sell, or otherwise dispose of
40//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
41//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
42//C- | General Public License.   This grant only confers the right to
43//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
44//C- | the extent such infringement is reasonably necessary to enable
45//C- | recipient to make, have made, practice, sell, or otherwise dispose
46//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
47//C- | any greater extent that may be necessary to utilize further
48//C- | modifications or combinations.
49//C- |
50//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
51//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
52//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
53//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
54//C- +------------------------------------------------------------------
55//
56// $Id: DjVuFileCache.cpp,v 1.10 2007/03/25 20:48:30 leonb Exp $
57// $Name: release_3_5_22 $
58
59#ifdef HAVE_CONFIG_H
60# include "config.h"
61#endif
62#if NEED_GNUG_PRAGMAS
63# pragma implementation
64#endif
65
66#include "DjVuFileCache.h"
67#include "debug.h"
68
69#include <stdlib.h>
70
71
72#ifdef HAVE_NAMESPACES
73namespace DJVU {
74# ifdef NOT_DEFINED // Just to fool emacs c++ mode
75}
76#endif
77#endif
78
79
80DjVuFileCache::~DjVuFileCache(void) {}
81
82int
83DjVuFileCache::Item::qsort_func(const void * el1, const void * el2)
84{
85   const Item * item1=*(Item **) el1;
86   const Item * item2=*(Item **) el2;
87   time_t time1=item1->get_time();
88   time_t time2=item2->get_time();
89   return time1<time2 ? -1 : time1>time2 ? 1 : 0;
90}
91
92void
93DjVuFileCache::set_max_size(int xmax_size)
94{
95   DEBUG_MSG("DjVuFileCache::set_max_size(): resizing to " << xmax_size << "\n");
96   DEBUG_MAKE_INDENT(3);
97
98   GCriticalSectionLock lock(&class_lock);
99   
100   max_size=xmax_size;
101   cur_size=calculate_size();
102
103   if (max_size>=0) clear_to_size(enabled ? max_size : 0);
104}
105
106void
107DjVuFileCache::enable(bool en)
108{
109   enabled=en;
110   set_max_size(max_size);
111}
112
113void
114DjVuFileCache::add_file(const GP<DjVuFile> & file)
115{
116   DEBUG_MSG("DjVuFileCache::add_file(): trying to add a new item\n");
117   DEBUG_MAKE_INDENT(3);
118
119   GCriticalSectionLock lock(&class_lock);
120
121      // See if the file is already cached
122   GPosition pos;
123   for(pos=list;pos;++pos)
124      if (list[pos]->get_file()==file) break;
125   
126   if (pos) list[pos]->refresh();       // Refresh the timestamp
127   else
128   {
129         // Doesn't exist in the list yet
130      int _max_size=enabled ? max_size : 0;
131      if (max_size<0) _max_size=max_size;
132
133      int add_size=file->get_memory_usage();
134   
135      if (_max_size>=0 && add_size>_max_size)
136      {
137         DEBUG_MSG("but this item is way too large => doing nothing\n");
138         return;
139      }
140
141      if (_max_size>=0) clear_to_size(_max_size-add_size);
142
143      list.append(new Item(file));
144      cur_size+=add_size;
145      file_added(file);
146   }
147}
148
149void
150DjVuFileCache::clear_to_size(int size)
151{
152   DEBUG_MSG("DjVuFileCache::clear_to_size(): dropping cache size to " << size << "\n");
153   DEBUG_MAKE_INDENT(3);
154
155   GCriticalSectionLock lock(&class_lock);
156   
157   if (size==0)
158   {
159      list.empty();
160      cur_size=0;
161   } else
162      if (list.size()>20)
163      {
164            // More than 20 elements in the cache: use qsort to
165            // sort them before picking up the oldest
166         GTArray<void *> item_arr(list.size()-1);
167         GPosition pos;
168         int i;
169         for(pos=list, i=0;pos;++pos, i++)
170         {
171            GP<Item> item=list[pos];
172            item->list_pos=pos;
173            item_arr[i]=item;
174         }
175
176         qsort(&item_arr[0], item_arr.size(), sizeof(item_arr[0]), Item::qsort_func);
177
178         for(i=0;i<item_arr.size() && cur_size>(int) size;i++)
179         {
180            Item * item=(Item *) item_arr[i];
181            cur_size-=item->get_size();
182            GP<DjVuFile> file=item->file;
183            list.del(item->list_pos);
184            file_cleared(file);
185            if (cur_size<=0) cur_size=calculate_size();
186         }
187      } else
188      {
189            // Less than 20 elements: no reason to presort
190         while(cur_size>(int) size)
191         {
192            if (!list.size())
193            {
194                  // Oops. Discrepancy due to an item changed its size
195               cur_size=0;
196               break;
197            }
198
199               // Remove the oldest cache item
200            GPosition oldest_pos=list;
201            GPosition pos=list;
202            for(++pos;pos;++pos)
203               if (list[pos]->get_time()<list[oldest_pos]->get_time())
204                  oldest_pos=pos;
205            cur_size-=list[oldest_pos]->get_size();
206            GP<DjVuFile> file=list[oldest_pos]->file;
207            list.del(oldest_pos);
208            file_cleared(file);
209
210               // cur_size *may* become negative because items may change their
211               // size after they've been added to the cache
212            if (cur_size<=0) cur_size=calculate_size();
213         }
214      }
215   
216   DEBUG_MSG("done: current cache size=" << cur_size << "\n");
217}
218
219int
220DjVuFileCache::calculate_size(void)
221{
222   GCriticalSectionLock lock(&class_lock);
223   
224   int size=0;
225   for(GPosition pos=list;pos;++pos)
226      size+=list[pos]->get_size();
227   return size;
228}
229
230void
231DjVuFileCache::del_file(const DjVuFile * file)
232{
233   DEBUG_MSG("DjVuFileCache::del_file(): Removing an item from cache\n");
234   DEBUG_MAKE_INDENT(3);
235
236   GCriticalSectionLock lock(&class_lock);
237
238   for(GPosition pos=list;pos;++pos)
239      if (list[pos]->get_file()==file)
240      {
241         GP<DjVuFile> file=list[pos]->get_file();
242         cur_size-=list[pos]->get_size();
243         list.del(pos);
244         file_deleted(file);
245         break;
246      }
247   if (cur_size<0) cur_size=calculate_size();
248   DEBUG_MSG("current cache size=" << cur_size << "\n");
249}
250
251GPList<DjVuFileCache::Item>
252DjVuFileCache::get_items(void)
253{
254   GCriticalSectionLock lock(&class_lock);
255
256   return list;
257}
258
259void
260DjVuFileCache::file_added(const GP<DjVuFile> &) {}
261
262void
263DjVuFileCache::file_deleted(const GP<DjVuFile> &) {}
264
265void
266DjVuFileCache::file_cleared(const GP<DjVuFile> &) {}
267
268#ifdef HAVE_NAMESPACES
269}
270# ifndef NOT_USING_DJVU_NAMESPACE
271using namespace DJVU;
272# endif
273#endif
274
Note: See TracBrowser for help on using the repository browser.