~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/g3d/g3dcache.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
}