GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
g3dcache.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 "G3d_intern.h"
7 
8 /*---------------------------------------------------------------------------*/
9 
10 static int cacheRead_readFun(int tileIndex, void *tileBuf, void *closure)
11 {
12  G3D_Map *map = closure;
13 
14  if (!G3d_readTile(map, tileIndex, tileBuf, map->typeIntern)) {
15  G3d_error("cacheRead_readFun: error in G3d_readTile");
16  return 0;
17  }
18  return 1;
19 }
20 
21 /*---------------------------------------------------------------------------*/
22 
23 static int initCacheRead(G3D_Map * map, int nCached)
24 {
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");
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  G3D_Map *map = closure;
59  int index, nBytes;
60  long pos, offs, offsLast;
61 
62  pos = map->index[tileIndex];
63 
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);
67  return 1;
68  }
69 
70  /* tile is in cache file */
71 
72  pos = -pos - 2; /* pos is shifted by 2 to avoid 0 and -1 */
73 
74  nBytes = map->tileSize * map->numLengthIntern;
75  offs = pos * (nBytes + sizeof(int));
76 
77  /* seek tile and read it into buffer */
78 
79  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
80  G3d_error("cacheWrite_readFun: can't position file");
81  return 0;
82  }
83  if (read(map->cacheFD, tileBuf, nBytes) != nBytes) {
84  G3d_error("cacheWrite_readFun: can't read file");
85  return 0;
86  }
87 
88  /* remove it from index */
89 
90  map->index[tileIndex] = -1;
91 
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 */
94 
95  if (map->cachePosLast == pos) {
96  map->cachePosLast--;
97  return 1;
98  }
99 
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 */
102 
103  offsLast = map->cachePosLast * (nBytes + sizeof(int));
104 
105  if (lseek(map->cacheFD, offsLast, SEEK_SET) == -1) {
106  G3d_error("cacheWrite_readFun: can't position file");
107  return 0;
108  }
109  if (read(map->cacheFD, xdr, nBytes + sizeof(int)) != nBytes + sizeof(int)) {
110  G3d_error("cacheWrite_readFun: can't read file");
111  return 0;
112  }
113 
114  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
115  G3d_error("cacheWrite_readFun: can't position file");
116  return 0;
117  }
118  if (write(map->cacheFD, xdr, nBytes + sizeof(int)) !=
119  nBytes + sizeof(int)) {
120  G3d_error("cacheWrite_readFun: can't write file");
121  return 0;
122  }
123 
124  index = *((int *)((unsigned char *)xdr + nBytes));
125  map->index[index] = -pos - 2;
126 
127  map->cachePosLast--;
128 
129  return 1;
130 }
131 
132 /*---------------------------------------------------------------------------*/
133 
134 static int
135 cacheWrite_writeFun(int tileIndex, const void *tileBuf, void *closure)
136 {
137  G3D_Map *map = closure;
138  int nBytes;
139  long offs;
140 
141  if (map->index[tileIndex] != -1)
142  return 1;
143 
144  map->cachePosLast++;
145  nBytes = map->tileSize * map->numLengthIntern;
146  offs = map->cachePosLast * (nBytes + sizeof(int));
147 
148  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
149  G3d_error("cacheWrite_writeFun: can't position file");
150  return 0;
151  }
152  if (write(map->cacheFD, tileBuf, nBytes) != nBytes) {
153  G3d_error("cacheWrite_writeFun: can't write file");
154  return 0;
155  }
156  if (write(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
157  G3d_error("cacheWrite_writeFun: can't write file");
158  return 0;
159  }
160 
161  map->index[tileIndex] = -map->cachePosLast - 2;
162 
163  return 1;
164 }
165 
166 /*---------------------------------------------------------------------------*/
167 
168 static int disposeCacheWrite(G3D_Map * map)
169 {
170  if (map->cacheFD >= 0) {
171  if (close(map->cacheFD) != 0) {
172  G3d_error("disposeCacheWrite: could not close file");
173  return 0;
174  }
175  remove(map->cacheFileName);
176  G3d_free(map->cacheFileName);
177  }
178 
179  G3d_cache_dispose(map->cache);
180 
181  return 1;
182 }
183 
184 /*---------------------------------------------------------------------------*/
185 
186 static int initCacheWrite(G3D_Map * map, int nCached)
187 {
188  map->cacheFileName = G_tempfile();
189  map->cacheFD = open(map->cacheFileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
190 
191  if (map->cacheFD < 0) {
192  G3d_error("initCacheWrite: could not open file");
193  return 0;
194  }
195 
196  map->cachePosLast = -1;
197 
198  map->cache = G3d_cache_new(nCached,
199  map->tileSize * map->numLengthIntern,
200  map->nTiles,
201  cacheWrite_writeFun, map,
202  cacheWrite_readFun, map);
203 
204  if (map->cache == NULL) {
205  disposeCacheWrite(map);
206  G3d_error("initCacheWrite: error in G3d_cache_new");
207  return 0;
208  }
209 
210  return 1;
211 }
212 
213 /*---------------------------------------------------------------------------*/
214 
215 int G3d_initCache(G3D_Map * map, int nCached)
216 {
217  if (map->operation == G3D_READ_DATA) {
218  if (!initCacheRead(map, nCached)) {
219  G3d_error("G3d_initCache: error in initCacheRead");
220  return 0;
221  }
222  return 1;
223  }
224 
225  if (!initCacheWrite(map, nCached)) {
226  G3d_error("G3d_initCache: error in initCacheWrite");
227  return 0;
228  }
229 
230  return 1;
231 }
232 
233 /*---------------------------------------------------------------------------*/
234 
235 static int disposeCacheRead(G3D_Map * map)
236 {
237  G3d_cache_dispose(map->cache);
238  return 1;
239 }
240 
241 /*---------------------------------------------------------------------------*/
242 
243 int G3d_disposeCache(G3D_Map * map)
244 {
245  if (map->operation == G3D_READ_DATA) {
246  if (!disposeCacheRead(map)) {
247  G3d_error("G3d_disposeCache: error in disposeCacheRead");
248  return 0;
249  }
250  return 1;
251  }
252 
253  if (!disposeCacheWrite(map)) {
254  G3d_error("G3d_disposeCache: error in disposeCacheWrite");
255  return 0;
256  }
257 
258  return 1;
259 }
260 
261 
262 /*---------------------------------------------------------------------------*/
263 
264 static int cacheFlushFun(int tileIndex, const void *tileBuf, void *closure)
265 {
266  G3D_Map *map = closure;
267 
268  if (!G3d_writeTile(map, tileIndex, tileBuf, map->typeIntern)) {
269  G3d_error("cacheFlushFun: error in G3d_writeTile");
270  return 0;
271  }
272 
273  return 1;
274 }
275 
276 /*---------------------------------------------------------------------------*/
277 
278 int G3d_flushAllTiles(G3D_Map * map)
279 {
280  int tileIndex, nBytes;
281  long offs;
282 
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");
286  return 0;
287  }
288  return 1;
289  }
290 
291  /* make cache write into output file instead of cache file */
292  G3d_cache_set_removeFun(map->cache, cacheFlushFun, map);
293 
294  /* first flush all the tiles which are in the file cache */
295 
296  nBytes = map->tileSize * map->numLengthIntern;
297 
298  while (map->cachePosLast >= 0) {
299  offs = map->cachePosLast * (nBytes + sizeof(int)) + nBytes;
300 
301  if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
302  G3d_error("G3d_flushAllTiles: can't position file");
303  return 0;
304  }
305  if (read(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
306  G3d_error("G3d_flushAllTiles: can't read file");
307  return 0;
308  }
309 
310  if (!G3d_cache_load(map->cache, tileIndex)) {
311  G3d_error("G3d_flushAllTiles: error in G3d_cache_load");
312  return 0;
313  }
314  if (!G3d_cache_flush(map->cache, tileIndex)) {
315  G3d_error("G3d_flushAllTiles: error in G3d_cache_flush");
316  return 0;
317  }
318  }
319 
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");
323  return 0;
324  }
325 
326  /* now the cache should write into the cache file again */
327  G3d_cache_set_removeFun(map->cache, cacheWrite_writeFun, map);
328 
329  return 1;
330 }
int G3d_writeTile(G3D_Map *map, int tileIndex, const void *tile, int type)
Writes tile with index tileIndex to the file corresponding to map. It is assumed that the cells in ti...
Definition: tilewrite.c:128
void * G3d_cache_new(int nofElts, int sizeOfElts, int nofNames, int(*eltRemoveFun)(), void *eltRemoveFunData, int(*eltLoadFun)(), void *eltLoadFunData)
Definition: cache.c:88
int G3d_cache_remove_all(G3D_cache *c)
Definition: cache.c:433
int G3d_initCache(G3D_Map *map, int nCached)
Definition: g3dcache.c:215
int G3d_disposeCache(G3D_Map *map)
Definition: g3dcache.c:243
void G3d_free(void *buf)
Same as free (ptr).
Definition: g3dalloc.c:71
void G3d_error(const char *msg,...)
Definition: g3derror.c:75
int G3d_flushAllTiles(G3D_Map *map)
Definition: g3dcache.c:278
#define G3D_READ_DATA
Definition: G3d_intern.h:20
tuple pos
Definition: tools.py:1367
int G3d_cache_load(G3D_cache *c, int name)
Definition: cache.c:516
char * G_tempfile(void)
Returns a temporary file name.
Definition: tempfile.c:47
int
Definition: g3dcolor.c:48
int G3d_cache_flush(G3D_cache *c, int name)
Definition: cache.c:421
void G3d_cache_dispose(G3D_cache *c)
Definition: cache.c:65
int G3d_cache_flush_all(G3D_cache *c)
Definition: cache.c:450
return NULL
Definition: dbfopen.c:1394
void * G3d_cache_new_read(int nofElts, int sizeOfElts, int nofNames, read_fn *eltLoadFun, void *eltLoadFunData)
Definition: cache.c:162
void * xdr
Definition: g3d/header.c:14
void G3d_cache_set_removeFun(G3D_cache *c, int(*eltRemoveFun)(), void *eltRemoveFunData)
Definition: cache.c:143
int G3d_readTile(G3D_Map *map, int tileIndex, void *tile, int type)
Reads tile with index tileIndex into the tile buffer. The cells are stored with type type which must ...
Definition: tileread.c:145