[GRASS-SVN] r53901 - grass/trunk/lib/vector/rtree

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Nov 18 11:21:23 PST 2012


Author: mmetz
Date: 2012-11-18 11:21:23 -0800 (Sun, 18 Nov 2012)
New Revision: 53901

Modified:
   grass/trunk/lib/vector/rtree/index.c
   grass/trunk/lib/vector/rtree/index.h
   grass/trunk/lib/vector/rtree/indexf.c
   grass/trunk/lib/vector/rtree/io.c
   grass/trunk/lib/vector/rtree/node.c
   grass/trunk/lib/vector/rtree/rect.c
   grass/trunk/lib/vector/rtree/rtree.h
Log:
rtree: spatial index with buffered external memory, work in progress

Modified: grass/trunk/lib/vector/rtree/index.c
===================================================================
--- grass/trunk/lib/vector/rtree/index.c	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/index.c	2012-11-18 19:21:23 UTC (rev 53901)
@@ -62,7 +62,7 @@
 {
     struct RTree *new_rtree;
     struct RTree_Node *n;
-    int i, j;
+    int i, j, k;
     
     new_rtree = (struct RTree *)malloc(sizeof(struct RTree));
 
@@ -78,7 +78,7 @@
 
     new_rtree->nsides_alloc = 2 * new_rtree->ndims_alloc;
 
-    /* init free nodes */
+    /* init free node positions */
     new_rtree->free_nodes.avail = 0;
     new_rtree->free_nodes.alloc = 0;
     new_rtree->free_nodes.pos = NULL;
@@ -94,7 +94,6 @@
     /* create empty root node */
     n = RTreeAllocNode(new_rtree, 0);
     new_rtree->rootlevel = n->level = 0;       /* leaf */
-    new_rtree->root = NULL;
     
     /* use overflow by default */
     new_rtree->overflow = 1;
@@ -105,25 +104,27 @@
 	new_rtree->leafcard = MAXCARD;
 
 	/* initialize node buffer */
+	new_rtree->nb = calloc(MAXLEVEL, sizeof(struct NodeBuffer *));
+	new_rtree->nb[0] = calloc(MAXLEVEL * NODE_BUFFER_SIZE, sizeof(struct NodeBuffer));
+	for (i = 1; i < MAXLEVEL; i++) {
+	    new_rtree->nb[i] = new_rtree->nb[i - 1] + NODE_BUFFER_SIZE;
+	}
+
 	for (i = 0; i < MAXLEVEL; i++) {
-	    new_rtree->nb[i][0].dirty = 0;
-	    new_rtree->nb[i][1].dirty = 0;
-	    new_rtree->nb[i][2].dirty = 0;
-	    new_rtree->nb[i][0].pos = -1;
-	    new_rtree->nb[i][1].pos = -1;
-	    new_rtree->nb[i][2].pos = -1;
-	    /* usage order */
-	    new_rtree->used[i][0] = 2;
-	    new_rtree->used[i][1] = 1;
-	    new_rtree->used[i][2] = 0;
 
-	    /* alloc memory for rectangles */
 	    for (j = 0; j < MAXCARD; j++) {
-		RTreeAllocBoundary(&(new_rtree->nb[i][0].n.branch[j].rect), new_rtree);
-		RTreeAllocBoundary(&(new_rtree->nb[i][1].n.branch[j].rect), new_rtree);
-		RTreeAllocBoundary(&(new_rtree->nb[i][2].n.branch[j].rect), new_rtree);
+		new_rtree->fs[i].sn.branch[j].rect.boundary = RTreeAllocBoundary(new_rtree);
+	    }
+	    for (j = 0; j < NODE_BUFFER_SIZE; j++) {
+		new_rtree->nb[i][j].dirty = 0;
+		new_rtree->nb[i][j].pos = -1;
+		/* usage order */
+		new_rtree->used[i][j] = j;
 
-		RTreeAllocBoundary(&(new_rtree->fs[i].sn.branch[j].rect), new_rtree);
+		/* alloc memory for rectangles */
+		for (k = 0; k < MAXCARD; k++) {
+		    new_rtree->nb[i][j].n.branch[k].rect.boundary = RTreeAllocBoundary(new_rtree);
+		}
 	    }
 	}
 
@@ -131,6 +132,7 @@
 	lseek(new_rtree->fd, rootpos, SEEK_SET);
 	RTreeWriteNode(n, new_rtree);
 	RTreeFreeNode(n);
+	new_rtree->root = NULL;
 
 	new_rtree->insert_rect = RTreeInsertRectF;
 	new_rtree->delete_rect = RTreeDeleteRectF;
@@ -162,19 +164,19 @@
     new_rtree->n_leafs = 0;
 
     /* initialize temp variables */
-    RTreeAllocBoundary(&(new_rtree->p.cover[0]), new_rtree);
-    RTreeAllocBoundary(&(new_rtree->p.cover[1]), new_rtree);
+    new_rtree->p.cover[0].boundary = RTreeAllocBoundary(new_rtree);
+    new_rtree->p.cover[1].boundary = RTreeAllocBoundary(new_rtree);
     
-    RTreeAllocBoundary(&(new_rtree->tmpb1.rect), new_rtree);
-    RTreeAllocBoundary(&(new_rtree->tmpb2.rect), new_rtree);
-    RTreeAllocBoundary(&(new_rtree->c.rect), new_rtree);
+    new_rtree->tmpb1.rect.boundary = RTreeAllocBoundary(new_rtree);
+    new_rtree->tmpb2.rect.boundary = RTreeAllocBoundary(new_rtree);
+    new_rtree->c.rect.boundary = RTreeAllocBoundary(new_rtree);
     for (i = 0; i <= MAXCARD; i++) {
-	RTreeAllocBoundary(&(new_rtree->BranchBuf[i].rect), new_rtree);
+	new_rtree->BranchBuf[i].rect.boundary = RTreeAllocBoundary(new_rtree);
     }
-    RTreeAllocBoundary(&(new_rtree->rect_0), new_rtree);
-    RTreeAllocBoundary(&(new_rtree->rect_1), new_rtree);
-    RTreeAllocBoundary(&(new_rtree->upperrect), new_rtree);
-    RTreeAllocBoundary(&(new_rtree->orect), new_rtree);
+    new_rtree->rect_0.boundary = RTreeAllocBoundary(new_rtree);
+    new_rtree->rect_1.boundary = RTreeAllocBoundary(new_rtree);
+    new_rtree->upperrect.boundary = RTreeAllocBoundary(new_rtree);
+    new_rtree->orect.boundary = RTreeAllocBoundary(new_rtree);
     new_rtree->center_n = (RectReal *)malloc(new_rtree->ndims_alloc * sizeof(RectReal));
 
     return new_rtree;
@@ -213,31 +215,19 @@
 
 void RTreeDestroyTree(struct RTree *t)
 {
-    int i, j;
+    int i;
 
     assert(t);
 
     if (t->fd > -1) {
 	if (t->free_nodes.alloc)
 	    free(t->free_nodes.pos);
+	free(t->nb[0]);
+	free(t->nb);
     }
     else if (t->root)
 	RTreeDestroyNode(t->root, t->root->level ? t->nodecard : t->leafcard);
 
-    if (t->fd > -1) {  /* file based */
-	/* free node buffer */
-	for (i = 0; i < MAXLEVEL; i++) {
-
-	    /* free memory for rectangles */
-	    for (j = 0; j < MAXCARD; j++) {
-		RTreeFreeBoundary(&(t->nb[i][0].n.branch[j].rect));
-		RTreeFreeBoundary(&(t->nb[i][1].n.branch[j].rect));
-		RTreeFreeBoundary(&(t->nb[i][2].n.branch[j].rect));
-		RTreeFreeBoundary(&(t->fs[i].sn.branch[j].rect));
-	    }
-	}
-    }
-
     /* free temp variables */
     RTreeFreeBoundary(&(t->p.cover[0]));
     RTreeFreeBoundary(&(t->p.cover[1]));

Modified: grass/trunk/lib/vector/rtree/index.h
===================================================================
--- grass/trunk/lib/vector/rtree/index.h	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/index.h	2012-11-18 19:21:23 UTC (rev 53901)
@@ -108,8 +108,9 @@
 int RTreeGetNodeMax(struct RTree *);
 int RTreeGetLeafMax(struct RTree *);
 
-/* fileio.c */
-void RTreeGetNode(struct RTree_Node *, off_t, int, struct RTree *);
+/* io.c */
+void RTreeGetNode(struct RTree_Node *n, off_t, int, struct RTree *);
+void RTreeNodeChanged(struct RTree_Node *, off_t , struct RTree *);
 void RTreePutNode(struct RTree_Node *, off_t, struct RTree *);
 size_t RTreeRewriteNode(struct RTree_Node *, off_t, struct RTree *);
 void RTreeUpdateRect(struct RTree_Rect *, struct RTree_Node *, off_t, int, struct RTree *);

Modified: grass/trunk/lib/vector/rtree/indexf.c
===================================================================
--- grass/trunk/lib/vector/rtree/indexf.c	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/indexf.c	2012-11-18 19:21:23 UTC (rev 53901)
@@ -50,6 +50,7 @@
     /* add root node position to stack */
     currlevel = t->rootlevel;
     s[top].pos = t->rootpos;
+    /* s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); */
     RTreeGetNode(&(s[top].sn), s[top].pos, currlevel, t);
     s[top].branch_id = i = 0;
     
@@ -64,6 +65,7 @@
 		    s[top++].branch_id = i + 1;
 		    /* add next node to stack */
 		    s[top].pos = n->branch[i].child.pos;
+		    /* s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); */
 		    RTreeGetNode(&(s[top].sn), s[top].pos, currlevel, t);
 		    s[top].branch_id = 0;
 		    notfound = 0;
@@ -125,17 +127,19 @@
     
     if (!rect_init) {
 	for (i = 0; i < MAXCARD; i++) {
-	    RTreeAllocBoundary(&(nn.branch[i].rect), t);
+	    nn.branch[i].rect.boundary = RTreeAllocBoundary(t);
 	}
-	RTreeAllocBoundary(&nr, t);
+	nr.boundary = RTreeAllocBoundary(t);
 	rect_init = t->ndims_alloc;
     }
 
     n2 = &nn;
+    /* n2 = newnode; */
 
     /* add root node position to stack */
     currlevel = t->rootlevel;
     s[top].pos = t->rootpos;
+    /* s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); */
     RTreeGetNode(&(s[top].sn), s[top].pos, currlevel, t);
 
     /* go down to level of insertion */
@@ -146,7 +150,8 @@
 	s[top++].branch_id = i;
 	/* add next node to stack */
 	s[top].pos = n->branch[i].child.pos;
-	RTreeGetNode(&(s[top].sn), s[top].pos, n->level - 1, t);
+	/* s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); */
+	RTreeGetNode(&(s[top].sn), s[top].pos, currlevel, t);
 	assert(s[top].sn.level == currlevel);
     }
     assert(s[top].sn.level == level);
@@ -162,6 +167,7 @@
     result = RTreeAddBranch(b, &(s[top].sn), &n2, ee, cover, overflow, t);
     /* update node */
     RTreePutNode(&(s[top].sn), s[top].pos, t);
+    /* RTreeNodeChanged(s[top].sn, s[top].pos, t); */
     /* write out new node if node was split */
     if (result == 1) {
 	*newnode_pos = RTreeGetNodePos(t);
@@ -179,6 +185,11 @@
 	    if (!RTreeCompareRect(&nr, &(s[top].sn.branch[i].rect), t)) {
 		RTreeUpdateRect(&nr, &(s[top].sn), s[top].pos, i, t);
 	    }
+	    /*
+	    if (RTreeExpandRect(&(s[top].sn->branch[i].rect), r, t)) {
+		RTreeNodeChanged(s[top].sn, s[top].pos, t);
+	    }
+	    */
 	}
 	else if (result == 2) {	/* branches were removed */
 	    /* get node cover of previous node */
@@ -186,6 +197,10 @@
 	    /* rewrite rect */
 	    if (!RTreeCompareRect(&nr, &(s[top].sn.branch[i].rect), t)) {
 		RTreeUpdateRect(&nr, &(s[top].sn), s[top].pos, i, t);
+		/*
+		RTreeCopyRect(&(s[top].sn->branch[i].rect), &nr, t);
+		RTreeNodeChanged(s[top].sn, s[top].pos, t);
+		*/
 	    }
 	}
 	else if (result == 1) {                /* node was split */
@@ -204,6 +219,7 @@
 
 	    /* update node */
 	    RTreePutNode(&(s[top].sn), s[top].pos, t);
+	    /* RTreeNodeChanged(s[top].sn, s[top].pos, t); */
 
 	    /* write out new node if node was split */
 	    if (result == 1) {
@@ -238,14 +254,15 @@
     struct RTree_Branch *b = &(t->tmpb1);
     off_t newnode_pos = -1;
 
-    static struct RTree_Node oldroot, newroot, newnode;
+    static struct RTree_Node oldroot;
+    static struct RTree_Node newroot, newnode;
     static int rect_init = 0;
     
     if (!rect_init) {
 	for (i = 0; i < MAXCARD; i++) {
-	    RTreeAllocBoundary(&(oldroot.branch[i].rect), t);
-	    RTreeAllocBoundary(&(newroot.branch[i].rect), t);
-	    RTreeAllocBoundary(&(newnode.branch[i].rect), t);
+	    oldroot.branch[i].rect.boundary = RTreeAllocBoundary(t);
+	    newroot.branch[i].rect.boundary = RTreeAllocBoundary(t);
+	    newnode.branch[i].rect.boundary = RTreeAllocBoundary(t);
 	}
 	rect_init = t->ndims_alloc;
     }
@@ -257,6 +274,7 @@
 			       t, &reInsertList, overflow);
 
     if (result == 1) {	/* root split */
+	/* oldroot = RTreeGetNode(t->rootpos, t->rootlevel, t); */
 	RTreeGetNode(&oldroot, t->rootpos, t->rootlevel, t);
 	/* grow a new root, & tree taller */
 	t->rootlevel++;
@@ -292,6 +310,7 @@
 				 &reInsertList, overflow);
 
 	    if (result == 1) {	/* root split */
+		/* oldroot = RTreeGetNode(t->rootpos, t->rootlevel, t); */
 		RTreeGetNode(&oldroot, t->rootpos, t->rootlevel, t);
 		/* grow a new root, & tree taller */
 		t->rootlevel++;
@@ -338,13 +357,14 @@
     assert(ee);
     
     if (!rect_init) {
-	RTreeAllocBoundary(&(nr), t);
+	nr.boundary = RTreeAllocBoundary(t);
 	rect_init = 1;
     }
 
     /* add root node position to stack */
     currlevel = t->rootlevel;
     s[top].pos = t->rootpos;
+    /* s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); */
     RTreeGetNode(&(s[top].sn), s[top].pos, currlevel, t);
     s[top].branch_id = 0;
 
@@ -354,10 +374,12 @@
 	    n = &(s[top].sn);
 	    currlevel = s[top].sn.level - 1;
 	    for (i = s[top].branch_id; i < t->nodecard; i++) {
-		if (n->branch[i].child.pos > -1 && RTreeOverlap(r, &(n->branch[i].rect), t)) {
+		if (n->branch[i].child.pos > -1 &&
+		    RTreeOverlap(r, &(n->branch[i].rect), t)) {
 		    s[top++].branch_id = i + 1;
 		    /* add next node to stack */
 		    s[top].pos = n->branch[i].child.pos;
+		    /* s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); */
 		    RTreeGetNode(&(s[top].sn), s[top].pos, currlevel, t);
 		    s[top].branch_id = 0;
 
@@ -379,6 +401,7 @@
 		    s[top].sn.branch[i].child.id == child.id) { /* found item */
 		    RTreeDisconnectBranch(&(s[top].sn), i, t);
 		    RTreePutNode(&(s[top].sn), s[top].pos, t);
+		    /* RTreeNodeChanged(s[top].sn, s[top].pos, t); */
 		    t->n_leafs--;
 		    notfound = 0;
 		    break;
@@ -407,6 +430,10 @@
 	    /* rewrite rect */
 	    if (!RTreeCompareRect(&nr, &(s[top].sn.branch[i].rect), t)) {
 		RTreeUpdateRect(&nr, &(s[top].sn), s[top].pos, i, t);
+		/*
+		RTreeCopyRect(&(s[top].sn->branch[i].rect), &nr, t);
+		RTreeNodeChanged(s[top].sn, s[top].pos, t);
+		*/
 	    }
 	}
 	else {
@@ -415,11 +442,12 @@
 	    n = RTreeAllocNode(t, s[down].sn.level);
 	    /* copy node */
 	    RTreeCopyNode(n, &(s[down].sn), t);
-	    RTreeAddNodePos(s[top].sn.branch[i].child.pos, s[down].sn.level, t);
+	    RTreeAddNodePos(s[down].pos, s[down].sn.level, t);
 	    RTreeReInsertNode(n, ee);
 	    RTreeDisconnectBranch(&(s[top].sn), i, t);
 
 	    RTreePutNode(&(s[top].sn), s[top].pos, t);
+	    /* RTreeNodeChanged(s[top].sn, s[top].pos, t); */
 	}
     }
 
@@ -445,7 +473,7 @@
     
     if (!rect_init) {
 	for (i = 0; i < MAXCARD; i++) {
-	    RTreeAllocBoundary(&(rn.branch[i].rect), t);
+	    rn.branch[i].rect.boundary = RTreeAllocBoundary(t);
 	}
 	rect_init = 1;
     }
@@ -480,16 +508,19 @@
 	}
 
 	/* check for redundant root (not leaf, 1 child) and eliminate */
+	/* n = RTreeGetNode(t->rootpos, t->rootlevel, t); */
 	RTreeGetNode(&rn, t->rootpos, t->rootlevel, t);
+	n = &rn;
 	
-	if (rn.count == 1 && rn.level > 0) {
+	if (n->count == 1 && n->level > 0) {
 	    for (i = 0; i < t->nodecard; i++) {
-		if (rn.branch[i].child.pos > -1)
+		if (n->branch[i].child.pos > -1)
 		    break;
 	    }
 	    RTreeAddNodePos(t->rootpos, t->rootlevel, t);
-	    t->rootpos = rn.branch[i].child.pos;
+	    t->rootpos = n->branch[i].child.pos;
 	    t->rootlevel--;
+	    t->n_nodes--;
 	}
 
 	return 0;

Modified: grass/trunk/lib/vector/rtree/io.c
===================================================================
--- grass/trunk/lib/vector/rtree/io.c	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/io.c	2012-11-18 19:21:23 UTC (rev 53901)
@@ -24,11 +24,13 @@
 #include <grass/config.h>
 #include "index.h"
 
+#define USAGE_SWAP
+
 /* add new free node position for recycling */
 void RTreeAddNodePos(off_t pos, int level, struct RTree *t)
 {
-    int which;
-    
+    int which, i;
+
     if (t->free_nodes.avail >= t->free_nodes.alloc) {
 	size_t size;
 
@@ -39,25 +41,34 @@
     }
     t->free_nodes.pos[t->free_nodes.avail++] = pos;
 
-    /* TODO: search with t->used[level][which] instead of which,
-     * then which = t->used[level][which] */
-    which = (pos == t->nb[level][2].pos ? 2 : pos == t->nb[level][1].pos);
+    /* check mru first */
+    i = 0;
+    while (t->nb[level][t->used[level][i]].pos != pos &&
+           i < NODE_BUFFER_SIZE)
+	i++;
+
+    assert(i < NODE_BUFFER_SIZE);
+    which = t->used[level][i];
+    assert(t->nb[level][which].n.level == level);
     t->nb[level][which].pos = -1;
     t->nb[level][which].dirty = 0;
     
     /* make it lru */
-    if (t->used[level][0] == which) {
-	t->used[level][0] = t->used[level][1];
-	t->used[level][1] = t->used[level][2];
-	t->used[level][2] = which; 
+    if (i < NODE_BUFFER_SIZE - 1) { /* which != t->used[level][NODE_BUFFER_SIZE - 1] */
+#ifdef USAGE_SWAP
+	t->used[level][i] = t->used[level][NODE_BUFFER_SIZE - 1];
+	t->used[level][NODE_BUFFER_SIZE - 1] = which;
+#else
+	while (i < NODE_BUFFER_SIZE - 1) {
+	    t->used[level][i] = t->used[level][i + 1];
+	    i++;
+	}
+	t->used[level][NODE_BUFFER_SIZE - 1] = which;
+#endif
     }
-    else if (t->used[level][1] == which) {
-	t->used[level][1] = t->used[level][2];
-	t->used[level][2] = which; 
-    }
 }
 
-/* looks for free node position, sets file pointer, returns position */
+/* look for free node position, set file pointer, return position */
 off_t RTreeGetNodePos(struct RTree *t)
 {
     if (t->free_nodes.avail > 0) {
@@ -100,39 +111,49 @@
 /* get node from buffer or file */
 void RTreeGetNode(struct RTree_Node *n, off_t nodepos, int level, struct RTree *t)
 {
-    int which = 0;
+    int which, i = 0;
 
-    /* TODO: search with t->used[level][which] instead of which,
-     * then which = t->used[level][which] */
-    while (t->nb[level][which].pos != nodepos &&
-           t->nb[level][which].pos >= 0 && which < 2)
-	which++;
+    /* check mru first */
+    while (t->nb[level][t->used[level][i]].pos != nodepos &&
+           t->nb[level][t->used[level][i]].pos >= 0 &&
+	   i < NODE_BUFFER_SIZE - 1)
+	i++;
 
+    which = t->used[level][i];
+
     if (t->nb[level][which].pos != nodepos) {
-	/* replace least recently used (fastest method of lru, pseudo-lru, mru) */
-	which = t->used[level][2];
+	if (t->nb[level][which].pos >= 0) {
+	    assert(i == NODE_BUFFER_SIZE - 1);
+	}
 	/* rewrite node in buffer */
 	if (t->nb[level][which].dirty) {
 	    assert(t->nb[level][which].pos >= 0);
-	    RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos, t);
+	    assert(t->nb[level][which].n.level == level);
+	    RTreeRewriteNode(&(t->nb[level][which].n),
+	                     t->nb[level][which].pos, t);
 	    t->nb[level][which].dirty = 0;
 	}
 	RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
 	t->nb[level][which].pos = nodepos;
     }
+    assert(t->nb[level][which].n.level == level);
     /* make it mru */
-    if (t->used[level][2] == which) {
-	t->used[level][2] = t->used[level][1];
-	t->used[level][1] = t->used[level][0];
-	t->used[level][0] = which; 
+    if (i) { /* t->used[level][0] != which */
+#ifdef USAGE_SWAP
+	t->used[level][i] = t->used[level][0];
+	t->used[level][0] = which;
+#else
+	while (i) {
+	    t->used[level][i] = t->used[level][i - 1];
+	    i--;
+	}
+	t->used[level][0] = which;
+#endif
     }
-    else if (t->used[level][1] == which) {
-	t->used[level][1] = t->used[level][0];
-	t->used[level][0] = which; 
-    }
-    /* copy node */
+
     RTreeCopyNode(n, &(t->nb[level][which].n), t);
-    assert(n->level == level);
+    
+    /* return &(t->nb[level][which].n); */
 }
 
 /* write branch to file */
@@ -171,78 +192,128 @@
     return RTreeWriteNode(n, t);
 }
 
+/* mark node in buffer as changed */
+void RTreeNodeChanged(struct RTree_Node *n, off_t nodepos, struct RTree *t)
+{
+    int which, i = 0;
+
+    /* check mru first */
+    while (t->nb[n->level][t->used[n->level][i]].pos != nodepos &&
+           i < NODE_BUFFER_SIZE)
+	i++;
+
+    assert(i < NODE_BUFFER_SIZE);
+    /* as it is used, it should always be mru */
+    assert(i == 0);
+    which = t->used[n->level][i];
+    assert(t->nb[n->level][which].n.level == n->level);
+
+    t->nb[n->level][which].dirty = 1;
+
+    /* make it mru */
+    if (i) { /* t->used[level][0] != which */
+#ifdef USAGE_SWAP
+	t->used[n->level][i] = t->used[n->level][0];
+	t->used[n->level][0] = which;
+#else
+	while (i) {
+	    t->used[n->level][i] = t->used[n->level][i - 1];
+	    i--;
+	}
+	t->used[n->level][0] = which;
+#endif
+    }
+}
+
 /* update node in buffer */
 void RTreePutNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
 {
-    int which = 0;
+    int which, i = 0;
 
-    /* TODO: search with t->used[level][which] instead of which,
-     * then which = t->used[level][which] */
-    while (t->nb[n->level][which].pos != nodepos && which < 2)
-	which++;
+    /* check mru first */
+    while (t->nb[n->level][t->used[n->level][i]].pos != nodepos &&
+           i < NODE_BUFFER_SIZE)
+	i++;
 
-    assert(t->nb[n->level][which].pos == nodepos);
+    assert(i < NODE_BUFFER_SIZE);
+    /* as it is used, it should always be mru */
+    assert(i == 0);
+    which = t->used[n->level][i];
+
     assert(t->nb[n->level][which].n.level == n->level);
     /* copy node */
     RTreeCopyNode(&(t->nb[n->level][which].n), n, t);
     t->nb[n->level][which].dirty = 1;
 
     /* make it mru */
-    if (t->used[n->level][2] == which) {
-	t->used[n->level][2] = t->used[n->level][1];
-	t->used[n->level][1] = t->used[n->level][0];
-	t->used[n->level][0] = which; 
+    if (i) { /* t->used[level][0] != which */
+#ifdef USAGE_SWAP
+	t->used[n->level][i] = t->used[n->level][0];
+	t->used[n->level][0] = which;
+#else
+	while (i) {
+	    t->used[n->level][i] = t->used[n->level][i - 1];
+	    i--;
+	}
+	t->used[n->level][0] = which;
+#endif
     }
-    else if (t->used[n->level][1] == which) {
-	t->used[n->level][1] = t->used[n->level][0];
-	t->used[n->level][0] = which; 
-    }
 }
 
 /* update rectangle */
 void RTreeUpdateRect(struct RTree_Rect *r, struct RTree_Node *n,
                      off_t nodepos, int b, struct RTree *t)
 {
-    int i, j;
-    int which = 0;
-    
-    while (t->nb[n->level][which].pos != nodepos && which < 2)
-	which++;
+    int i, j, k, which;
 
+    /* check mru first */
+    i = 0;
+    while (t->nb[n->level][t->used[n->level][i]].pos != nodepos &&
+           i < NODE_BUFFER_SIZE)
+	i++;
+
+    assert(i < NODE_BUFFER_SIZE);
+    /* as it is used, it should always be mru */
+    assert(i == 0);
+    which = t->used[n->level][i];
+
     assert(t->nb[n->level][which].n.level == n->level);
-    for (i = 0; i < t->ndims_alloc; i++) {
-	t->nb[n->level][which].n.branch[b].rect.boundary[i] =
-	                  n->branch[b].rect.boundary[i] = r->boundary[i];
-	j = i + t->ndims_alloc;
+    for (j = 0; j < t->ndims_alloc; j++) {
 	t->nb[n->level][which].n.branch[b].rect.boundary[j] =
 	                  n->branch[b].rect.boundary[j] = r->boundary[j];
+	k = j + t->ndims_alloc;
+	t->nb[n->level][which].n.branch[b].rect.boundary[k] =
+	                  n->branch[b].rect.boundary[k] = r->boundary[k];
     }
 
     t->nb[n->level][which].dirty = 1;
 
     /* make it mru */
-    if (t->used[n->level][2] == which) {
-	t->used[n->level][2] = t->used[n->level][1];
-	t->used[n->level][1] = t->used[n->level][0];
-	t->used[n->level][0] = which; 
+    if (i) { /* t->used[level][0] != which */
+#ifdef USAGE_SWAP
+	t->used[n->level][i] = t->used[n->level][0];
+	t->used[n->level][0] = which;
+#else
+	while (i) {
+	    t->used[n->level][i] = t->used[n->level][i - 1];
+	    i--;
+	}
+	t->used[n->level][0] = which;
+#endif
     }
-    else if (t->used[n->level][1] == which) {
-	t->used[n->level][1] = t->used[n->level][0];
-	t->used[n->level][0] = which; 
-    }
 }
 
 /* flush pending changes to file */
 void RTreeFlushBuffer(struct RTree *t)
 {
-    int i;
+    int i, j;
     
     for (i = 0; i <= t->rootlevel; i++) {
-	if (t->nb[i][0].dirty)
-	    RTreeRewriteNode(&(t->nb[i][0].n), t->nb[i][0].pos, t);
-	if (t->nb[i][1].dirty)
-	    RTreeRewriteNode(&(t->nb[i][1].n), t->nb[i][1].pos, t);
-	if (t->nb[i][2].dirty)
-	    RTreeRewriteNode(&(t->nb[i][2].n), t->nb[i][2].pos, t);
+	for (j = 0; j < NODE_BUFFER_SIZE; j++) {
+	    if (t->nb[i][j].dirty) {
+		RTreeRewriteNode(&(t->nb[i][j].n), t->nb[i][j].pos, t);
+		t->nb[i][j].dirty = 0;
+	    }
+	}
     }
 }

Modified: grass/trunk/lib/vector/rtree/node.c
===================================================================
--- grass/trunk/lib/vector/rtree/node.c	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/node.c	2012-11-18 19:21:23 UTC (rev 53901)
@@ -83,7 +83,7 @@
     n->level = level;
 
     for (i = 0; i < MAXCARD; i++) {
-	RTreeAllocBoundary(&(n->branch[i].rect), t);
+	n->branch[i].rect.boundary = RTreeAllocBoundary(t);
 	RTreeInitBranch[NODETYPE(level, t->fd)](&(n->branch[i]), t);
     }
 
@@ -433,7 +433,7 @@
        (struct RTree_ListBranch *)malloc(sizeof(struct RTree_ListBranch));
 
     assert(p);
-    RTreeAllocBoundary(&(p->b.rect), t);
+    p->b.rect.boundary = RTreeAllocBoundary(t);
 
     return p;
 }

Modified: grass/trunk/lib/vector/rtree/rect.c
===================================================================
--- grass/trunk/lib/vector/rtree/rect.c	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/rect.c	2012-11-18 19:21:23 UTC (rev 53901)
@@ -52,7 +52,7 @@
 
     assert(r);
 
-    RTreeAllocBoundary(r, t);
+    r->boundary = RTreeAllocBoundary(t);
     return r;
 }
 
@@ -81,11 +81,13 @@
            self allocated.
  \param t: The pointer to a RTree struct
 -----------------------------------------------------------------------------*/
-void RTreeAllocBoundary(struct RTree_Rect *r, struct RTree *t)
+RectReal *RTreeAllocBoundary(struct RTree *t)
 {
-    assert(r && t);
-    r->boundary = (RectReal *)malloc(t->rectsize);
-    assert(r->boundary);
+    RectReal *boundary = (RectReal *)malloc(t->rectsize);
+
+    assert(boundary);
+
+    return boundary;
 }
 
 /**----------------------------------------------------------------------------
@@ -111,7 +113,7 @@
 {
     register int i;
 
-    for (i = 0; i < t->ndims; i++)
+    for (i = 0; i < t->ndims_alloc; i++)
 	r->boundary[i] = r->boundary[i + t->ndims_alloc] = (RectReal) 0;
 }
 
@@ -229,8 +231,8 @@
     /* assert(r); */
 
     r->boundary[0] = (RectReal) 1;
-    r->boundary[t->nsides - 1] = (RectReal) - 1;
-    for (i = 1; i < t->ndims; i++)
+    r->boundary[t->nsides_alloc - 1] = (RectReal) - 1;
+    for (i = 1; i < t->ndims_alloc; i++)
 	r->boundary[i] = r->boundary[i + t->ndims_alloc] = (RectReal) 0;
 
     return;
@@ -508,14 +510,14 @@
     /* assert(r1 && r2 && r3); */
 
     if (Undefined(r1, t)) {
-	for (i = 0; i < t->nsides; i++)
+	for (i = 0; i < t->nsides_alloc; i++)
 	    r3->boundary[i] = r2->boundary[i];
 
 	return;
     }
 
     if (Undefined(r2, t)) {
-	for (i = 0; i < t->nsides; i++)
+	for (i = 0; i < t->nsides_alloc; i++)
 	    r3->boundary[i] = r1->boundary[i];
 
 	return;

Modified: grass/trunk/lib/vector/rtree/rtree.h
===================================================================
--- grass/trunk/lib/vector/rtree/rtree.h	2012-11-18 19:00:14 UTC (rev 53900)
+++ grass/trunk/lib/vector/rtree/rtree.h	2012-11-18 19:21:23 UTC (rev 53901)
@@ -51,6 +51,9 @@
 /* maximum no of levels = tree depth */
 #define MAXLEVEL 20        /* 8^MAXLEVEL items are guaranteed to fit into the tree */
 
+/* number of nodes buffered per level */
+#define NODE_BUFFER_SIZE 4
+
 struct RTree_Rect
 {
     RectReal *boundary;	/* xmin,ymin,...,xmax,ymax,... */
@@ -111,6 +114,14 @@
     int branch_id;		/* branch number to follow down */
 };
 
+/* node buffer for file-based index */
+struct NodeBuffer
+{
+    struct RTree_Node n;	/* buffered node */
+    off_t pos;	    		/* file position of buffered node */
+    char dirty;         	/* node in buffer was modified */
+};
+
 /* temp vars for node splitting */
 struct RTree_PartitionVars {
     int partition[MAXCARD + 1];
@@ -154,19 +165,13 @@
         off_t *pos;         /* array of available positions */
     } free_nodes;
 
-    /* node buffer for file-based index, three nodes per level
-     * more than three nodes per level would require too complex cache management */
-    struct NodeBuffer
-    {
-	struct RTree_Node n;	    /* buffered node */
-	off_t pos;	    /* file position of buffered node */
-	char dirty;         /* node in buffer was modified */
-    } nb[MAXLEVEL][3];
+    /* node buffer for file-based index */
+    struct NodeBuffer **nb;
 
     /* usage order of buffered nodes per level
      * used[level][0] = most recently used
-     * used[level][2] = least recently used */
-    char used[MAXLEVEL][3];
+     * used[level][NODE_BUFFER_SIZE - 1] = least recently used */
+    int used[MAXLEVEL][NODE_BUFFER_SIZE];
 
     /* insert, delete, search */
     rt_insert_fn *insert_rect;
@@ -228,7 +233,7 @@
 /* RTree rectangle allocation and deletion */
 struct RTree_Rect *RTreeAllocRect(struct RTree *t);
 void RTreeFreeRect(struct RTree_Rect *r);
-void RTreeAllocBoundary(struct RTree_Rect *r, struct RTree *t);
+RectReal *RTreeAllocBoundary(struct RTree *t);
 void RTreeFreeBoundary(struct RTree_Rect *r);
 
 /* RTree IO */



More information about the grass-commit mailing list