1 |
/* |
2 |
======================================================================= |
3 |
Cache for out-of-core octree. |
4 |
|
5 |
Uses an LRU page replacement scheme. Page table nodes are stored in |
6 |
order of reference in a doubly linked list, with the most recently used |
7 |
(MRU) page at the head, and the least recently used (LRU) at the tail. |
8 |
|
9 |
Nodes are referenced by the page's base address via a hashtable for |
10 |
constant time access (in the absence of hash collisions). Hash |
11 |
collisions can be limited by adjusting the hashtable load factor |
12 |
OOC_CACHE_LOAD; this is the fraction of the number of pages that will |
13 |
actually be cached. |
14 |
|
15 |
Roland Schregle (roland.schregle@{hslu.ch, gmail.com}) |
16 |
(c) Lucerne University of Applied Sciences and Arts, |
17 |
supported by the Swiss National Science Foundation (SNSF, #147053) |
18 |
======================================================================= |
19 |
|
20 |
$Id: ooccache.h,v 2.1 2016/05/17 17:39:47 rschregle Exp $ |
21 |
*/ |
22 |
|
23 |
|
24 |
#ifndef OOC_CACHE_H |
25 |
#define OOC_CACHE_H |
26 |
|
27 |
#include <stdio.h> |
28 |
#include <stdint.h> |
29 |
|
30 |
#ifdef __cplusplus |
31 |
extern "C" { |
32 |
#endif |
33 |
|
34 |
/* Hashtable load factor to limit hash collisions */ |
35 |
#define OOC_CACHE_LOAD 0.75 |
36 |
|
37 |
/* Minimum number of cache pages */ |
38 |
#define OOC_CACHE_MINPAGES 8 |
39 |
|
40 |
/* Hashing function for key -> pagetable mapping (assumes n is prime) */ |
41 |
#define OOC_CACHE_PRIME 19603 |
42 |
#define OOC_CACHE_HASH(k,n) ((k) * OOC_CACHE_PRIME % (n)) |
43 |
|
44 |
/* Next index in pagetable probe sequence for collision resolution */ |
45 |
#define OOC_CACHE_NEXT(i,n) (((i) + 1) % (n)) |
46 |
|
47 |
/* Cache key and index types */ |
48 |
typedef uint32_t OOC_CacheKey; |
49 |
typedef uint32_t OOC_CacheIdx; |
50 |
|
51 |
/* Undefined value for cache index */ |
52 |
#define OOC_CACHEIDX_NULL UINT32_MAX |
53 |
|
54 |
|
55 |
|
56 |
typedef struct { |
57 |
OOC_CacheKey key; /* Key to resolve hashing collisions */ |
58 |
OOC_CacheIdx prev, next; /* Previous/next page in history */ |
59 |
void *data; /* Start of page data */ |
60 |
} OOC_CacheNode; |
61 |
|
62 |
typedef struct { |
63 |
unsigned recSize, /* Data record size in bytes */ |
64 |
recPerPage; /* Page size in number of records */ |
65 |
unsigned long pageSize; /* Page size in bytes (precomp) */ |
66 |
OOC_CacheIdx pageCnt, /* Num pages used */ |
67 |
numPages; /* Pagetable size */ |
68 |
|
69 |
/* NOTE: The hashtable load factor limits the number of pages actually |
70 |
* used, such that pageCnt <= OOC_CACHE_LOAD * numPages */ |
71 |
|
72 |
OOC_CacheNode *pageTable; /* Pagetable with numPages nodes */ |
73 |
OOC_CacheIdx mru, lru; /* Most/least recently used page |
74 |
== head/tail of page history */ |
75 |
OOC_CacheKey lastKey; /* Previous key to detect repeat lookups */ |
76 |
OOC_CacheNode *lastPage; /* Previous page for repeat lookups */ |
77 |
|
78 |
unsigned long numReads, /* Statistics counters */ |
79 |
numHits, |
80 |
numColl, |
81 |
numRept; |
82 |
} OOC_Cache; |
83 |
|
84 |
|
85 |
|
86 |
/* Initialise cache containing up to numPages pages; this is rounded up |
87 |
* the next prime number to reduce hash clustering and collisions. The |
88 |
* page size recPerPage is specified in units of records of size recSize |
89 |
* bytes. Returns 0 on success, else -1. */ |
90 |
int OOC_CacheInit (OOC_Cache *cache, unsigned numPages, |
91 |
unsigned recPerPage, unsigned recSize); |
92 |
|
93 |
/* Return pointer to cached record with index recIdx, loading from file |
94 |
* and possibly evicting the LRU page */ |
95 |
void *OOC_CacheData (OOC_Cache *cache, FILE *file, unsigned long recIdx); |
96 |
|
97 |
/* Delete cache and free allocated pages */ |
98 |
void OOC_DeleteCache (OOC_Cache *cache); |
99 |
|
100 |
#ifdef __cplusplus |
101 |
} |
102 |
#endif |
103 |
|
104 |
#endif |