GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
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 
10 static 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 
23 static int initCacheRead(RASTER3D_Map * map, int nCached)
24 {
25  map->cache = Rast3d_cache_new_read(nCached,
26  map->tileSize * map->numLengthIntern,
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 
56 static 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  long int pos;
63 
64  pos = map->index[tileIndex];
65 
66  /* tile has already been flushed onto output file or does not exist yet */
67  if (pos >= -1) { /* note, Rast3d_read_tile takes care of the case pos == -1 */
68  Rast3d_read_tile(map, tileIndex, tileBuf, map->typeIntern);
69  return 1;
70  }
71 
72  /* tile is in cache file */
73 
74  pos = -pos - 2; /* pos is shifted by 2 to avoid 0 and -1 */
75 
76  nBytes = map->tileSize * map->numLengthIntern;
77  offs = pos * (nBytes + sizeof(int));
78 
79  /* seek tile and read it into buffer */
80 
81  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
82  Rast3d_error("cacheWrite_readFun: can't position file");
83  return 0;
84  }
85  if (read(map->cacheFD, tileBuf, nBytes) != nBytes) {
86  Rast3d_error("cacheWrite_readFun: can't read file");
87  return 0;
88  }
89 
90  /* remove it from index */
91 
92  map->index[tileIndex] = -1;
93 
94  /* if it is the last tile in the file we are done */
95  /* map->cachePosLast tells us the position of the last tile in the file */
96 
97  if (map->cachePosLast == pos) {
98  map->cachePosLast--;
99  return 1;
100  }
101 
102  /* otherwise we move the last tile in the file into the position of */
103  /* the tile we just read and update the hash information */
104 
105  offsLast = map->cachePosLast * (nBytes + sizeof(int));
106 
107  if (lseek(map->cacheFD, offsLast, SEEK_SET) == -1) {
108  Rast3d_error("cacheWrite_readFun: can't position file");
109  return 0;
110  }
111  if (read(map->cacheFD, xdr, nBytes + sizeof(int)) != nBytes + sizeof(int)) {
112  Rast3d_error("cacheWrite_readFun: can't read file");
113  return 0;
114  }
115 
116  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
117  Rast3d_error("cacheWrite_readFun: can't position file");
118  return 0;
119  }
120  if (write(map->cacheFD, xdr, nBytes + sizeof(int)) !=
121  nBytes + sizeof(int)) {
122  Rast3d_error("cacheWrite_readFun: can't write file");
123  return 0;
124  }
125 
126  index = *((int*)((unsigned char *)xdr + nBytes));
127  map->index[index] = -pos - 2;
128 
129  map->cachePosLast--;
130 
131  return 1;
132 }
133 
134 /*---------------------------------------------------------------------------*/
135 
136 static int
137 cacheWrite_writeFun(int tileIndex, const void *tileBuf, void *closure)
138 {
139  RASTER3D_Map *map = closure;
140  size_t nBytes;
141  size_t offs;
142 
143  if (map->index[tileIndex] != -1)
144  return 1;
145 
146  map->cachePosLast++;
147  nBytes = map->tileSize * map->numLengthIntern;
148  offs = map->cachePosLast * (nBytes + sizeof(int));
149 
150  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
151  Rast3d_error("cacheWrite_writeFun: can't position file");
152  return 0;
153  }
154  if (write(map->cacheFD, tileBuf, nBytes) != nBytes) {
155  Rast3d_error("cacheWrite_writeFun: can't write file");
156  return 0;
157  }
158  if (write(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
159  Rast3d_error("cacheWrite_writeFun: can't write file");
160  return 0;
161  }
162 
163  map->index[tileIndex] = -map->cachePosLast - 2;
164 
165  return 1;
166 }
167 
168 /*---------------------------------------------------------------------------*/
169 
170 static int disposeCacheWrite(RASTER3D_Map * map)
171 {
172  if (map->cacheFD >= 0) {
173  if (close(map->cacheFD) != 0) {
174  Rast3d_error("disposeCacheWrite: could not close file");
175  return 0;
176  }
177  remove(map->cacheFileName);
179  }
180 
182 
183  return 1;
184 }
185 
186 /*---------------------------------------------------------------------------*/
187 
188 static int initCacheWrite(RASTER3D_Map * map, int nCached)
189 {
190  map->cacheFileName = G_tempfile();
191  map->cacheFD = open(map->cacheFileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
192 
193  if (map->cacheFD < 0) {
194  Rast3d_error("initCacheWrite: could not open file");
195  return 0;
196  }
197 
198  map->cachePosLast = -1;
199 
200  map->cache = Rast3d_cache_new(nCached,
201  map->tileSize * map->numLengthIntern,
202  map->nTiles,
203  cacheWrite_writeFun, map,
204  cacheWrite_readFun, map);
205 
206  if (map->cache == NULL) {
207  disposeCacheWrite(map);
208  Rast3d_error("initCacheWrite: error in Rast3d_cache_new");
209  return 0;
210  }
211 
212  return 1;
213 }
214 
215 /*---------------------------------------------------------------------------*/
216 
217 int Rast3d_init_cache(RASTER3D_Map * map, int nCached)
218 {
219  if (map->operation == RASTER3D_READ_DATA) {
220  if (!initCacheRead(map, nCached)) {
221  Rast3d_error("Rast3d_init_cache: error in initCacheRead");
222  return 0;
223  }
224  return 1;
225  }
226 
227  if (!initCacheWrite(map, nCached)) {
228  Rast3d_error("Rast3d_init_cache: error in initCacheWrite");
229  return 0;
230  }
231 
232  return 1;
233 }
234 
235 /*---------------------------------------------------------------------------*/
236 
237 static int disposeCacheRead(RASTER3D_Map * map)
238 {
240  return 1;
241 }
242 
243 /*---------------------------------------------------------------------------*/
244 
246 {
247  if (map->operation == RASTER3D_READ_DATA) {
248  if (!disposeCacheRead(map)) {
249  Rast3d_error("Rast3d_dispose_cache: error in disposeCacheRead");
250  return 0;
251  }
252  return 1;
253  }
254 
255  if (!disposeCacheWrite(map)) {
256  Rast3d_error("Rast3d_dispose_cache: error in disposeCacheWrite");
257  return 0;
258  }
259 
260  return 1;
261 }
262 
263 
264 /*---------------------------------------------------------------------------*/
265 
266 static int cacheFlushFun(int tileIndex, const void *tileBuf, void *closure)
267 {
268  RASTER3D_Map *map = closure;
269 
270  if (!Rast3d_write_tile(map, tileIndex, tileBuf, map->typeIntern)) {
271  Rast3d_error("cacheFlushFun: error in Rast3d_write_tile");
272  return 0;
273  }
274 
275  return 1;
276 }
277 
278 /*---------------------------------------------------------------------------*/
279 
281 {
282  size_t tileIndex, nBytes;
283  size_t offs;
284 
285  if (map->operation == RASTER3D_READ_DATA) {
286  if (!Rast3d_cache_remove_all(map->cache)) {
287  Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_remove_all");
288  return 0;
289  }
290  return 1;
291  }
292 
293  /* make cache write into output file instead of cache file */
294  Rast3d_cache_set_remove_fun(map->cache, cacheFlushFun, map);
295 
296  /* first flush all the tiles which are in the file cache */
297 
298  nBytes = map->tileSize * map->numLengthIntern;
299 
300  while (map->cachePosLast >= 0) {
301  offs = map->cachePosLast * (nBytes + sizeof(int)) + nBytes;
302 
303  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
304  Rast3d_error("Rast3d_flush_all_tiles: can't position file");
305  return 0;
306  }
307  if (read(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
308  Rast3d_error("Rast3d_flush_all_tiles: can't read file");
309  return 0;
310  }
311 
312  if (!Rast3d_cache_load(map->cache, tileIndex)) {
313  Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_load");
314  return 0;
315  }
316  if (!Rast3d_cache_flush(map->cache, tileIndex)) {
317  Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_flush");
318  return 0;
319  }
320  }
321 
322  /* then flush all the tiles which remain in the non-file cache */
323  if (!Rast3d_cache_flush_all(map->cache)) {
324  Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_flush_all");
325  return 0;
326  }
327 
328  /* now the cache should write into the cache file again */
329  Rast3d_cache_set_remove_fun(map->cache, cacheWrite_writeFun, map);
330 
331  return 1;
332 }
int numLengthIntern
Definition: raster3d.h:175
int Rast3d_init_cache(RASTER3D_Map *map, int nCached)
Definition: cache.c:217
void * cache
Definition: raster3d.h:160
long cachePosLast
Definition: raster3d.h:163
int typeIntern
Definition: raster3d.h:149
int operation
Definition: raster3d.h:81
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:145
#define NULL
Definition: ccmath.h:32
int Rast3d_cache_flush(RASTER3D_cache *, int)
Definition: cache1.c:420
int Rast3d_dispose_cache(RASTER3D_Map *map)
Definition: cache.c:245
void * xdr
void Rast3d_error(const char *,...) __attribute__((format(printf
long * index
Definition: raster3d.h:141
char * G_tempfile(void)
Returns a temporary file name.
Definition: tempfile.c:62
char * cacheFileName
Definition: raster3d.h:162
#define RASTER3D_READ_DATA
int Rast3d_flush_all_tiles(RASTER3D_Map *map)
Definition: cache.c:280
int Rast3d_cache_load(RASTER3D_cache *, int)
Definition: cache1.c:515
void Rast3d_cache_set_remove_fun(RASTER3D_cache *, write_fn *, void *)
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:127
int tileSize
Definition: raster3d.h:179
void * Rast3d_cache_new(int, int, int, write_fn *, void *, read_fn *, void *)
int Rast3d_cache_flush_all(RASTER3D_cache *)
Definition: cache1.c:449
void * Rast3d_cache_new_read(int, int, int, read_fn *, void *)
Definition: cache1.c:161
int Rast3d_cache_remove_all(RASTER3D_cache *)
Definition: cache1.c:432
void Rast3d_free(void *)
Same as free (ptr).
void Rast3d_cache_dispose(RASTER3D_cache *)
Definition: cache1.c:65