|
@@ -1,422 +1,209 @@
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
-#include <string.h>
|
|
|
+#include <fcntl.h>
|
|
|
#include <sys/types.h>
|
|
|
#include <unistd.h>
|
|
|
-#include <grass/G3d.h>
|
|
|
#include "G3d_intern.h"
|
|
|
-#include "cachehash.h"
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-#define IS_ACTIVE_ELT(elt) (c->locks[elt] != 2)
|
|
|
-#define IS_NOT_ACTIVE_ELT(elt) (c->locks[elt] == 2)
|
|
|
-#define IS_LOCKED_ELT(elt) (c->locks[elt] == 1)
|
|
|
-#define IS_UNLOCKED_ELT(elt) (c->locks[elt] == 0)
|
|
|
-#define IS_NOT_IN_QUEUE_ELT(elt) (IS_LOCKED_ELT (elt))
|
|
|
-#define IS_IN_QUEUE_ELT(elt) (! IS_NOT_IN_QUEUE_ELT (elt))
|
|
|
-
|
|
|
-#define DEACTIVATE_ELT(elt) ((IS_LOCKED_ELT(elt) ? \
|
|
|
- (c->nofUnlocked)++ : (0)), \
|
|
|
- c->locks[elt] = 2)
|
|
|
-#define LOCK_ELT(elt) ((IS_LOCKED_ELT(elt) ? \
|
|
|
- (0) : (c->nofUnlocked)--), \
|
|
|
- (c->locks[elt] = 1))
|
|
|
-#define UNLOCK_ELT(elt) ((IS_LOCKED_ELT(elt) ? \
|
|
|
- (c->nofUnlocked)++ : (0)), \
|
|
|
- (c->locks[elt] = 0))
|
|
|
-
|
|
|
-#define ONE_UNLOCKED_ELT_ONLY (c->first == c->last)
|
|
|
-#define ARE_MIN_UNLOCKED (c->nofUnlocked <= c->minUnlocked)
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-void G3d_cache_reset(G3D_cache * c)
|
|
|
+static int cacheRead_readFun(int tileIndex, void *tileBuf, void *closure)
|
|
|
{
|
|
|
- int i;
|
|
|
+ G3D_Map *map = closure;
|
|
|
|
|
|
- for (i = 0; i < c->nofElts; i++) {
|
|
|
- DEACTIVATE_ELT(i);
|
|
|
- c->next[i] = i + 1;
|
|
|
- c->prev[i] = i - 1;
|
|
|
- c->names[i] = -1;
|
|
|
+ if (!G3d_readTile(map, tileIndex, tileBuf, map->typeIntern)) {
|
|
|
+ G3d_error("cacheRead_readFun: error in G3d_readTile");
|
|
|
+ return 0;
|
|
|
}
|
|
|
-
|
|
|
- c->prev[0] = c->next[c->nofElts - 1] = -1;
|
|
|
- c->first = 0;
|
|
|
- c->last = c->nofElts - 1;
|
|
|
-
|
|
|
- c->autoLock = 0;
|
|
|
- c->nofUnlocked = c->nofElts;
|
|
|
- c->minUnlocked = 1;
|
|
|
-
|
|
|
- G3d_cache_hash_reset(c->hash);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-static int cache_dummy_fun(int tileIndex, const void *tileBuf, void *map)
|
|
|
-{
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-void G3d_cache_dispose(G3D_cache * c)
|
|
|
-{
|
|
|
- if (c == NULL)
|
|
|
- return;
|
|
|
-
|
|
|
- G3d_cache_hash_dispose(c->hash);
|
|
|
-
|
|
|
- if (c->elts != NULL)
|
|
|
- G3d_free(c->elts);
|
|
|
- if (c->names != NULL)
|
|
|
- G3d_free(c->names);
|
|
|
- if (c->locks != NULL)
|
|
|
- G3d_free(c->locks);
|
|
|
- if (c->next != NULL)
|
|
|
- G3d_free(c->next);
|
|
|
- if (c->prev != NULL)
|
|
|
- G3d_free(c->prev);
|
|
|
-
|
|
|
- G3d_free(c);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-void *G3d_cache_new(int nofElts, int sizeOfElts, int nofNames,
|
|
|
- int (*eltRemoveFun) (), void *eltRemoveFunData,
|
|
|
- int (*eltLoadFun) (), void *eltLoadFunData)
|
|
|
+static int initCacheRead(G3D_Map * map, int nCached)
|
|
|
{
|
|
|
- G3D_cache *tmp;
|
|
|
-
|
|
|
- tmp = G3d_malloc(sizeof(G3D_cache));
|
|
|
- if (tmp == NULL) {
|
|
|
- G3d_error("G3d_cache_new: error in G3d_malloc");
|
|
|
- return (void *)NULL;
|
|
|
- }
|
|
|
-
|
|
|
- tmp->hash = NULL;
|
|
|
-
|
|
|
- tmp->nofElts = nofElts;
|
|
|
- tmp->eltSize = sizeOfElts;
|
|
|
- tmp->elts = G3d_malloc(tmp->eltSize * tmp->nofElts);
|
|
|
- tmp->names = G3d_malloc(sizeof(int) * tmp->nofElts);
|
|
|
- tmp->locks = G3d_malloc(tmp->nofElts);
|
|
|
- tmp->next = G3d_malloc(sizeof(int) * tmp->nofElts);
|
|
|
- tmp->prev = G3d_malloc(sizeof(int) * tmp->nofElts);
|
|
|
-
|
|
|
- if ((tmp->elts == NULL) || (tmp->names == NULL) || (tmp->locks == NULL) ||
|
|
|
- (tmp->next == NULL) || (tmp->prev == NULL)) {
|
|
|
-
|
|
|
- G3d_cache_dispose(tmp);
|
|
|
- G3d_error("G3d_cache_new: error in G3d_malloc");
|
|
|
- return (void *)NULL;
|
|
|
- }
|
|
|
-
|
|
|
- tmp->eltRemoveFun = eltRemoveFun;
|
|
|
- tmp->eltRemoveFunData = eltRemoveFunData;
|
|
|
- tmp->eltLoadFun = eltLoadFun;
|
|
|
- tmp->eltLoadFunData = eltLoadFunData;
|
|
|
-
|
|
|
- tmp->hash = G3d_cache_hash_new(nofNames);
|
|
|
- if (tmp->hash == NULL) {
|
|
|
- G3d_cache_dispose(tmp);
|
|
|
- G3d_error("G3d_cache_new: error in G3d_cache_hash_new");
|
|
|
- return (void *)NULL;
|
|
|
+ map->cache = G3d_cache_new_read(nCached,
|
|
|
+ map->tileSize * map->numLengthIntern,
|
|
|
+ map->nTiles, cacheRead_readFun, map);
|
|
|
+ if (map->cache == NULL) {
|
|
|
+ G3d_error("initCacheRead: error in G3d_cache_new_read");
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- G3d_cache_reset(tmp);
|
|
|
-
|
|
|
- return tmp;
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-void
|
|
|
-G3d_cache_set_removeFun(G3D_cache * c, int (*eltRemoveFun) (),
|
|
|
- void *eltRemoveFunData)
|
|
|
-{
|
|
|
- c->eltRemoveFun = eltRemoveFun;
|
|
|
- c->eltRemoveFunData = eltRemoveFunData;
|
|
|
-}
|
|
|
+/*
|
|
|
+ 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)
|
|
|
|
|
|
-void
|
|
|
-G3d_cache_set_loadFun(G3D_cache * c, int (*eltLoadFun) (),
|
|
|
- void *eltLoadFunData)
|
|
|
-{
|
|
|
- c->eltLoadFun = eltLoadFun;
|
|
|
- c->eltLoadFunData = eltLoadFunData;
|
|
|
-}
|
|
|
+ symmetrically, we use
|
|
|
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
+ fileposition = - (index + 2)
|
|
|
|
|
|
-void *G3d_cache_new_read(int nofElts, int sizeOfElts, int nofNames,
|
|
|
- read_fn * eltLoadFun, void *eltLoadFunData)
|
|
|
-{
|
|
|
- return G3d_cache_new(nofElts, sizeOfElts, nofNames,
|
|
|
- cache_dummy_fun, NULL, eltLoadFun, eltLoadFunData);
|
|
|
-}
|
|
|
+ to convert from index to the fileposition.
|
|
|
+ */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-static void cache_queue_dequeue(G3D_cache * c, int index)
|
|
|
+static int cacheWrite_readFun(int tileIndex, void *tileBuf, void *closure)
|
|
|
{
|
|
|
- if (IS_NOT_IN_QUEUE_ELT(index))
|
|
|
- G3d_fatalError("cache_queue_dequeue: index not in queue");
|
|
|
+ G3D_Map *map = closure;
|
|
|
+ int index, nBytes;
|
|
|
+ long pos, offs, offsLast;
|
|
|
|
|
|
- if (index == c->first)
|
|
|
- c->first = c->next[index];
|
|
|
- if (index == c->last)
|
|
|
- c->last = c->prev[index];
|
|
|
+ pos = map->index[tileIndex];
|
|
|
|
|
|
- if (c->next[index] != -1)
|
|
|
- c->prev[c->next[index]] = c->prev[index];
|
|
|
- if (c->prev[index] != -1)
|
|
|
- c->next[c->prev[index]] = c->next[index];
|
|
|
+ /* tile has already been flushed onto output file or does not exist yet */
|
|
|
+ if (pos >= -1) { /* note, G3d_readTile takes care of the case pos == -1 */
|
|
|
+ G3d_readTile(map, tileIndex, tileBuf, map->typeIntern);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
|
|
|
- c->next[index] = c->prev[index] = -1;
|
|
|
-}
|
|
|
+ /* tile is in cache file */
|
|
|
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
+ pos = -pos - 2; /* pos is shifted by 2 to avoid 0 and -1 */
|
|
|
|
|
|
-static void cache_queue_enqueue(G3D_cache * c, int left, int index)
|
|
|
-{
|
|
|
- if (IS_IN_QUEUE_ELT(index))
|
|
|
- G3d_fatalError("cache_queue_enqueue: index already in queue");
|
|
|
+ nBytes = map->tileSize * map->numLengthIntern;
|
|
|
+ offs = pos * (nBytes + sizeof(int));
|
|
|
|
|
|
- if (c->first == -1) {
|
|
|
- if (left != c->last)
|
|
|
- G3d_fatalError("cache_queue_enqueue: position out of range");
|
|
|
+ /* seek tile and read it into buffer */
|
|
|
|
|
|
- c->first = c->last = index;
|
|
|
- return;
|
|
|
+ if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
|
|
|
+ G3d_error("cacheWrite_readFun: can't position file");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (read(map->cacheFD, tileBuf, nBytes) != nBytes) {
|
|
|
+ G3d_error("cacheWrite_readFun: can't read file");
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- if (IS_NOT_IN_QUEUE_ELT(left))
|
|
|
- G3d_fatalError("cache_queue_enqueue: position not in queue");
|
|
|
+ /* remove it from index */
|
|
|
|
|
|
+ map->index[tileIndex] = -1;
|
|
|
|
|
|
- if (left == -1) {
|
|
|
- c->next[index] = c->first;
|
|
|
- c->prev[c->first] = index;
|
|
|
- c->first = index;
|
|
|
+ /* 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 */
|
|
|
|
|
|
- return;
|
|
|
+ if (map->cachePosLast == pos) {
|
|
|
+ map->cachePosLast--;
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
- c->prev[index] = left;
|
|
|
+ /* otherwise we move the last tile in the file into the position of */
|
|
|
+ /* the tile we just read and update the hash information */
|
|
|
|
|
|
- if (c->next[left] == -1) {
|
|
|
- c->next[left] = index;
|
|
|
- c->last = index;
|
|
|
+ offsLast = map->cachePosLast * (nBytes + sizeof(int));
|
|
|
|
|
|
- return;
|
|
|
+ if (lseek(map->cacheFD, offsLast, SEEK_SET) == -1) {
|
|
|
+ G3d_error("cacheWrite_readFun: can't position file");
|
|
|
+ return 0;
|
|
|
}
|
|
|
-
|
|
|
- c->prev[c->next[left]] = index;
|
|
|
- c->next[index] = c->next[left];
|
|
|
- c->next[left] = index;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-static int cache_queue_get_top(G3D_cache * c)
|
|
|
-{
|
|
|
- int top;
|
|
|
-
|
|
|
- top = c->first;
|
|
|
-
|
|
|
- cache_queue_dequeue(c, c->first);
|
|
|
-
|
|
|
- return top;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-static void cache_queue_append(G3D_cache * c, int index)
|
|
|
-{
|
|
|
- cache_queue_enqueue(c, c->last, index);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-static void cache_queue_preppend(G3D_cache * c, int index)
|
|
|
-{
|
|
|
- cache_queue_enqueue(c, -1, index);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
- /* EXPORTED FUNCTIONS */
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-int G3d_cache_lock(G3D_cache * c, int name)
|
|
|
-{
|
|
|
- int index;
|
|
|
-
|
|
|
- index = G3d_cache_hash_name2index(c->hash, name);
|
|
|
- if (index == -1) {
|
|
|
- G3d_error("G3d_cache_lock: name not in cache");
|
|
|
+ if (read(map->cacheFD, xdr, nBytes + sizeof(int)) != nBytes + sizeof(int)) {
|
|
|
+ G3d_error("cacheWrite_readFun: can't read file");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (IS_LOCKED_ELT(index))
|
|
|
- return 1;
|
|
|
- if (ONE_UNLOCKED_ELT_ONLY)
|
|
|
- return -1;
|
|
|
- if (ARE_MIN_UNLOCKED)
|
|
|
- return -1;
|
|
|
-
|
|
|
- cache_queue_dequeue(c, index);
|
|
|
- LOCK_ELT(index);
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-void G3d_cache_lock_intern(G3D_cache * c, int index)
|
|
|
-{
|
|
|
- if (IS_LOCKED_ELT(index))
|
|
|
- return;
|
|
|
-
|
|
|
- cache_queue_dequeue(c, index);
|
|
|
- LOCK_ELT(index);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-int G3d_cache_unlock(G3D_cache * c, int name)
|
|
|
-{
|
|
|
- int index;
|
|
|
-
|
|
|
- index = G3d_cache_hash_name2index(c->hash, name);
|
|
|
- if (index == -1) {
|
|
|
- G3d_error("G3d_cache_unlock: name not in cache");
|
|
|
+ if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
|
|
|
+ G3d_error("cacheWrite_readFun: can't position file");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (write(map->cacheFD, xdr, nBytes + sizeof(int)) !=
|
|
|
+ nBytes + sizeof(int)) {
|
|
|
+ G3d_error("cacheWrite_readFun: can't write file");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (IS_UNLOCKED_ELT(index))
|
|
|
- return 1;
|
|
|
+ index = *((int *)((unsigned char *)xdr + nBytes));
|
|
|
+ map->index[index] = -pos - 2;
|
|
|
|
|
|
- cache_queue_append(c, index);
|
|
|
- UNLOCK_ELT(index);
|
|
|
+ map->cachePosLast--;
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-int G3d_cache_unlock_all(G3D_cache * c)
|
|
|
+static int
|
|
|
+cacheWrite_writeFun(int tileIndex, const void *tileBuf, void *closure)
|
|
|
{
|
|
|
- int index;
|
|
|
+ G3D_Map *map = closure;
|
|
|
+ int nBytes;
|
|
|
+ long offs;
|
|
|
|
|
|
- for (index = 0; index < c->nofElts; index++)
|
|
|
- if (IS_LOCKED_ELT(index))
|
|
|
- if (!G3d_cache_unlock(c, c->names[index])) {
|
|
|
- G3d_error("G3d_cache_unlock_all: error in G3d_cache_unlock");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (map->index[tileIndex] != -1)
|
|
|
+ return 1;
|
|
|
|
|
|
- return 1;
|
|
|
-}
|
|
|
+ map->cachePosLast++;
|
|
|
+ nBytes = map->tileSize * map->numLengthIntern;
|
|
|
+ offs = map->cachePosLast * (nBytes + sizeof(int));
|
|
|
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-int G3d_cache_lock_all(G3D_cache * c)
|
|
|
-{
|
|
|
- int index;
|
|
|
+ if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
|
|
|
+ G3d_error("cacheWrite_writeFun: can't position file");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (write(map->cacheFD, tileBuf, nBytes) != nBytes) {
|
|
|
+ G3d_error("cacheWrite_writeFun: can't write file");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (write(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
|
|
|
+ G3d_error("cacheWrite_writeFun: can't write file");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- for (index = 0; index < c->nofElts; index++)
|
|
|
- if (IS_UNLOCKED_ELT(index))
|
|
|
- G3d_cache_lock_intern(c, index);
|
|
|
+ map->index[tileIndex] = -map->cachePosLast - 2;
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-void G3d_cache_autolock_on(G3D_cache * c)
|
|
|
+static int disposeCacheWrite(G3D_Map * map)
|
|
|
{
|
|
|
- c->autoLock = 1;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-void G3d_cache_autolock_off(G3D_cache * c)
|
|
|
-{
|
|
|
- c->autoLock = 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-void G3d_cache_set_minUnlock(G3D_cache * c, int nofMinUnLocked)
|
|
|
-{
|
|
|
- c->minUnlocked = nofMinUnLocked;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-static int cache_remove_elt(G3D_cache * c, int name, int doFlush)
|
|
|
-{
|
|
|
- int index;
|
|
|
-
|
|
|
- index = G3d_cache_hash_name2index(c->hash, name);
|
|
|
- if (index == -1) {
|
|
|
- G3d_error("G3d_cache_deactivate_elt : name not in cache");
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (IS_NOT_ACTIVE_ELT(index))
|
|
|
- return 1;
|
|
|
-
|
|
|
- if (IS_IN_QUEUE_ELT(index)) {
|
|
|
- cache_queue_dequeue(c, index);
|
|
|
- LOCK_ELT(index);
|
|
|
- }
|
|
|
-
|
|
|
- if (doFlush)
|
|
|
- if (!c->eltRemoveFun(name, c->elts + c->eltSize * index,
|
|
|
- c->eltRemoveFunData)) {
|
|
|
- G3d_error("cache_remove_elt: error in c->eltRemoveFun");
|
|
|
+ if (map->cacheFD >= 0) {
|
|
|
+ if (close(map->cacheFD) != 0) {
|
|
|
+ G3d_error("disposeCacheWrite: could not close file");
|
|
|
return 0;
|
|
|
}
|
|
|
+ remove(map->cacheFileName);
|
|
|
+ G3d_free(map->cacheFileName);
|
|
|
+ }
|
|
|
|
|
|
- cache_queue_preppend(c, index);
|
|
|
- DEACTIVATE_ELT(index);
|
|
|
-
|
|
|
- G3d_cache_hash_remove_name(c->hash, name);
|
|
|
+ G3d_cache_dispose(map->cache);
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-int G3d_cache_remove_elt(G3D_cache * c, int name)
|
|
|
+static int initCacheWrite(G3D_Map * map, int nCached)
|
|
|
{
|
|
|
- if (!cache_remove_elt(c, name, 0)) {
|
|
|
- G3d_error("G3d_cache_remove_elt: error in cache_remove_elt");
|
|
|
+ map->cacheFileName = G_tempfile();
|
|
|
+ map->cacheFD = open(map->cacheFileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
|
+
|
|
|
+ if (map->cacheFD < 0) {
|
|
|
+ G3d_error("initCacheWrite: could not open file");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- return 1;
|
|
|
-}
|
|
|
+ map->cachePosLast = -1;
|
|
|
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
+ map->cache = G3d_cache_new(nCached,
|
|
|
+ map->tileSize * map->numLengthIntern,
|
|
|
+ map->nTiles,
|
|
|
+ cacheWrite_writeFun, map,
|
|
|
+ cacheWrite_readFun, map);
|
|
|
|
|
|
-int G3d_cache_flush(G3D_cache * c, int name)
|
|
|
-{
|
|
|
- if (!cache_remove_elt(c, name, 1)) {
|
|
|
- G3d_error("G3d_cache_flush: error in cache_remove_elt");
|
|
|
+ if (map->cache == NULL) {
|
|
|
+ disposeCacheWrite(map);
|
|
|
+ G3d_error("initCacheWrite: error in G3d_cache_new");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -425,272 +212,119 @@ int G3d_cache_flush(G3D_cache * c, int name)
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-int G3d_cache_remove_all(G3D_cache * c)
|
|
|
+int G3d_initCache(G3D_Map * map, int nCached)
|
|
|
{
|
|
|
- int index;
|
|
|
+ if (map->operation == G3D_READ_DATA) {
|
|
|
+ if (!initCacheRead(map, nCached)) {
|
|
|
+ G3d_error("G3d_initCache: error in initCacheRead");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
|
|
|
- for (index = 0; index < c->nofElts; index++)
|
|
|
- if (IS_ACTIVE_ELT(index))
|
|
|
- if (!G3d_cache_remove_elt(c, c->names[index])) {
|
|
|
- G3d_error
|
|
|
- ("G3d_cache_remove_all: error in G3d_cache_remove_elt");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (!initCacheWrite(map, nCached)) {
|
|
|
+ G3d_error("G3d_initCache: error in initCacheWrite");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-int G3d_cache_flush_all(G3D_cache * c)
|
|
|
+static int disposeCacheRead(G3D_Map * map)
|
|
|
{
|
|
|
- int index;
|
|
|
-
|
|
|
- for (index = 0; index < c->nofElts; index++)
|
|
|
- if (IS_ACTIVE_ELT(index))
|
|
|
- if (!G3d_cache_flush(c, c->names[index])) {
|
|
|
- G3d_error("G3d_cache_flush_all: error in G3d_cache_flush");
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
+ G3d_cache_dispose(map->cache);
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-void *G3d_cache_elt_ptr(G3D_cache * c, int name)
|
|
|
+int G3d_disposeCache(G3D_Map * map)
|
|
|
{
|
|
|
- int index, oldName, doUnlock;
|
|
|
-
|
|
|
- index = G3d_cache_hash_name2index(c->hash, name);
|
|
|
-
|
|
|
- if (index != -1) {
|
|
|
- if (c->autoLock)
|
|
|
- if (IS_UNLOCKED_ELT(index) && (!ONE_UNLOCKED_ELT_ONLY) &&
|
|
|
- (!ARE_MIN_UNLOCKED))
|
|
|
- G3d_cache_lock_intern(c, index);
|
|
|
-
|
|
|
- return c->elts + c->eltSize * index;
|
|
|
- }
|
|
|
-
|
|
|
- index = c->first;
|
|
|
- if (IS_ACTIVE_ELT(index)) {
|
|
|
- oldName = c->names[index];
|
|
|
- G3d_cache_hash_remove_name(c->hash, oldName);
|
|
|
- if (!c->eltRemoveFun(oldName, c->elts + c->eltSize * index,
|
|
|
- c->eltRemoveFunData)) {
|
|
|
- G3d_error("G3d_cache_elt_ptr: error in c->eltRemoveFun");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- G3d_cache_hash_load_name(c->hash, name, index);
|
|
|
-
|
|
|
- doUnlock = ((!c->autoLock) || ONE_UNLOCKED_ELT_ONLY || ARE_MIN_UNLOCKED);
|
|
|
-
|
|
|
- UNLOCK_ELT(index);
|
|
|
- c->names[index] = name;
|
|
|
- G3d_cache_lock_intern(c, index);
|
|
|
-
|
|
|
- if (doUnlock)
|
|
|
- if (!G3d_cache_unlock(c, name)) {
|
|
|
- G3d_error("G3d_cache_elt_ptr: error in G3d_cache_unlock");
|
|
|
- return NULL;
|
|
|
+ if (map->operation == G3D_READ_DATA) {
|
|
|
+ if (!disposeCacheRead(map)) {
|
|
|
+ G3d_error("G3d_disposeCache: error in disposeCacheRead");
|
|
|
+ return 0;
|
|
|
}
|
|
|
-
|
|
|
- if (!c->eltLoadFun(name, c->elts + c->eltSize * index, c->eltLoadFunData)) {
|
|
|
- G3d_error("G3d_cache_elt_ptr: error in c->eltLoadFun");
|
|
|
- return NULL;
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
- return c->elts + c->eltSize * index;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-int G3d_cache_load(G3D_cache * c, int name)
|
|
|
-{
|
|
|
- if (G3d_cache_elt_ptr(c, name) == NULL) {
|
|
|
- G3d_error("G3d_cache_load: error in G3d_cache_elt_ptr");
|
|
|
+ if (!disposeCacheWrite(map)) {
|
|
|
+ G3d_error("G3d_disposeCache: error in disposeCacheWrite");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-int G3d_cache_get_elt(G3D_cache * c, int name, void *dst)
|
|
|
+static int cacheFlushFun(int tileIndex, const void *tileBuf, void *closure)
|
|
|
{
|
|
|
- const void *elt;
|
|
|
+ G3D_Map *map = closure;
|
|
|
|
|
|
- elt = G3d_cache_elt_ptr(c, name);
|
|
|
- if (elt == NULL) {
|
|
|
- G3d_error("G3d_cache_get_elt: error in G3d_cache_elt_ptr");
|
|
|
+ if (!G3d_writeTile(map, tileIndex, tileBuf, map->typeIntern)) {
|
|
|
+ G3d_error("cacheFlushFun: error in G3d_writeTile");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- memcpy(dst, elt, c->eltSize);
|
|
|
-
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-int G3d_cache_put_elt(G3D_cache * c, int name, const void *src)
|
|
|
+int G3d_flushAllTiles(G3D_Map * map)
|
|
|
{
|
|
|
- void *elt;
|
|
|
+ int tileIndex, nBytes;
|
|
|
+ long offs;
|
|
|
|
|
|
- elt = G3d_cache_elt_ptr(c, name);
|
|
|
- if (elt == NULL) {
|
|
|
- G3d_error("G3d_cache_put_elt: error in G3d_cache_elt_ptr");
|
|
|
- return 0;
|
|
|
+ if (map->operation == G3D_READ_DATA) {
|
|
|
+ if (!G3d_cache_remove_all(map->cache)) {
|
|
|
+ G3d_error("G3d_flushAllTiles: error in G3d_cache_remove_all");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
- memcpy(elt, src, c->eltSize);
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
+ /* make cache write into output file instead of cache file */
|
|
|
+ G3d_cache_set_removeFun(map->cache, cacheFlushFun, map);
|
|
|
|
|
|
- /* TEST FUNCTIONS */
|
|
|
+ /* 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;
|
|
|
|
|
|
-static void cache_test_print(G3D_cache * c)
|
|
|
-{
|
|
|
- int i, al;
|
|
|
- int *a;
|
|
|
-
|
|
|
- al = c->autoLock;
|
|
|
- G3d_cache_autolock_off(c);
|
|
|
-
|
|
|
- printf("\n--------------------------------\n");
|
|
|
- for (i = 0; i < c->nofElts; i++) {
|
|
|
- printf("elt %d: ", i);
|
|
|
- if (IS_NOT_ACTIVE_ELT(i)) {
|
|
|
- printf("na\n");
|
|
|
- continue;
|
|
|
+ if (lseek(map->cacheFD, offs, SEEK_SET) == -1) {
|
|
|
+ G3d_error("G3d_flushAllTiles: can't position file");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (read(map->cacheFD, &tileIndex, sizeof(int)) != sizeof(int)) {
|
|
|
+ G3d_error("G3d_flushAllTiles: can't read file");
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- a = (int *)G3d_cache_elt_ptr(c, c->names[i]);
|
|
|
- /*G3d_cache_get_elt (c, c->names[i], a); */
|
|
|
- printf("name %d val %d %s\n", c->names[i], a[17],
|
|
|
- (IS_LOCKED_ELT(i) ? "locked" :
|
|
|
- IS_UNLOCKED_ELT(i) ? "unlocked" : ""));
|
|
|
+ if (!G3d_cache_load(map->cache, tileIndex)) {
|
|
|
+ G3d_error("G3d_flushAllTiles: error in G3d_cache_load");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (!G3d_cache_flush(map->cache, tileIndex)) {
|
|
|
+ G3d_error("G3d_flushAllTiles: error in G3d_cache_flush");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
- printf("\n--------------------------------\n");
|
|
|
-
|
|
|
- if (al)
|
|
|
- G3d_cache_autolock_on(c);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
-static int cache_test_flush_fun(int name, const void *eltPtr, void *data)
|
|
|
-{
|
|
|
- printf("flushing name %d value %d\n", name, ((const int *)eltPtr)[17]);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-typedef struct
|
|
|
-{
|
|
|
-
|
|
|
- int *value;
|
|
|
- int size;
|
|
|
-
|
|
|
-} cache_test_data_type;
|
|
|
-
|
|
|
-static int cache_test_load_fun(int name, void *eltPtr, void *data)
|
|
|
-{
|
|
|
- const void *src;
|
|
|
-
|
|
|
- printf("loading name %d value %d\n", name,
|
|
|
- ((cache_test_data_type *) data)->value[17]);
|
|
|
-
|
|
|
- src = ((cache_test_data_type *) data)->value;
|
|
|
- memcpy(eltPtr, src, ((cache_test_data_type *) data)->size);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-static cache_test_data_type ctd;
|
|
|
-
|
|
|
-static void cache_test_add(void *c, int name, int val)
|
|
|
-{
|
|
|
- static int firstTime = 1;
|
|
|
-
|
|
|
- if (firstTime) {
|
|
|
- ctd.value = G3d_malloc(((G3D_cache *) c)->eltSize * sizeof(int));
|
|
|
- firstTime = 0;
|
|
|
+ /* then flush all the tiles which remain in the non-file cache */
|
|
|
+ if (!G3d_cache_flush_all(map->cache)) {
|
|
|
+ G3d_error("G3d_flushAllTiles: error in G3d_cache_flush_all");
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- ctd.value[17] = val;
|
|
|
- ctd.size = ((G3D_cache *) c)->eltSize;
|
|
|
+ /* now the cache should write into the cache file again */
|
|
|
+ G3d_cache_set_removeFun(map->cache, cacheWrite_writeFun, map);
|
|
|
|
|
|
- G3d_cache_load(c, name);
|
|
|
-}
|
|
|
-
|
|
|
-/*---------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-int MAIN()
|
|
|
-{
|
|
|
- void *c;
|
|
|
-
|
|
|
- c = G3d_cache_new(3, 76 * sizeof(int), 100000,
|
|
|
- cache_test_flush_fun, NULL, cache_test_load_fun, &ctd);
|
|
|
-
|
|
|
- G3d_cache_autolock_on(c);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 1111, -11);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 2222, -22);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 3333, -33);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 4444, -44);
|
|
|
- cache_test_print(c);
|
|
|
- G3d_cache_unlock_all(c);
|
|
|
- cache_test_print(c);
|
|
|
- G3d_cache_load(c, 2222);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 5555, -55);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 6666, -66);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 7777, -77);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 8888, -88);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 9999, -99);
|
|
|
- cache_test_print(c);
|
|
|
- G3d_cache_flush(c, 9999);
|
|
|
- cache_test_print(c);
|
|
|
- G3d_cache_flush_all(c);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 1111, -11);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 2222, -22);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 3333, -33);
|
|
|
- cache_test_print(c);
|
|
|
- G3d_cache_reset(c);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 1111, -11);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 2222, -22);
|
|
|
- cache_test_print(c);
|
|
|
- cache_test_add(c, 3333, -33);
|
|
|
- cache_test_print(c);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ return 1;
|
|
|
}
|