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]

Reply via email to