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

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Jan 4 15:06:37 EST 2011


Author: mmetz
Date: 2011-01-04 12:06:37 -0800 (Tue, 04 Jan 2011)
New Revision: 44867

Modified:
   grass/trunk/lib/vector/rtree/index.c
   grass/trunk/lib/vector/rtree/index.h
   grass/trunk/lib/vector/rtree/io.c
Log:
R*Tree: three buffered nodes per level

Modified: grass/trunk/lib/vector/rtree/index.c
===================================================================
--- grass/trunk/lib/vector/rtree/index.c	2011-01-04 13:45:49 UTC (rev 44866)
+++ grass/trunk/lib/vector/rtree/index.c	2011-01-04 20:06:37 UTC (rev 44867)
@@ -68,9 +68,14 @@
 	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->mru[i] = 0;
+	    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;
 	}
 
 	/* write empty root node */
@@ -78,7 +83,8 @@
 	RTreeWriteNode(n, new_rtree);
 	new_rtree->nb[0][0].n = *n;
 	new_rtree->nb[0][0].pos = rootpos;
-	new_rtree->mru[0] = 0;
+	new_rtree->used[0][0] = 0;
+	new_rtree->used[0][2] = 2;
 	RTreeFreeNode(n);
 
 	new_rtree->insert_rect = RTreeInsertRectF;

Modified: grass/trunk/lib/vector/rtree/index.h
===================================================================
--- grass/trunk/lib/vector/rtree/index.h	2011-01-04 13:45:49 UTC (rev 44866)
+++ grass/trunk/lib/vector/rtree/index.h	2011-01-04 20:06:37 UTC (rev 44867)
@@ -129,17 +129,20 @@
         off_t *pos;         /* array of available positions */
     } free_nodes;
 
-    /* node buffer for file-based index, two nodes per level
-     * more than two nodes per level would require too complex cache management:
-     * lru or pseudo-lru replacement, searching for buffered 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 Node n;	    /* buffered node */
 	off_t pos;	    /* file position of buffered node */
 	char dirty;         /* node in buffer was modified */
-    } nb[MAXLEVEL][2];
-    char mru[MAXLEVEL];     /* most recently used buffered node per level */
+    } nb[MAXLEVEL][3];
 
+    /* usage order of buffered nodes per level
+     * used[level][0] = most recently used
+     * used[level][2] = least recently used */
+    char used[MAXLEVEL][3];
+
     /* insert, delete, search */
     rt_insert_fn *insert_rect;
     rt_delete_fn *delete_rect;

Modified: grass/trunk/lib/vector/rtree/io.c
===================================================================
--- grass/trunk/lib/vector/rtree/io.c	2011-01-04 13:45:49 UTC (rev 44866)
+++ grass/trunk/lib/vector/rtree/io.c	2011-01-04 20:06:37 UTC (rev 44867)
@@ -39,10 +39,20 @@
     }
     t->free_nodes.pos[t->free_nodes.avail++] = pos;
     
-    which = pos == t->nb[level][1].pos;
+    which = (pos == t->nb[level][2].pos ? 2 : pos == t->nb[level][1].pos);
     t->nb[level][which].pos = -1;
     t->nb[level][which].dirty = 0;
-    t->mru[level] = which == 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; 
+    }
+    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 */
@@ -67,14 +77,11 @@
 /* get node from buffer or file */
 void RTreeGetNode(struct Node *n, off_t nodepos, int level, struct RTree *t)
 {
-    int which = nodepos == t->nb[level][1].pos;
+    int which = (nodepos == t->nb[level][2].pos ? 2 : nodepos == t->nb[level][1].pos);
 
     if (t->nb[level][which].pos != nodepos) {
-	/* which is 0 */
-	/* replace least recently used */
-	/* least recently used is faster than most recently used */
-	if (t->nb[level][which].pos != -1)
-	    which = t->mru[level] == 0;
+	/* replace least recently used (fastest method of lru, pseudo-lru, mru) */
+	which = t->used[level][2];
 	/* rewrite node in buffer */
 	if (t->nb[level][which].dirty) {
 	    RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos, t);
@@ -83,7 +90,16 @@
 	RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
 	t->nb[level][which].pos = nodepos;
     }
-    t->mru[level] = which;
+    /* 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; 
+    }
+    else if (t->used[level][1] == which) {
+	t->used[level][1] = t->used[level][0];
+	t->used[level][0] = which; 
+    }
     *n = t->nb[level][which].n;
 }
 
@@ -104,21 +120,41 @@
 /* update node in buffer */
 void RTreePutNode(struct Node *n, off_t nodepos, struct RTree *t)
 {
-    int which = nodepos == t->nb[n->level][1].pos;
+    int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
     
     t->nb[n->level][which].n = *n;
     t->nb[n->level][which].dirty = 1;
-    t->mru[n->level] = which;
+
+    /* 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; 
+    }
+    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 Rect *r, struct Node *n, off_t nodepos, int b, struct RTree *t)
 {
-    int which = nodepos == t->nb[n->level][1].pos;
+    int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
     
     t->nb[n->level][which].n.branch[b].rect = n->branch[b].rect = *r;
     t->nb[n->level][which].dirty = 1;
-    t->mru[n->level] = which;
+
+    /* 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; 
+    }
+    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 */
@@ -131,5 +167,7 @@
 	    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);
     }
 }



More information about the grass-commit mailing list