[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