Changeset: 4720c5def5d1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/4720c5def5d1
Added Files:
        gdk/gdk_rtree.c
        gdk/gdk_rtree.h
Modified Files:
        gdk/gdk.h
Branch: geo-update-dev
Log Message:

First version of rtree index (using librtree). BATrtree builds the index on a 
geometry BAT and RTREEsearch searches for intersecting geometries to the input 
mbr. Added variable in gdk.h that was not correctly set by the librtree.


diffs (180 lines):

diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -351,6 +351,11 @@ gdk_export _Noreturn void GDKfatal(_In_z
 #include "stream.h"
 #include "mstring.h"
 
+#ifndef SIZEOF_RTREE_COORD_T
+#define SIZEOF_RTREE_COORD_T 4
+#endif
+#include <rtree.h>
+
 #undef MIN
 #undef MAX
 #define MAX(A,B)       ((A)<(B)?(B):(A))
@@ -740,6 +745,8 @@ 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;
+       
        Imprints *imprints;     /* column imprints index */
        Heap *orderidx;         /* order oid index */
        Strimps *strimps;       /* string imprint index  */
diff --git a/gdk/gdk_rtree.c b/gdk/gdk_rtree.c
new file mode 100644
--- /dev/null
+++ b/gdk/gdk_rtree.c
@@ -0,0 +1,128 @@
+#include "monetdb_config.h"
+#include "gdk.h"
+#include "gdk_private.h"
+#include "gdk_rtree.h"
+
+//TODO The check for hasrtree should look into the parent BAT, not just 
compare the BAT->rtree to NULL
+
+// Persist rtree to disk if the conditions are right
+/*static void
+persistRtree (BAT *b)
+{*/
+       /* Conditions to persist the RTree:
+        * - BAT has to be persistent
+        * - No deleted rows (when does batInserted update?)
+        * - The heap is not dirty -> no new values
+        * - DB Farm is persistent i.e. not in memory
+        */
+/*     if ((BBP_status(b->batCacheid) & BBPEXISTING)
+            && b->batInserted == b->batCount
+            && !b->theap->dirty
+            && !GDKinmemory(b->theap->farmid)) {
+               BBPfix(b->batCacheid);
+               //char name[MT_NAME_LEN];
+               //snprintf(name, sizeof(name), "rtreesync%d", b->batCacheid);
+       }
+}*/
+
+//TODO Make this multi-thread safe? -> Only allow one thread to do rtree_new 
and persist the BAT, but multiple threads can add new rects to the tree
+//MBR bat
+gdk_return
+BATrtree_wkb(BAT *wkb, BAT *mbr)
+{
+       BAT *pb;
+       BATiter bi;
+       rtree_t *rtree = NULL;
+       struct canditer ci;
+
+       //TODO check for MBR type
+
+       //Check for a parent BAT of wkb, load if exists
+       if (VIEWtparent(wkb)) {
+               pb = BBP_cache(VIEWtparent(wkb));
+               assert(pb);
+       } else {
+               pb = wkb;
+       }
+
+       //Check if rtree already exists
+       //TODO Check if it is on disk
+       if (pb->T.rtree == NULL) {
+               //If it doesn't exist, take the lock to create/get the rtree
+               MT_lock_set(&pb->batIdxLock);
+
+               //Try to load it from disk
+               //TODO BATcheckrtree
+
+               //First arg are dimensions: we only allow x, y
+               //Second arg are flags: split strategy and nodes-per-page
+               if ((rtree = rtree_new(2, RTREE_DEFAULT)) == NULL) {
+                       GDKerror("rtree_new failed\n");
+                       return GDK_FAIL;
+               }
+               bi = bat_iterator(mbr);
+               canditer_init(&ci, mbr,NULL);
+
+               for (BUN i = 0; i < ci.ncand; i++) {
+                       oid p = canditer_next(&ci) - mbr->hseqbase;
+                       mbr_t *inMBR = (mbr_t *)BUNtail(bi, p);
+
+                       rtree_id_t rtree_id = i;
+                       rtree_coord_t rect[4];
+                       rect[0] = inMBR->xmin;
+                       rect[1] = inMBR->ymin;
+                       rect[2] = inMBR->xmax;
+                       rect[3] = inMBR->ymax;
+                       rtree_add_rect(rtree,rtree_id,rect);
+               }
+               bat_iterator_end(&bi);
+               pb->T.rtree = rtree;
+               //TODO persist rtree
+               MT_lock_unset(&pb->batIdxLock);
+       }
+       //TODO Check if the rtree is complete in case of already existing rtree 
(not NULL)
+       return GDK_SUCCEED;
+}
+
+struct results_rtree {
+       int results_next;
+       int results_left;
+       BUN* candidates;
+};
+
+static int
+f (rtree_id_t id, void *context) {
+       struct results_rtree *results_rtree = (struct results_rtree *) context;
+       results_rtree->candidates[results_rtree->results_next++] = (BUN) id;
+       results_rtree->results_left -= 1;
+       return results_rtree->results_left <= 0;
+}
+
+BUN*
+RTREEsearch(BAT *b, mbr_t *inMBR, int result_limit) {
+       BAT *pb;
+       if (VIEWtparent(b)) {
+               pb = BBP_cache(VIEWtparent(b));
+               assert(pb);
+       } else {
+               pb = b;
+       }
+       rtree_t *rtree = pb->T.rtree;
+       if (rtree != NULL) {
+               BUN *candidates = GDKmalloc(result_limit*sizeof(BUN));
+               memset(candidates,BUN_NONE,result_limit*sizeof(BUN));
+
+               rtree_coord_t rect[4];
+               rect[0] = inMBR->xmin;
+               rect[1] = inMBR->ymin;
+               rect[2] = inMBR->xmax;
+               rect[3] = inMBR->ymax;
+               struct results_rtree results;
+               results.results_next = 0;
+               results.results_left = result_limit;
+               results.candidates = candidates;
+               rtree_search(rtree, (const rtree_coord_t*) rect, f, &results);
+               return candidates;
+       } else
+               return NULL;
+}
diff --git a/gdk/gdk_rtree.h b/gdk/gdk_rtree.h
new file mode 100644
--- /dev/null
+++ b/gdk/gdk_rtree.h
@@ -0,0 +1,18 @@
+#ifndef SIZEOF_RTREE_COORD_T
+#define SIZEOF_RTREE_COORD_T 4
+#endif
+#include <rtree.h>
+
+typedef struct mbr_t {
+       float xmin;
+       float ymin;
+       float xmax;
+       float ymax;
+
+} mbr_t;
+//TODO REMOVE
+
+gdk_export gdk_return BATrtree(BAT *b);
+gdk_export gdk_return BATrtree_wkb(BAT *wkb, BAT* mbr);
+gdk_export void RTREEdestroy(BAT *b);
+gdk_export BUN* RTREEsearch(BAT *b, mbr_t *inMBR, int result_limit);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to