iipsrv  0.9.9
Cache.h
1 // Tile Cache Class
2 
3 /* IIP Image Server
4 
5  Copyright (C) 2005-2010 Ruven Pillay.
6  Based on an LRU cache by Patrick Audley <http://blackcat.ca/lifeline/query.php/tag=LRU_CACHE>
7  Copyright (C) 2004 by Patrick Audley
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 
24 
25 
26 #ifndef _CACHE_H
27 #define _CACHE_H
28 
29 // Remove our deprecated warnings for now. We should upgrade our hash_maps to
30 // unordered_maps, however
31 #undef __DEPRECATED
32 
33 // Use the hashmap extensions if we are using >= gcc 3.1
34 #ifdef __GNUC__
35 
36 #if (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || (__GNUC__ >= 4)
37 #define USE_HASHMAP 1
38 #include <ext/hash_map>
39 namespace __gnu_cxx
40 {
41  template<> struct hash< const std::string > {
42  size_t operator()( const std::string& x ) const {
43  return hash< const char* >()( x.c_str() );
44  }
45  };
46 }
47 #endif
48 
49 // And the high performance memory pool allocator if >= gcc 3.4
50 #if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)
51 #define POOL_ALLOCATOR 1
52 #include <ext/pool_allocator.h>
53 #endif
54 
55 #endif
56 
57 
58 #ifndef USE_HASHMAP
59 #include <map>
60 #endif
61 
62 
63 // Fix missing snprintf in Windows
64 #if _MSC_VER
65 #define snprintf _snprintf
66 #endif
67 
68 
69 #include <iostream>
70 #include <list>
71 #include <string>
72 #include "RawTile.h"
73 
74 
75 
77 
78 class Cache {
79 
80 
81  private:
82 
84  int tileSize;
85 
87  unsigned long maxSize;
88 
90  unsigned long currentSize;
91 
93 #ifdef POOL_ALLOCATOR
94  typedef std::list < std::pair<const std::string,RawTile>,
95  __gnu_cxx::__pool_alloc< std::pair<const std::string,RawTile> > > TileList;
96 #else
97  typedef std::list < std::pair<const std::string,RawTile> > TileList;
98 #endif
99 
101  typedef std::list < std::pair<const std::string,RawTile> >::iterator List_Iter;
102 
104 #ifdef USE_HASHMAP
105 #ifdef POOL_ALLOCATOR
106  typedef __gnu_cxx::hash_map < const std::string, List_Iter,
107  __gnu_cxx::hash< const std::string >,
108  std::equal_to< const std::string >,
109  __gnu_cxx::__pool_alloc< std::pair<const std::string, List_Iter> >
110  > TileMap;
111 #else
112  typedef __gnu_cxx::hash_map < const std::string,List_Iter > TileMap;
113 #endif
114 #else
115  typedef std::map < const std::string,List_Iter > TileMap;
116 #endif
117 
119  TileList tileList;
120 
122  TileMap tileMap;
123 
124 
126 
130  TileMap::iterator _touch( const std::string &key ) {
131  TileMap::iterator miter = tileMap.find( key );
132  if( miter == tileMap.end() ) return miter;
133  // Move the found node to the head of the list.
134  tileList.splice( tileList.begin(), tileList, miter->second );
135  return miter;
136  }
137 
138 
140 
144  void _remove( const TileMap::iterator &miter ) {
145  // Reduce our current size counter
146  currentSize -= ( (miter->second->second).dataLength +
147  ( (miter->second->second).filename.capacity() + (miter->second->first).capacity() )*sizeof(char) +
148  tileSize );
149  tileList.erase( miter->second );
150  tileMap.erase( miter );
151  }
152 
153 
155 
156  void _remove( const std::string &key ) {
157  TileMap::iterator miter = tileMap.find( key );
158  this->_remove( miter );
159  }
160 
161 
162 
163  public:
164 
166 
167  Cache( float max ) {
168  maxSize = (unsigned long)(max*1024000) ; currentSize = 0;
169  // 64 chars added at the end represents an average string length
170  tileSize = sizeof( RawTile ) + sizeof( std::pair<const std::string,RawTile> ) +
171  sizeof( std::pair<const std::string, List_Iter> ) + sizeof(char)*64 + sizeof(List_Iter);
172  };
173 
174 
176  ~Cache() {
177  tileList.clear();
178  tileMap.clear();
179  }
180 
181 
183 
184  void insert( const RawTile& r ) {
185 
186  if( maxSize == 0 ) return;
187 
188  std::string key = this->getIndex( r.filename, r.resolution, r.tileNum,
190 
191  // Touch the key, if it exists
192  TileMap::iterator miter = this->_touch( key );
193 
194  // Check whether this tile exists in our cache
195  if( miter != tileMap.end() ){
196  // Check the timestamp and delete if necessary
197  if( miter->second->second.timestamp < r.timestamp ){
198  this->_remove( miter );
199  }
200  // If this index already exists and it is up to date, do nothing
201  else return;
202  }
203 
204  // Store the key if it doesn't already exist in our cache
205  // Ok, do the actual insert at the head of the list
206  tileList.push_front( std::make_pair(key,r) );
207 
208  // And store this in our map
209  List_Iter liter = tileList.begin();
210  tileMap[ key ] = liter;
211 
212  // Update our total current size variable. Use the string::capacity function
213  // rather than length() as std::string can allocate slightly more than necessary
214  // The +1 is for the terminating null byte
215  currentSize += (r.dataLength + (r.filename.capacity()+key.capacity())*sizeof(char) + tileSize);
216 
217  // Check to see if we need to remove an element due to exceeding max_size
218  while( currentSize > maxSize ) {
219  // Remove the last element
220  liter = tileList.end();
221  --liter;
222  this->_remove( liter->first );
223  }
224 
225  }
226 
227 
229  unsigned int getNumElements() { return tileList.size(); }
230 
231 
233  float getMemorySize() { return (float) ( currentSize / 1024000.0 ); }
234 
235 
237 
247  RawTile* getTile( std::string f, int r, int t, int h, int v, CompressionType c, int q ) {
248 
249  if( maxSize == 0 ) return NULL;
250 
251  std::string key = this->getIndex( f, r, t, h, v, c, q );
252 
253  TileMap::iterator miter = tileMap.find( key );
254  if( miter == tileMap.end() ) return NULL;
255  this->_touch( key );
256 
257  return &(miter->second->second);
258  }
259 
260 
262 
272  std::string getIndex( std::string f, int r, int t, int h, int v, CompressionType c, int q ) {
273  char tmp[1024];
274  snprintf( tmp, 1024, "%s:%d:%d:%d:%d:%d:%d", f.c_str(), r, t, h, v, c, q );
275  return std::string( tmp );
276  }
277 
278 
279 
280 };
281 
282 
283 
284 #endif
int vSequence
The vertical angle to which this tile belongs.
Definition: RawTile.h:57
int resolution
The resolution to which this tile belongs.
Definition: RawTile.h:51
void insert(const RawTile &r)
Insert a tile.
Definition: Cache.h:184
int hSequence
The horizontal angle to which this tile belongs.
Definition: RawTile.h:54
int tileNum
The tile number for this tile.
Definition: RawTile.h:48
CompressionType compressionType
Compression type.
Definition: RawTile.h:60
float getMemorySize()
Return the number of MB stored.
Definition: Cache.h:233
std::string filename
Name of the file from which this tile comes.
Definition: RawTile.h:66
Cache to store raw tile data.
Definition: Cache.h:78
std::string getIndex(std::string f, int r, int t, int h, int v, CompressionType c, int q)
Create a hash index.
Definition: Cache.h:272
~Cache()
Destructor.
Definition: Cache.h:176
int quality
Compression rate or quality.
Definition: RawTile.h:63
Cache(float max)
Constructor.
Definition: Cache.h:167
unsigned int getNumElements()
Return the number of tiles in the cache.
Definition: Cache.h:229
RawTile * getTile(std::string f, int r, int t, int h, int v, CompressionType c, int q)
Get a tile from the cache.
Definition: Cache.h:247
time_t timestamp
Tile timestamp.
Definition: RawTile.h:69
Class to represent a single image tile.
Definition: RawTile.h:43
int dataLength
The size of the data pointed to by data.
Definition: RawTile.h:84