Changeset: acddb6337e36 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/acddb6337e36
Removed Files:
gdk/gdk_rtree.h
Modified Files:
gdk/gdk.h
gdk/gdk_private.h
gdk/gdk_rtree.c
geom/monetdb5/geod.c
Branch: geo-update-dev
Log Message:
Added logical references to RTree functions, complete with increase and
decrease references. RTreeDestroy and RTreeFree improved.
diffs (298 lines):
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -584,6 +584,7 @@ typedef struct {
typedef struct Hash Hash;
typedef struct Imprints Imprints;
typedef struct Strimps Strimps;
+typedef struct RTree RTree;
/*
* @+ Binary Association Tables
@@ -745,7 +746,7 @@ typedef struct {
BUN baseoff; /* offset in heap->base (in whole items) */
Heap *vheap; /* space for the varsized data. */
Hash *hash; /* hash table */
- rtree_t *rtree;
+ RTree *rtree;
Imprints *imprints; /* column imprints index */
Heap *orderidx; /* order oid index */
@@ -842,6 +843,7 @@ typedef struct BAT {
#define timprints T.imprints
#define tprops T.props
#define tstrimps T.strimps
+#define trtree T.rtree
/* some access functions for the bitmask type */
@@ -1873,9 +1875,11 @@ typedef struct mbr_t {
gdk_export bool RTREEexists(BAT *b);
gdk_export gdk_return BATrtree(BAT *wkb, BAT* mbr);
-gdk_export void RTREEdestroy(BAT *b);
gdk_export BUN* RTREEsearch(BAT *b, mbr_t *inMBR, int result_limit);
gdk_export void RTREEdestroy(BAT *b);
+gdk_export void RTREEfree(BAT *b);
+gdk_export void RTREEdecref(RTree *rtree);
+gdk_export void RTREEincref(RTree *rtree);
/* The ordered index structure */
diff --git a/gdk/gdk_private.h b/gdk/gdk_private.h
--- a/gdk/gdk_private.h
+++ b/gdk/gdk_private.h
@@ -457,6 +457,12 @@ struct Strimps {
/* bitstrings_base is a pointer to uint64_t */
};
+struct RTree {
+ ATOMIC_TYPE refs; /* counter for logical references to the rtree
*/
+ rtree_t *rtree; /* rtree structure */
+ bool destroy; /* destroy rtree when there are no more logical
references */
+};
+
typedef struct {
MT_Lock swap;
} batlock_t;
diff --git a/gdk/gdk_rtree.c b/gdk/gdk_rtree.c
--- a/gdk/gdk_rtree.c
+++ b/gdk/gdk_rtree.c
@@ -3,9 +3,11 @@
#include "gdk_private.h"
//TODO Why use BBPselectfarm?
-//TODO Do we need to guard against dirty heap and deleted rows?
-//TODO Where do put the RTREEdestroy calls? We should invalidate on updates,
deletes and inserts
+//TODO Do we need to guard against dirty heap and deleted rows? -> Panos only
does this for persisting, not creating
+//TODO Where do put the RTREEdestroy calls? We should invalidate on updates,
deletes and inserts -> Check Panos impl
+
+//TODO Re-check the conditions
/* Conditions to create and persist the RTree:
* - BAT has to be persistent
* - No deleted rows (when does batInserted update?)
@@ -13,21 +15,41 @@
* - DB Farm is persistent i.e. not in memory
*/
static bool
-RTreecreatecheck (BAT *b) {
+RTREEcreatecheck (BAT *b) {
return ((BBP_status(b->batCacheid) & BBPEXISTING)
&& b->batInserted == b->batCount
&& !b->theap->dirty
&& !GDKinmemory(b->theap->farmid));
}
+void
+RTREEdecref(RTree *rtree)
+{
+ ATOMIC_BASE_TYPE refs = ATOMIC_DEC(&rtree->refs);
+ //If RTree is marked for destruction and there are no refs, destroy the
RTree
+ if (rtree->destroy && refs == 0) {
+ ATOMIC_DESTROY(&rtree->refs);
+ rtree_destroy(rtree->rtree);
+ rtree->rtree = NULL;
+ rtree = NULL;
+ }
+
+}
+
+void
+RTREEincref(RTree *rtree)
+{
+ ATOMIC_INC(&rtree->refs);
+}
+
// Persist rtree to disk if the conditions are right
static gdk_return
persistRtree (BAT *b)
{
- if (RTreecreatecheck(b)) {
+ if (RTREEcreatecheck(b)) {
//TODO Necessary?
BBPfix(b->batCacheid);
- rtree_t *rtree = b->T.rtree;
+ rtree_t *rtree = b->trtree->rtree;
if (rtree) {
const char * filename = BBP_physical(b->batCacheid);
@@ -86,7 +108,7 @@ BATcheckrtree(BAT *b) {
fclose(file_stream);
return GDK_FAIL;
}
- b->T.rtree = rtree;
+ b->trtree->rtree = rtree;
fclose(file_stream);
}
else {
@@ -94,6 +116,8 @@ BATcheckrtree(BAT *b) {
close(fd);
return GDK_FAIL;
}
+ b->trtree->destroy = false;
+ ATOMIC_INIT(&b->trtree->refs, 1);
return GDK_SUCCEED;
}
@@ -111,7 +135,7 @@ RTREEexists(BAT *b)
}
MT_lock_set(&pb->batIdxLock);
- ret = pb->T.rtree != NULL;
+ ret = pb->trtree->rtree != NULL;
MT_lock_unset(&pb->batIdxLock);
return ret;
@@ -135,12 +159,12 @@ BATrtree(BAT *wkb, BAT *mbr)
}
//Check if rtree already exists
- if (pb->T.rtree == NULL && RTreecreatecheck(pb)) {
+ if (pb->trtree->rtree == NULL && RTREEcreatecheck(pb)) {
//If it doesn't exist, take the lock to create/get the rtree
MT_lock_set(&pb->batIdxLock);
//Try to load it from disk
- if (BATcheckrtree(pb) == GDK_SUCCEED && pb->T.rtree != NULL) {
+ if (BATcheckrtree(pb) == GDK_SUCCEED && pb->trtree->rtree !=
NULL) {
MT_lock_unset(&pb->batIdxLock);
return GDK_SUCCEED;
}
@@ -167,13 +191,37 @@ BATrtree(BAT *wkb, BAT *mbr)
rtree_add_rect(rtree,rtree_id,rect);
}
bat_iterator_end(&bi);
- pb->T.rtree = rtree;
+ pb->trtree->rtree = rtree;
+ pb->trtree->destroy = false;
+ ATOMIC_INIT(&pb->trtree->refs, 1);
persistRtree(pb);
MT_lock_unset(&pb->batIdxLock);
}
return GDK_SUCCEED;
}
+//Free the RTree from memory,
+void
+RTREEfree(BAT *b)
+{
+ BAT *pb;
+ if (VIEWtparent(b)) {
+ pb = BBP_cache(VIEWtparent(b));
+ assert(pb);
+ } else {
+ pb = b;
+ }
+
+ if (pb && pb->trtree->rtree) {
+ MT_lock_set(&pb->batIdxLock);
+ //Mark the RTree for destruction
+ pb->trtree->destroy = true;
+ RTREEdecref(pb->trtree);
+ MT_lock_unset(&b->batIdxLock);
+ }
+}
+
+//Free the RTree from memory, unlink the file associated with it
void
RTREEdestroy(BAT *b)
{
@@ -185,14 +233,19 @@ RTREEdestroy(BAT *b)
pb = b;
}
- if (pb && pb->T.rtree) {
+ //TODO When there is a RTree index on file (i.e. not loaded yet) and
this method is called, we should unlink the file (no need to touch refs)
+ if (pb && pb->trtree->rtree) {
MT_lock_set(&pb->batIdxLock);
- rtree_destroy(pb->T.rtree);
- pb->T.rtree = NULL;
- GDKunlink(pb->theap->farmid,
- BATDIR,
- BBP_physical(b->batCacheid),
- "bsrt");
+ //Mark the RTree for destruction
+ pb->trtree->destroy = true;
+ RTREEdecref(pb->trtree);
+ //If the farm is in-memory, don't unlink the file (there is no
file in that case)
+ if (GDKinmemory(pb->theap->farmid)) {
+ GDKunlink(pb->theap->farmid,
+ BATDIR,
+ BBP_physical(b->batCacheid),
+ "bsrt");
+ }
MT_lock_unset(&b->batIdxLock);
}
}
@@ -220,8 +273,21 @@ RTREEsearch(BAT *b, mbr_t *inMBR, int re
} else {
pb = b;
}
- rtree_t *rtree = pb->T.rtree;
+
+ //Try to load if there is an RTree index on file
+ MT_lock_set(&pb->batIdxLock);
+ if (pb->trtree == NULL) {
+ if (BATcheckrtree(pb) != GDK_SUCCEED) {
+ MT_lock_unset(&pb->batIdxLock);
+ return NULL;
+ }
+ }
+ MT_lock_unset(&pb->batIdxLock);
+
+ rtree_t *rtree = pb->trtree->rtree;
if (rtree != NULL) {
+ //Increase ref, we're gonna use the index
+ RTREEincref(pb->trtree);
BUN *candidates = GDKmalloc(result_limit*sizeof(BUN));
memset(candidates,BUN_NONE,result_limit*sizeof(BUN));
@@ -235,6 +301,8 @@ RTREEsearch(BAT *b, mbr_t *inMBR, int re
results.results_left = result_limit;
results.candidates = candidates;
rtree_search(rtree, (const rtree_coord_t*) rect, f, &results);
+ //Finished using the index, decrease ref
+ RTREEdecref(pb->trtree);
return candidates;
} else
return NULL;
diff --git a/gdk/gdk_rtree.h b/gdk/gdk_rtree.h
deleted file mode 100644
--- a/gdk/gdk_rtree.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef SIZEOF_RTREE_COORD_T
-#define SIZEOF_RTREE_COORD_T 4
-#endif
-#include <rtree.h>
-
-//TODO REMOVE
-typedef struct mbr_t {
- float xmin;
- float ymin;
- float xmax;
- float ymax;
-
-} mbr_t;
-
-gdk_export bool RTREEexists(BAT *b);
-gdk_export gdk_return BATrtree(BAT *wkb, BAT* mbr);
-gdk_export void RTREEdestroy(BAT *b);
-gdk_export BUN* RTREEsearch(BAT *b, mbr_t *inMBR, int result_limit);
diff --git a/geom/monetdb5/geod.c b/geom/monetdb5/geod.c
--- a/geom/monetdb5/geod.c
+++ b/geom/monetdb5/geod.c
@@ -7,6 +7,12 @@
const double earth_radius = 6371.009;
const double earth_radius_meters = 6371009;
+#ifndef M_PI
+#define M_PI ((double) 3.14159265358979323846) /* pi */
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923132169163975144 /* pi/2
*/
+#endif
/* Converts a longitude value in degrees to radians */
static double
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]