123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include "raster3d_intern.h"
- /*---------------------------------------------------------------------------*/
- static int cacheRead_readFun(int tileIndex, void *tileBuf, void *closure)
- {
- RASTER3D_Map *map = closure;
- if (!Rast3d_read_tile(map, tileIndex, tileBuf, map->typeIntern)) {
- Rast3d_error("cacheRead_readFun: error in Rast3d_read_tile");
- return 0;
- }
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- static int initCacheRead(RASTER3D_Map * map, int nCached)
- {
- map->cache = Rast3d_cache_new_read(nCached,
- map->tileSize * map->numLengthIntern,
- map->nTiles, cacheRead_readFun, map);
- if (map->cache == NULL) {
- Rast3d_error("initCacheRead: error in Rast3d_cache_new_read");
- return 0;
- }
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- /*
- the map->index array is (ab)used to store the positions of the tiles in the
- file-cash. we can do this since we maintain the invariant for every tile
- that it is either in no file (index == -1) or in either the output-file
- (index >= 0) or the cash-file (index <= -2). to convert the file-position in
- the cash-file into an index we use the following function:
- index = - (fileposition + 2)
- symmetrically, we use
- fileposition = - (index + 2)
- to convert from index to the fileposition.
- */
- /*---------------------------------------------------------------------------*/
- static int cacheWrite_readFun(int tileIndex, void *tileBuf, void *closure)
- {
- RASTER3D_Map *map = closure;
- int index;
- size_t nBytes;
- size_t offs, offsLast;
- long int pos;
- pos = map->index[tileIndex];
- /* tile has already been flushed onto output file or does not exist yet */
- if (pos >= -1) { /* note, Rast3d_read_tile takes care of the case pos == -1 */
- Rast3d_read_tile(map, tileIndex, tileBuf, map->typeIntern);
- return 1;
- }
- /* tile is in cache file */
- pos = -pos - 2; /* pos is shifted by 2 to avoid 0 and -1 */
- nBytes = map->tileSize * map->numLengthIntern;
- offs = pos * (nBytes + sizeof(int));
- /* seek tile and read it into buffer */
- if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
- Rast3d_error("cacheWrite_readFun: can't position file");
- return 0;
- }
- if (read(map->cacheFD, tileBuf, nBytes) != nBytes) {
- Rast3d_error("cacheWrite_readFun: can't read file");
- return 0;
- }
- /* remove it from index */
- map->index[tileIndex] = -1;
- /* if it is the last tile in the file we are done */
- /* map->cachePosLast tells us the position of the last tile in the file */
- if (map->cachePosLast == pos) {
- map->cachePosLast--;
- return 1;
- }
- /* otherwise we move the last tile in the file into the position of */
- /* the tile we just read and update the hash information */
- offsLast = map->cachePosLast * (nBytes + sizeof(int));
- if (lseek(map->cacheFD, offsLast, SEEK_SET) == -1) {
- Rast3d_error("cacheWrite_readFun: can't position file");
- return 0;
- }
- if (read(map->cacheFD, xdr, nBytes + sizeof(int)) != nBytes + sizeof(int)) {
- Rast3d_error("cacheWrite_readFun: can't read file");
- return 0;
- }
- if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
- Rast3d_error("cacheWrite_readFun: can't position file");
- return 0;
- }
- if (write(map->cacheFD, xdr, nBytes + sizeof(int)) !=
- nBytes + sizeof(int)) {
- Rast3d_error("cacheWrite_readFun: can't write file");
- return 0;
- }
- index = *((int*)((unsigned char *)xdr + nBytes));
- map->index[index] = -pos - 2;
- map->cachePosLast--;
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- static int
- cacheWrite_writeFun(int tileIndex, const void *tileBuf, void *closure)
- {
- RASTER3D_Map *map = closure;
- size_t nBytes;
- size_t offs;
- if (map->index[tileIndex] != -1)
- return 1;
- map->cachePosLast++;
- nBytes = map->tileSize * map->numLengthIntern;
- offs = map->cachePosLast * (nBytes + sizeof(int));
- if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
- Rast3d_error("cacheWrite_writeFun: can't position file");
- return 0;
- }
- if (write(map->cacheFD, tileBuf, nBytes) != nBytes) {
- Rast3d_error("cacheWrite_writeFun: can't write file");
- return 0;
- }
- if (write(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
- Rast3d_error("cacheWrite_writeFun: can't write file");
- return 0;
- }
- map->index[tileIndex] = -map->cachePosLast - 2;
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- static int disposeCacheWrite(RASTER3D_Map * map)
- {
- if (map->cacheFD >= 0) {
- if (close(map->cacheFD) != 0) {
- Rast3d_error("disposeCacheWrite: could not close file");
- return 0;
- }
- remove(map->cacheFileName);
- Rast3d_free(map->cacheFileName);
- }
- Rast3d_cache_dispose(map->cache);
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- static int initCacheWrite(RASTER3D_Map * map, int nCached)
- {
- map->cacheFileName = G_tempfile();
- map->cacheFD = open(map->cacheFileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
- if (map->cacheFD < 0) {
- Rast3d_error("initCacheWrite: could not open file");
- return 0;
- }
- map->cachePosLast = -1;
- map->cache = Rast3d_cache_new(nCached,
- map->tileSize * map->numLengthIntern,
- map->nTiles,
- cacheWrite_writeFun, map,
- cacheWrite_readFun, map);
- if (map->cache == NULL) {
- disposeCacheWrite(map);
- Rast3d_error("initCacheWrite: error in Rast3d_cache_new");
- return 0;
- }
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- int Rast3d_init_cache(RASTER3D_Map * map, int nCached)
- {
- if (map->operation == RASTER3D_READ_DATA) {
- if (!initCacheRead(map, nCached)) {
- Rast3d_error("Rast3d_init_cache: error in initCacheRead");
- return 0;
- }
- return 1;
- }
- if (!initCacheWrite(map, nCached)) {
- Rast3d_error("Rast3d_init_cache: error in initCacheWrite");
- return 0;
- }
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- static int disposeCacheRead(RASTER3D_Map * map)
- {
- Rast3d_cache_dispose(map->cache);
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- int Rast3d_dispose_cache(RASTER3D_Map * map)
- {
- if (map->operation == RASTER3D_READ_DATA) {
- if (!disposeCacheRead(map)) {
- Rast3d_error("Rast3d_dispose_cache: error in disposeCacheRead");
- return 0;
- }
- return 1;
- }
- if (!disposeCacheWrite(map)) {
- Rast3d_error("Rast3d_dispose_cache: error in disposeCacheWrite");
- return 0;
- }
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- static int cacheFlushFun(int tileIndex, const void *tileBuf, void *closure)
- {
- RASTER3D_Map *map = closure;
- if (!Rast3d_write_tile(map, tileIndex, tileBuf, map->typeIntern)) {
- Rast3d_error("cacheFlushFun: error in Rast3d_write_tile");
- return 0;
- }
- return 1;
- }
- /*---------------------------------------------------------------------------*/
- int Rast3d_flush_all_tiles(RASTER3D_Map * map)
- {
- size_t tileIndex, nBytes;
- size_t offs;
- if (map->operation == RASTER3D_READ_DATA) {
- if (!Rast3d_cache_remove_all(map->cache)) {
- Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_remove_all");
- return 0;
- }
- return 1;
- }
- /* make cache write into output file instead of cache file */
- Rast3d_cache_set_remove_fun(map->cache, cacheFlushFun, map);
- /* first flush all the tiles which are in the file cache */
- nBytes = map->tileSize * map->numLengthIntern;
- while (map->cachePosLast >= 0) {
- offs = map->cachePosLast * (nBytes + sizeof(int)) + nBytes;
- if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
- Rast3d_error("Rast3d_flush_all_tiles: can't position file");
- return 0;
- }
- if (read(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
- Rast3d_error("Rast3d_flush_all_tiles: can't read file");
- return 0;
- }
- if (!Rast3d_cache_load(map->cache, tileIndex)) {
- Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_load");
- return 0;
- }
- if (!Rast3d_cache_flush(map->cache, tileIndex)) {
- Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_flush");
- return 0;
- }
- }
- /* then flush all the tiles which remain in the non-file cache */
- if (!Rast3d_cache_flush_all(map->cache)) {
- Rast3d_error("Rast3d_flush_all_tiles: error in Rast3d_cache_flush_all");
- return 0;
- }
- /* now the cache should write into the cache file again */
- Rast3d_cache_set_remove_fun(map->cache, cacheWrite_writeFun, map);
- return 1;
- }
|