6
#include "G3d_intern.h"
8
/*---------------------------------------------------------------------------*/
10
static int cacheRead_readFun(int tileIndex, void *tileBuf, void *closure)
12
G3D_Map *map = closure;
14
if (!G3d_readTile(map, tileIndex, tileBuf, map->typeIntern)) {
15
G3d_error("cacheRead_readFun: error in G3d_readTile");
21
/*---------------------------------------------------------------------------*/
23
static int initCacheRead(G3D_Map * map, int nCached)
25
map->cache = G3d_cache_new_read(nCached,
26
map->tileSize * map->numLengthIntern,
27
map->nTiles, cacheRead_readFun, map);
28
if (map->cache == NULL) {
29
G3d_error("initCacheRead: error in G3d_cache_new_read");
36
/*---------------------------------------------------------------------------*/
39
the map->index array is (ab)used to store the positions of the tiles in the
40
file-cash. we can do this since we maintain the invariant for every tile
41
that it is either in no file (index == -1) or in either the output-file
42
(index >= 0) or the cash-file (index <= -2). to convert the file-position in
43
the cash-file into an index we use the following function:
45
index = - (fileposition + 2)
49
fileposition = - (index + 2)
51
to convert from index to the fileposition.
54
/*---------------------------------------------------------------------------*/
56
static int cacheWrite_readFun(int tileIndex, void *tileBuf, void *closure)
58
G3D_Map *map = closure;
60
long pos, offs, offsLast;
62
pos = map->index[tileIndex];
64
/* tile has already been flushed onto output file or does not exist yet */
65
if (pos >= -1) { /* note, G3d_readTile takes care of the case pos == -1 */
66
G3d_readTile(map, tileIndex, tileBuf, map->typeIntern);
70
/* tile is in cache file */
72
pos = -pos - 2; /* pos is shifted by 2 to avoid 0 and -1 */
74
nBytes = map->tileSize * map->numLengthIntern;
75
offs = pos * (nBytes + sizeof(int));
77
/* seek tile and read it into buffer */
79
if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
80
G3d_error("cacheWrite_readFun: can't position file");
83
if (read(map->cacheFD, tileBuf, nBytes) != nBytes) {
84
G3d_error("cacheWrite_readFun: can't read file");
88
/* remove it from index */
90
map->index[tileIndex] = -1;
92
/* if it is the last tile in the file we are done */
93
/* map->cachePosLast tells us the position of the last tile in the file */
95
if (map->cachePosLast == pos) {
100
/* otherwise we move the last tile in the file into the position of */
101
/* the tile we just read and update the hash information */
103
offsLast = map->cachePosLast * (nBytes + sizeof(int));
105
if (lseek(map->cacheFD, offsLast, SEEK_SET) == -1) {
106
G3d_error("cacheWrite_readFun: can't position file");
109
if (read(map->cacheFD, xdr, nBytes + sizeof(int)) != nBytes + sizeof(int)) {
110
G3d_error("cacheWrite_readFun: can't read file");
114
if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
115
G3d_error("cacheWrite_readFun: can't position file");
118
if (write(map->cacheFD, xdr, nBytes + sizeof(int)) !=
119
nBytes + sizeof(int)) {
120
G3d_error("cacheWrite_readFun: can't write file");
124
index = *((int *)((unsigned char *)xdr + nBytes));
125
map->index[index] = -pos - 2;
132
/*---------------------------------------------------------------------------*/
135
cacheWrite_writeFun(int tileIndex, const void *tileBuf, void *closure)
137
G3D_Map *map = closure;
141
if (map->index[tileIndex] != -1)
145
nBytes = map->tileSize * map->numLengthIntern;
146
offs = map->cachePosLast * (nBytes + sizeof(int));
148
if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
149
G3d_error("cacheWrite_writeFun: can't position file");
152
if (write(map->cacheFD, tileBuf, nBytes) != nBytes) {
153
G3d_error("cacheWrite_writeFun: can't write file");
156
if (write(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
157
G3d_error("cacheWrite_writeFun: can't write file");
161
map->index[tileIndex] = -map->cachePosLast - 2;
166
/*---------------------------------------------------------------------------*/
168
static int disposeCacheWrite(G3D_Map * map)
170
if (map->cacheFD >= 0) {
171
if (close(map->cacheFD) != 0) {
172
G3d_error("disposeCacheWrite: could not close file");
175
remove(map->cacheFileName);
176
G3d_free(map->cacheFileName);
179
G3d_cache_dispose(map->cache);
184
/*---------------------------------------------------------------------------*/
186
static int initCacheWrite(G3D_Map * map, int nCached)
188
map->cacheFileName = G_tempfile();
189
map->cacheFD = open(map->cacheFileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
191
if (map->cacheFD < 0) {
192
G3d_error("initCacheWrite: could not open file");
196
map->cachePosLast = -1;
198
map->cache = G3d_cache_new(nCached,
199
map->tileSize * map->numLengthIntern,
201
cacheWrite_writeFun, map,
202
cacheWrite_readFun, map);
204
if (map->cache == NULL) {
205
disposeCacheWrite(map);
206
G3d_error("initCacheWrite: error in G3d_cache_new");
213
/*---------------------------------------------------------------------------*/
215
int G3d_initCache(G3D_Map * map, int nCached)
217
if (map->operation == G3D_READ_DATA) {
218
if (!initCacheRead(map, nCached)) {
219
G3d_error("G3d_initCache: error in initCacheRead");
225
if (!initCacheWrite(map, nCached)) {
226
G3d_error("G3d_initCache: error in initCacheWrite");
233
/*---------------------------------------------------------------------------*/
235
static int disposeCacheRead(G3D_Map * map)
237
G3d_cache_dispose(map->cache);
241
/*---------------------------------------------------------------------------*/
243
int G3d_disposeCache(G3D_Map * map)
245
if (map->operation == G3D_READ_DATA) {
246
if (!disposeCacheRead(map)) {
247
G3d_error("G3d_disposeCache: error in disposeCacheRead");
253
if (!disposeCacheWrite(map)) {
254
G3d_error("G3d_disposeCache: error in disposeCacheWrite");
262
/*---------------------------------------------------------------------------*/
264
static int cacheFlushFun(int tileIndex, const void *tileBuf, void *closure)
266
G3D_Map *map = closure;
268
if (!G3d_writeTile(map, tileIndex, tileBuf, map->typeIntern)) {
269
G3d_error("cacheFlushFun: error in G3d_writeTile");
276
/*---------------------------------------------------------------------------*/
278
int G3d_flushAllTiles(G3D_Map * map)
280
int tileIndex, nBytes;
283
if (map->operation == G3D_READ_DATA) {
284
if (!G3d_cache_remove_all(map->cache)) {
285
G3d_error("G3d_flushAllTiles: error in G3d_cache_remove_all");
291
/* make cache write into output file instead of cache file */
292
G3d_cache_set_removeFun(map->cache, cacheFlushFun, map);
294
/* first flush all the tiles which are in the file cache */
296
nBytes = map->tileSize * map->numLengthIntern;
298
while (map->cachePosLast >= 0) {
299
offs = map->cachePosLast * (nBytes + sizeof(int)) + nBytes;
301
if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
302
G3d_error("G3d_flushAllTiles: can't position file");
305
if (read(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
306
G3d_error("G3d_flushAllTiles: can't read file");
310
if (!G3d_cache_load(map->cache, tileIndex)) {
311
G3d_error("G3d_flushAllTiles: error in G3d_cache_load");
314
if (!G3d_cache_flush(map->cache, tileIndex)) {
315
G3d_error("G3d_flushAllTiles: error in G3d_cache_flush");
320
/* then flush all the tiles which remain in the non-file cache */
321
if (!G3d_cache_flush_all(map->cache)) {
322
G3d_error("G3d_flushAllTiles: error in G3d_cache_flush_all");
326
/* now the cache should write into the cache file again */
327
G3d_cache_set_removeFun(map->cache, cacheWrite_writeFun, map);