Changeset: d3d1a38907d1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d3d1a38907d1
Modified Files:
        sql/backends/monet5/sql.c
        sql/storage/bat/bat_storage.c
        sql/storage/sql_storage.h
Branch: default
Log Message:

Added bind_updates_idx interface to avoid race conditions on idxs update bats


diffs (truncated from 306 to 300 lines):

diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -1565,16 +1565,19 @@ str
 mvc_bind_idxbat_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
        int upd = (pci->argc == 7 || pci->argc == 9);
-       BAT *b = NULL, *bn;
+       BAT *b = NULL;
        bat *bid = getArgReference_bat(stk, pci, 0);
-       int coltype = getBatType(getArgType(mb, pci, 0));
        mvc *m = NULL;
        str msg;
-       const char *sname = *getArgReference_str(stk, pci, 2 + upd);
-       const char *tname = *getArgReference_str(stk, pci, 3 + upd);
-       const char *iname = *getArgReference_str(stk, pci, 4 + upd);
-       int access = *getArgReference_int(stk, pci, 5 + upd);
-
+       const char *sname       = *getArgReference_str(stk, pci, 2 + upd);
+       const char *tname       = *getArgReference_str(stk, pci, 3 + upd);
+       const char *iname       = *getArgReference_str(stk, pci, 4 + upd);
+       const int       access  = *getArgReference_int(stk, pci, 5 + upd);
+
+       const bool partitioned_access = pci->argc == (8 + upd) && 
getArgType(mb, pci, 6 + upd) == TYPE_int;
+
+       /* This doesn't work with quick access for now... */
+       assert(access != QUICK);
        if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
                return msg;
        if ((msg = checkSQLContext(cntxt)) != NULL)
@@ -1583,102 +1586,73 @@ mvc_bind_idxbat_wrap(Client cntxt, MalBl
        sql_schema *s = mvc_bind_schema(m, sname);
        sql_table *t = mvc_bind_table(m, s, tname);
        if (t && !isTable(t))
-               throw(SQL, "sql.tid", SQLSTATE(42000) "%s '%s' is not 
persistent",
+               throw(SQL, "sql.bindidx", SQLSTATE(42000) "%s '%s' is not 
persistent",
                          TABLE_TYPE_DESCRIPTION(t->type, t->properties), 
t->base.name);
        sql_idx *i = mvc_bind_idx(m, s, iname);
-       b = mvc_bind_idxbat(m, sname, tname, iname, access);
-       if (b && b->ttype && b->ttype != coltype) {
-               BBPunfix(b->batCacheid);
-               throw(SQL,"sql.bind",SQLSTATE(42000) "Index column type 
mismatch %s.%s.%s",sname,tname,iname);
-       }
-       if (b) {
-               if (pci->argc == (8 + upd) && getArgType(mb, pci, 6 + upd) == 
TYPE_int) {
-                       BUN cnt = store->storage_api.count_idx(m->session->tr, 
i, 0), psz;
-                       /* partitioned access */
-                       int part_nr = *getArgReference_int(stk, pci, 6 + upd);
-                       int nr_parts = *getArgReference_int(stk, pci, 7 + upd);
-
-                       if (access == 0) {
-                               BUN l, h;
-                               psz = cnt ? (cnt / nr_parts) : 0;
-                               l = part_nr * psz;
-                               if (l > cnt)
-                                       l = cnt;
-                               h = (part_nr + 1 == nr_parts) ? cnt : ((part_nr 
+ 1) * psz);
-                               if (h > cnt)
-                                       h = cnt;
-                               bn = BATslice(b, l, h);
-                               if(bn == NULL){
-                                       BBPunfix(b->batCacheid);
-                                       throw(SQL, "sql.bindidx", 
GDK_EXCEPTION);
-                               }
-                               BAThseqbase(bn, l);
-                       } else {
-                               /* BAT b holds the UPD_ID bat */
-                               oid l, h;
-                               cnt = 
store->storage_api.count_idx(m->session->tr, i, 0);
-                               psz = cnt ? (cnt / nr_parts) : 0;
-                               l = part_nr * psz;
-                               if (l > cnt)
-                                       l = cnt;
-                               h = (part_nr + 1 == nr_parts) ? cnt : ((part_nr 
+ 1) * psz);
-                               if (h > cnt)
-                                       h = cnt;
-                               h--;
-                               bn = BATselect(b, NULL, &l, &h, true, true, 
false);
-                               if(bn == NULL) {
-                                       BBPunfix(b->batCacheid);
-                                       throw(SQL, "sql.bindidx", 
GDK_EXCEPTION);
-                               }
+
+       if (partitioned_access) {
+               /* partitioned access */
+               int part_nr = *getArgReference_int(stk, pci, 6 + upd);
+               int nr_parts = *getArgReference_int(stk, pci, 7 + upd);
+               BUN cnt = store->storage_api.count_idx(m->session->tr, i, 0), 
psz;
+               oid l, h;
+               psz = cnt ? (cnt / nr_parts) : 0;
+               l = part_nr * psz;
+               if (l > cnt)
+                       l = cnt;
+               h = (part_nr + 1 == nr_parts) ? cnt : ((part_nr + 1) * psz);
+               if (h > cnt)
+                       h = cnt;
+
+               if (upd) {
+                       sql_updates* updates = 
store->storage_api.bind_updates_idx(m->session->tr, i);
+
+                       if (!updates)
+                               throw(SQL,"sql.bindidx",SQLSTATE(HY005) "Cannot 
access the update columns");
+                       BAT *ui = updates->ui;
+                       BAT *uv = updates->uv;
+                       GDKfree(updates);
+
+                       h--;
+                       BAT* bn = BATselect(ui, NULL, &l, &h, true, true, 
false);
+                       if(bn == NULL) {
+                               BBPunfix(ui->batCacheid);
+                               BBPunfix(uv->batCacheid);
+                               throw(SQL, "sql.bindidx", GDK_EXCEPTION);
                        }
-                       BBPunfix(b->batCacheid);
-                       b = bn;
-               } else if (upd) {
-                       BAT *uv = mvc_bind_idxbat(m, sname, tname, iname, 
RD_UPD_VAL);
+
                        bat *uvl = getArgReference_bat(stk, pci, 1);
-                       if ( uv == NULL){
-                               BBPunfix(b->batCacheid);
-                               throw(SQL,"sql.bindidx",SQLSTATE(42000) "Cannot 
access index column %s.%s.%s",sname,tname,iname);
-                       }
-                       *bid = b->batCacheid;
-                       BBPkeepref(b);
-                       *uvl = uv->batCacheid;
-                       BBPkeepref(uv);
-                       return MAL_SUCCEED;
-               }
-               if (upd) {
-                       bat *uvl = getArgReference_bat(stk, pci, 1);
-
-                       if (BATcount(b)) {
-                               BAT *uv = mvc_bind_idxbat(m, sname, tname, 
iname, RD_UPD_VAL);
-                               BAT *ui = mvc_bind_idxbat(m, sname, tname, 
iname, RD_UPD_ID);
-                               BAT *id, *vl;
-                               if ( ui == NULL || uv == NULL) {
+
+                       if (BATcount(bn)) {
+                               BAT *id;
+                               BAT *vl;
+                               if (ui == NULL || uv == NULL) {
                                        bat_destroy(uv);
                                        bat_destroy(ui);
-                                       BBPunfix(b->batCacheid);
+                                       BBPunfix(bn->batCacheid);
                                        throw(SQL,"sql.bindidx",SQLSTATE(42000) 
"Cannot access index column %s.%s.%s",sname,tname,iname);
                                }
-                               id = BATproject(b, ui);
-                               vl = BATproject(b, uv);
+                               assert(uv->batCount == ui->batCount);
+                               id = BATproject(bn, ui);
+                               vl = BATproject(bn, uv);
                                bat_destroy(ui);
                                bat_destroy(uv);
                                if (id == NULL || vl == NULL) {
+                                       BBPunfix(bn->batCacheid);
                                        bat_destroy(id);
                                        bat_destroy(vl);
-                                       BBPunfix(b->batCacheid);
                                        throw(SQL, "sql.bindidx", 
GDK_EXCEPTION);
                                }
                                if ( BATcount(id) != BATcount(vl)){
-                                       BBPunfix(b->batCacheid);
+                                       BBPunfix(bn->batCacheid);
                                        bat_destroy(id);
                                        bat_destroy(vl);
                                        throw(SQL, "sql.bindidx", 
SQLSTATE(0000) "Inconsistent BAT count");
                                }
+                               BBPkeepref(id);
+                               BBPkeepref(vl);
                                *bid = id->batCacheid;
-                               BBPkeepref(id);
                                *uvl = vl->batCacheid;
-                               BBPkeepref(vl);
                        } else {
                                *bid = e_bat(TYPE_oid);
                                *uvl = 
e_bat((i->type==join_idx)?TYPE_oid:TYPE_lng);
@@ -1691,16 +1665,51 @@ mvc_bind_idxbat_wrap(Client cntxt, MalBl
                                        throw(SQL, "sql.bindidx", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
                                }
                        }
+               } else {
+                       int idxtype = getBatType(getArgType(mb, pci, 0));
+                       b = store->storage_api.bind_idx(m->session->tr, i, 
access);
+
+                       if (b && b->ttype && b->ttype != idxtype) {
+                               BBPunfix(b->batCacheid);
+                               throw(SQL,"sql.bindidx",SQLSTATE(42000) "Index 
type mismatch %s.%s.%s",sname,tname,iname);
+                       }
+
+                       BAT* bn = BATslice(b, l, h);
+                       if(bn == NULL) {
+                               BBPunfix(b->batCacheid);
+                               throw(SQL, "sql.bindidx", GDK_EXCEPTION);
+                       }
+                       BAThseqbase(bn, l);
                        BBPunfix(b->batCacheid);
-               } else {
-                       *bid = b->batCacheid;
-                       BBPkeepref(b);
+                       BBPkeepref(bn);
+                       *bid = bn->batCacheid;
                }
-               return MAL_SUCCEED;
-       }
-       if (sname)
-               throw(SQL, "sql.bindidx", SQLSTATE(HY005) "Cannot access column 
descriptor %s for %s.%s", iname, sname, tname);
-       throw(SQL, "sql.bindidx", SQLSTATE(HY005) "Cannot access column 
descriptor %s for %s", iname, tname);
+       }
+       else if (upd) { /*unpartitioned access to update bats*/
+               sql_updates* updates = 
store->storage_api.bind_updates_idx(m->session->tr, i);
+
+               if (!updates)
+                       throw(SQL,"sql.bindidx",SQLSTATE(HY005) "Cannot access 
the update columns");
+
+               bat *uvl = getArgReference_bat(stk, pci, 1);
+               BBPkeepref(updates->ui);
+               BBPkeepref(updates->uv);
+               *bid = updates->ui->batCacheid;
+               *uvl = updates->uv->batCacheid;
+               GDKfree(updates);
+       }
+       else { /*unpartitioned access to base index*/
+               int idxtype = getBatType(getArgType(mb, pci, 0));
+               b = store->storage_api.bind_idx(m->session->tr, i, access);
+
+               if (b && b->ttype && b->ttype != idxtype) {
+                       BBPunfix(b->batCacheid);
+                       throw(SQL,"sql.bindidx",SQLSTATE(42000) "Index type 
mismatch %s.%s.%s",sname,tname,iname);
+               }
+               BBPkeepref(b);
+               *bid = b->batCacheid;
+       }
+       return MAL_SUCCEED;
 }
 
 str
diff --git a/sql/storage/bat/bat_storage.c b/sql/storage/bat/bat_storage.c
--- a/sql/storage/bat/bat_storage.c
+++ b/sql/storage/bat/bat_storage.c
@@ -1088,6 +1088,37 @@ bind_updates(sql_trans *tr, sql_column *
        return upd;
 }
 
+static void*
+bind_updates_idx(sql_trans *tr, sql_idx *i) {
+       sql_updates* upd = GDKmalloc(sizeof(sql_updates));
+       if (!upd)
+               return NULL;
+
+       lock_column(tr->store, i->base.id);
+       size_t cnt = count_idx(tr, i, 0);
+       sql_delta *d = idx_timestamp_delta(tr, i);
+       int type = oid_index(i->type)?TYPE_oid:TYPE_lng;
+
+       if (!d) {
+               unlock_column(tr->store, i->base.id);
+               GDKfree(upd);
+               return NULL;
+       }
+
+       upd->ui = bind_ubat(tr, d, isTempTable(i->t), RD_UPD_ID, type, cnt);
+       upd->uv = bind_ubat(tr, d, isTempTable(i->t), RD_UPD_VAL, type, cnt);
+
+       unlock_column(tr->store, i->base.id);
+
+       if (upd->ui == NULL || upd->uv == NULL) {
+               bat_destroy(upd->ui);
+               bat_destroy(upd->uv);
+               GDKfree(upd);
+               return NULL;
+       }
+       return upd;
+}
+
 static void *                                  /* BAT * */
 bind_col(sql_trans *tr, sql_column *c, int access)
 {
@@ -4895,6 +4926,7 @@ bat_storage_init( store_functions *sf)
 {
        sf->bind_col = &bind_col;
        sf->bind_updates = &bind_updates;
+       sf->bind_updates_idx = &bind_updates_idx;
        sf->bind_idx = &bind_idx;
        sf->bind_cands = &bind_cands;
 
diff --git a/sql/storage/sql_storage.h b/sql/storage/sql_storage.h
--- a/sql/storage/sql_storage.h
+++ b/sql/storage/sql_storage.h
@@ -137,6 +137,7 @@ typedef struct table_functions {
 */
 typedef void *(*bind_col_fptr) (sql_trans *tr, sql_column *c, int access);
 typedef void *(*bind_updates_fptr) (sql_trans *tr, sql_column *c);
+typedef void *(*bind_updates_idx_fptr) (sql_trans *tr, sql_idx *c);
 typedef void *(*bind_idx_fptr) (sql_trans *tr, sql_idx *i, int access);
 typedef void *(*bind_cands_fptr) (sql_trans *tr, sql_table *t, int 
nr_of_parts, int part_nr);
 
@@ -222,6 +223,7 @@ typedef struct store_functions {
 
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to