iipsrv  1.1
iipsrv is an advanced high-performance feature-rich image server for web-based streamed viewing and zooming of ultra high-resolution images
Cache.h
1 // Tile Cache Class
2 
3 /* IIP Image Server
4 
5  Copyright (C) 2005-2019 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 3 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 Foundation,
21  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23 
24 
25 
26 #ifndef _CACHE_H
27 #define _CACHE_H
28 
29 
30 // Fix missing snprintf in Windows
31 #if defined _MSC_VER && _MSC_VER<1900
32 #define snprintf _snprintf
33 #endif
34 
35 
36 
37 // Test for available map types. Try to use an efficient hashed map type if possible
38 // and define this as HASHMAP, which we can then use elsewhere.
39 #if defined(HAVE_UNORDERED_MAP)
40 #include <unordered_map>
41 #define HASHMAP std::unordered_map
42 
43 #elif defined(HAVE_TR1_UNORDERED_MAP)
44 #include <tr1/unordered_map>
45 #define HASHMAP std::tr1::unordered_map
46 
47 // Use the gcc hash_map extension if we have it
48 #elif defined(HAVE_EXT_HASH_MAP)
49 #include <ext/hash_map>
50 #define HASHMAP __gnu_cxx::hash_map
51 
52 /* Explicit template specialization of hash of a string class,
53  which just uses the internal char* representation as a wrapper.
54  Required for older versions of gcc as hashing on a string is
55  not supported.
56  */
57 namespace __gnu_cxx {
58  template <>
59  struct hash<std::string> {
60  size_t operator() (const std::string& x) const {
61  return hash<const char*>()(x.c_str());
62  }
63  };
64 }
65 
66 // If no hash type available, just use map
67 #else
68 #include <map>
69 #define HASHMAP std::map
70 
71 #endif // End of #if defined
72 
73 
74 
75 // Try to use the gcc high performance memory pool allocator (available in gcc >= 3.4)
76 #ifdef HAVE_EXT_POOL_ALLOCATOR
77 #include <ext/pool_allocator.h>
78 #endif
79 
80 
81 
82 #include <iostream>
83 #include <list>
84 #include <string>
85 #include "RawTile.h"
86 
87 
88 
90 
91 class Cache {
92 
93 
94  private:
95 
97  int tileSize;
98 
100  unsigned long maxSize;
101 
103  unsigned long currentSize;
104 
106 #ifdef HAVE_EXT_POOL_ALLOCATOR
107  typedef std::list < std::pair<const std::string,RawTile>,
108  __gnu_cxx::__pool_alloc< std::pair<const std::string,RawTile> > > TileList;
109 #else
110  typedef std::list < std::pair<const std::string,RawTile> > TileList;
111 #endif
112 
114  typedef std::list < std::pair<const std::string,RawTile> >::iterator List_Iter;
115 
117 #ifdef HAVE_EXT_POOL_ALLOCATOR
118  typedef HASHMAP < std::string, List_Iter,
119  __gnu_cxx::hash< const std::string >,
120  std::equal_to< const std::string >,
121  __gnu_cxx::__pool_alloc< std::pair<const std::string, List_Iter> >
122  > TileMap;
123 #else
124  typedef HASHMAP < std::string,List_Iter > TileMap;
125 #endif
126 
127 
129  TileList tileList;
130 
132  TileMap tileMap;
133 
134 
136 
140  TileMap::iterator _touch( const std::string &key ) {
141  TileMap::iterator miter = tileMap.find( key );
142  if( miter == tileMap.end() ) return miter;
143  // Move the found node to the head of the list.
144  tileList.splice( tileList.begin(), tileList, miter->second );
145  return miter;
146  }
147 
148 
150 
154  void _remove( const TileMap::iterator &miter ) {
155  // Reduce our current size counter
156  currentSize -= ( (miter->second->second).dataLength +
157  ( (miter->second->second).filename.capacity() + (miter->second->first).capacity() )*sizeof(char) +
158  tileSize );
159  tileList.erase( miter->second );
160  tileMap.erase( miter );
161  }
162 
163 
165 
166  void _remove( const std::string &key ) {
167  TileMap::iterator miter = tileMap.find( key );
168  this->_remove( miter );
169  }
170 
171 
172 
173  public:
174 
176 
177  Cache( float max ) {
178  maxSize = (unsigned long)(max*1024000) ; currentSize = 0;
179  // 64 chars added at the end represents an average string length
180  tileSize = sizeof( RawTile ) + sizeof( std::pair<const std::string,RawTile> ) +
181  sizeof( std::pair<const std::string, List_Iter> ) + sizeof(char)*64 + sizeof(List_Iter);
182  };
183 
184 
186  ~Cache() {
187  clear();
188  }
189 
190 
192  void clear() {
193  tileList.clear();
194  tileMap.clear();
195  currentSize = 0;
196  }
197 
198 
200 
201  void insert( const RawTile& r ) {
202 
203  if( maxSize == 0 ) return;
204 
205  std::string key = this->getIndex( r.filename, r.resolution, r.tileNum,
207 
208  // Touch the key, if it exists
209  TileMap::iterator miter = this->_touch( key );
210 
211  // Check whether this tile exists in our cache
212  if( miter != tileMap.end() ){
213  // Check the timestamp and delete if necessary
214  if( miter->second->second.timestamp < r.timestamp ){
215  this->_remove( miter );
216  }
217  // If this index already exists and it is up to date, do nothing
218  else return;
219  }
220 
221  // Store the key if it doesn't already exist in our cache
222  // Ok, do the actual insert at the head of the list
223  tileList.push_front( std::make_pair(key,r) );
224 
225  // And store this in our map
226  List_Iter liter = tileList.begin();
227  tileMap[ key ] = liter;
228 
229  // Update our total current size variable. Use the string::capacity function
230  // rather than length() as std::string can allocate slightly more than necessary
231  // The +1 is for the terminating null byte
232  currentSize += (r.dataLength + (r.filename.capacity()+key.capacity())*sizeof(char) + tileSize);
233 
234  // Check to see if we need to remove an element due to exceeding max_size
235  while( currentSize > maxSize ) {
236  // Remove the last element
237  liter = tileList.end();
238  --liter;
239  this->_remove( liter->first );
240  }
241 
242  }
243 
244 
246  unsigned int getNumElements() { return tileList.size(); }
247 
248 
250  float getMemorySize() { return (float) ( currentSize / 1024000.0 ); }
251 
252 
254 
264  RawTile* getTile( std::string f, int r, int t, int h, int v, CompressionType c, int q ) {
265 
266  if( maxSize == 0 ) return NULL;
267 
268  std::string key = this->getIndex( f, r, t, h, v, c, q );
269 
270  TileMap::iterator miter = tileMap.find( key );
271  if( miter == tileMap.end() ) return NULL;
272  this->_touch( key );
273 
274  return &(miter->second->second);
275  }
276 
277 
279 
289  std::string getIndex( std::string f, int r, int t, int h, int v, CompressionType c, int q ) {
290  char tmp[1024];
291  snprintf( tmp, 1024, "%s:%d:%d:%d:%d:%d:%d", f.c_str(), r, t, h, v, c, q );
292  return std::string( tmp );
293  }
294 
295 
296 
297 };
298 
299 
300 
301 #endif
int vSequence
The vertical angle to which this tile belongs.
Definition: RawTile.h:59
unsigned int dataLength
The size of the data pointed to by data.
Definition: RawTile.h:82
int resolution
The resolution to which this tile belongs.
Definition: RawTile.h:53
void insert(const RawTile &r)
Insert a tile.
Definition: Cache.h:201
STL namespace.
int hSequence
The horizontal angle to which this tile belongs.
Definition: RawTile.h:56
int tileNum
The tile number for this tile.
Definition: RawTile.h:50
CompressionType compressionType
Compression type.
Definition: RawTile.h:62
float getMemorySize()
Return the number of MB stored.
Definition: Cache.h:250
std::string filename
Name of the file from which this tile comes.
Definition: RawTile.h:68
Cache to store raw tile data.
Definition: Cache.h:91
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:289
void clear()
Empty the cache.
Definition: Cache.h:192
~Cache()
Destructor.
Definition: Cache.h:186
int quality
Compression rate or quality.
Definition: RawTile.h:65
Cache(float max)
Constructor.
Definition: Cache.h:177
unsigned int getNumElements()
Return the number of tiles in the cache.
Definition: Cache.h:246
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:264
time_t timestamp
Tile timestamp.
Definition: RawTile.h:71
Class to represent a single image tile.
Definition: RawTile.h:45