GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
cache.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include <fcntl.h>
4#include <sys/types.h>
5#include <unistd.h>
6#include "raster3d_intern.h"
7
8/*---------------------------------------------------------------------------*/
9
10static int cacheRead_readFun(int tileIndex, void *tileBuf, void *closure)
11{
12 RASTER3D_Map *map = closure;
13
14 if (!Rast3d_read_tile(map, tileIndex, tileBuf, map->typeIntern)) {
15 Rast3d_error("cacheRead_readFun: error in Rast3d_read_tile");
16 return 0;
17 }
18 return 1;
19}
20
21/*---------------------------------------------------------------------------*/
22
23static int initCacheRead(RASTER3D_Map *map, int nCached)
24{
25 map->cache =
27 map->nTiles, cacheRead_readFun, map);
28 if (map->cache == NULL) {
29 Rast3d_error("initCacheRead: error in Rast3d_cache_new_read");
30 return 0;
31 }
32
33 return 1;
34}
35
36/*---------------------------------------------------------------------------*/
37
38/*
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:
44
45 index = - (fileposition + 2)
46
47 symmetrically, we use
48
49 fileposition = - (index + 2)
50
51 to convert from index to the fileposition.
52 */
53
54/*---------------------------------------------------------------------------*/
55
56static int cacheWrite_readFun(int tileIndex, void *tileBuf, void *closure)
57{
58 RASTER3D_Map *map = closure;
59 int index;
60 size_t nBytes;
61 size_t offs, offsLast;
62 ssize_t res;
63 long int pos;
64
65 pos = map->index[tileIndex];
66
67 /* tile has already been flushed onto output file or does not exist yet */
68 if (pos >=
69 -1) { /* note, Rast3d_read_tile takes care of the case pos == -1 */
71 return 1;
72 }
73
74 /* tile is in cache file */
75
76 pos = -pos - 2; /* pos is shifted by 2 to avoid 0 and -1 */
77
78 nBytes = map->tileSize * map->numLengthIntern;
79 offs = pos * (nBytes + sizeof(int));
80
81 /* seek tile and read it into buffer */
82
83 if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
84 Rast3d_error("cacheWrite_readFun: can't position file");
85 return 0;
86 }
87 if ((res = read(map->cacheFD, tileBuf, nBytes)) < 0 ||
88 (size_t)res != nBytes) {
89 Rast3d_error("cacheWrite_readFun: can't read file");
90 return 0;
91 }
92
93 /* remove it from index */
94
95 map->index[tileIndex] = -1;
96
97 /* if it is the last tile in the file we are done */
98 /* map->cachePosLast tells us the position of the last tile in the file */
99
100 if (map->cachePosLast == pos) {
101 map->cachePosLast--;
102 return 1;
103 }
104
105 /* otherwise we move the last tile in the file into the position of */
106 /* the tile we just read and update the hash information */
107
108 offsLast = map->cachePosLast * (nBytes + sizeof(int));
109
110 if (lseek(map->cacheFD, offsLast, SEEK_SET) == -1) {
111 Rast3d_error("cacheWrite_readFun: can't position file");
112 return 0;
113 }
114 if ((res = read(map->cacheFD, xdr, nBytes + sizeof(int))) < 0 ||
115 (size_t)res != nBytes + sizeof(int)) {
116 Rast3d_error("cacheWrite_readFun: can't read file");
117 return 0;
118 }
119
120 if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
121 Rast3d_error("cacheWrite_readFun: can't position file");
122 return 0;
123 }
124 if ((res = write(map->cacheFD, xdr, nBytes + sizeof(int))) < 0 ||
125 (size_t)res != nBytes + sizeof(int)) {
126 Rast3d_error("cacheWrite_readFun: can't write file");
127 return 0;
128 }
129
130 index = *((int *)((unsigned char *)xdr + nBytes));
131 map->index[index] = -pos - 2;
132
133 map->cachePosLast--;
134
135 return 1;
136}
137
138/*---------------------------------------------------------------------------*/
139
140static int cacheWrite_writeFun(int tileIndex, const void *tileBuf,
141 void *closure)
142{
143 RASTER3D_Map *map = closure;
144 size_t nBytes;
145 size_t offs;
146 ssize_t res;
147
148 if (map->index[tileIndex] != -1)
149 return 1;
150
151 map->cachePosLast++;
152 nBytes = map->tileSize * map->numLengthIntern;
153 offs = map->cachePosLast * (nBytes + sizeof(int));
154
155 if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
156 Rast3d_error("cacheWrite_writeFun: can't position file");
157 return 0;
158 }
159 if ((res = write(map->cacheFD, tileBuf, nBytes)) < 0 ||
160 (size_t)res != nBytes) {
161 Rast3d_error("cacheWrite_writeFun: can't write file");
162 return 0;
163 }
164 if (write(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
165 Rast3d_error("cacheWrite_writeFun: can't write file");
166 return 0;
167 }
168
169 map->index[tileIndex] = -map->cachePosLast - 2;
170
171 return 1;
172}
173
174/*---------------------------------------------------------------------------*/
175
176static int disposeCacheWrite(RASTER3D_Map *map)
177{
178 if (map->cacheFD >= 0) {
179 if (close(map->cacheFD) != 0) {
180 Rast3d_error("disposeCacheWrite: could not close file");
181 return 0;
182 }
183 remove(map->cacheFileName);
185 }
186
188
189 return 1;
190}
191
192/*---------------------------------------------------------------------------*/
193
194static int initCacheWrite(RASTER3D_Map *map, int nCached)
195{
196 map->cacheFileName = G_tempfile();
197 map->cacheFD = open(map->cacheFileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
198
199 if (map->cacheFD < 0) {
200 Rast3d_error("initCacheWrite: could not open file");
201 return 0;
202 }
203
204 map->cachePosLast = -1;
205
207 map->nTiles, cacheWrite_writeFun, map,
208 cacheWrite_readFun, map);
209
210 if (map->cache == NULL) {
211 disposeCacheWrite(map);
212 Rast3d_error("initCacheWrite: error in Rast3d_cache_new");
213 return 0;
214 }
215
216 return 1;
217}
218
219/*---------------------------------------------------------------------------*/
220
222{
223 if (map->operation == RASTER3D_READ_DATA) {
224 if (!initCacheRead(map, nCached)) {
225 Rast3d_error("Rast3d_init_cache: error in initCacheRead");
226 return 0;
227 }
228 return 1;
229 }
230
231 if (!initCacheWrite(map, nCached)) {
232 Rast3d_error("Rast3d_init_cache: error in initCacheWrite");
233 return 0;
234 }
235
236 return 1;
237}
238
239/*---------------------------------------------------------------------------*/
240
241static int disposeCacheRead(RASTER3D_Map *map)
242{
244 return 1;
245}
246
247/*---------------------------------------------------------------------------*/
248
250{
251 if (map->operation == RASTER3D_READ_DATA) {
252 if (!disposeCacheRead(map)) {
253 Rast3d_error("Rast3d_dispose_cache: error in disposeCacheRead");
254 return 0;
255 }
256 return 1;
257 }
258
259 if (!disposeCacheWrite(map)) {
260 Rast3d_error("Rast3d_dispose_cache: error in disposeCacheWrite");
261 return 0;
262 }
263
264 return 1;
265}
266
267/*---------------------------------------------------------------------------*/
268
269static int cacheFlushFun(int tileIndex, const void *tileBuf, void *closure)
270{
271 RASTER3D_Map *map = closure;
272
273 if (!Rast3d_write_tile(map, tileIndex, tileBuf, map->typeIntern)) {
274 Rast3d_error("cacheFlushFun: error in Rast3d_write_tile");
275 return 0;
276 }
277
278 return 1;
279}
280
281/*---------------------------------------------------------------------------*/
282
284{
285 size_t tileIndex, nBytes;
286 size_t offs;
287
288 if (map->operation == RASTER3D_READ_DATA) {
289 if (!Rast3d_cache_remove_all(map->cache)) {
291 "Rast3d_flush_all_tiles: error in Rast3d_cache_remove_all");
292 return 0;
293 }
294 return 1;
295 }
296
297 /* make cache write into output file instead of cache file */
298 Rast3d_cache_set_remove_fun(map->cache, cacheFlushFun, map);
299
300 /* first flush all the tiles which are in the file cache */
301
302 nBytes = map->tileSize * map->numLengthIntern;
303
304 while (map->cachePosLast >= 0) {
305 offs = map->cachePosLast * (nBytes + sizeof(int)) + nBytes;
306
307 if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
308 Rast3d_error("Rast3d_flush_all_tiles: can't position file");
309 return 0;
310 }
311 if (read(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
312 Rast3d_error("Rast3d_flush_all_tiles: can't read file");
313 return 0;
314 }
315
316 if (!Rast3d_cache_load(map->cache, tileIndex)) {
317 Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_load");
318 return 0;
319 }
320 if (!Rast3d_cache_flush(map->cache, tileIndex)) {
321 Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_flush");
322 return 0;
323 }
324 }
325
326 /* then flush all the tiles which remain in the non-file cache */
327 if (!Rast3d_cache_flush_all(map->cache)) {
328 Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_flush_all");
329 return 0;
330 }
331
332 /* now the cache should write into the cache file again */
333 Rast3d_cache_set_remove_fun(map->cache, cacheWrite_writeFun, map);
334
335 return 1;
336}
int Rast3d_flush_all_tiles(RASTER3D_Map *map)
Definition cache.c:283
int Rast3d_dispose_cache(RASTER3D_Map *map)
Definition cache.c:249
int Rast3d_init_cache(RASTER3D_Map *map, int nCached)
Definition cache.c:221
#define NULL
Definition ccmath.h:32
char * G_tempfile(void)
Returns a temporary file name.
Definition tempfile.c:62
int Rast3d_cache_flush_all(RASTER3D_cache *)
Definition cache1.c:451
void Rast3d_cache_dispose(RASTER3D_cache *)
Definition cache1.c:63
void Rast3d_free(void *)
Same as free (ptr).
int Rast3d_cache_load(RASTER3D_cache *, int)
Definition cache1.c:518
int Rast3d_cache_flush(RASTER3D_cache *, int)
Definition cache1.c:422
void * Rast3d_cache_new_read(int, int, int, read_fn *, void *)
Definition cache1.c:161
void Rast3d_cache_set_remove_fun(RASTER3D_cache *, write_fn *, void *)
int Rast3d_read_tile(RASTER3D_Map *, int, void *, int)
Reads tile with index tileIndex into the tile buffer. The cells are stored with type type which must ...
Definition tileread.c:150
void Rast3d_error(const char *,...) __attribute__((format(printf
int Rast3d_write_tile(RASTER3D_Map *, int, const void *, int)
Writes tile with index tileIndex to the file corresponding to map. It is assumed that the cells in ti...
Definition tilewrite.c:129
void * Rast3d_cache_new(int, int, int, write_fn *, void *, read_fn *, void *)
int Rast3d_cache_remove_all(RASTER3D_cache *)
Definition cache1.c:434
Header file for msvc/fcntl.c.
#define open
Definition fcntl.h:33
void * xdr
#define RASTER3D_READ_DATA
long * index
Definition raster3d.h:142
char * cacheFileName
Definition raster3d.h:163
long cachePosLast
Definition raster3d.h:164
void * cache
Definition raster3d.h:161
int operation
Definition raster3d.h:79
int numLengthIntern
Definition raster3d.h:176
#define read
Definition unistd.h:5
#define close
Definition unistd.h:8
#define write
Definition unistd.h:6