int ai_findandset_imatch(as_sindex_metadata *imd, as_sindex_pmetadata *pimd, int idx) { if (!Num_tbls) { return AS_SINDEX_ERR; } char *tname = NULL, *cname = NULL, *iname = NULL; int ret = AS_SINDEX_OK; if (!(tname = create_tname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } ret = AS_SINDEX_ERR; AI_GRLOCK(); int tmatch = find_table(tname); if (tmatch == -1) { goto END; } if (imd->iname) { if (!(iname = get_iname_from_imd(imd))) { ret = AS_SINDEX_ERR_NO_MEMORY; goto END; } char idx_str[NAME_STR_LEN]; snprintf(idx_str, sizeof(idx_str), "%d", idx); char *piname = str_concat(iname, '.', idx_str); pimd->imatch = match_partial_index_name(piname); cf_free(piname); } else { if (!(cname = create_cname_from_imd(imd))) { ret = AS_SINDEX_ERR_NO_MEMORY; goto END; } icol_t *ic = find_column(tmatch, cname); if (!ic) { goto END; } pimd->imatch = find_partial_index(tmatch, ic); } if (pimd->imatch == -1) { SITRACE(imd->si, META, debug, "Index%s: %s not found", imd->iname ? "" : "column-name", imd->iname ? iname : cname); goto END; } ret = AS_SINDEX_OK; END: AI_UNLOCK(); cf_free(tname); cf_free(iname); cf_free(cname); return ret; }
int ai_btree_destroy(as_sindex_metadata *imd) { char *tname, *cname, *iname; AI_GWLOCK(); for (int i = 0; i < imd->nprts; i++) { ai_cleanup(imd->pimd[i].ibtr); } if (!(tname = create_tname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } if (!(cname = create_cname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } if (0 > ai_drop_column(tname, cname)) { cf_warning(AS_SINDEX, "Failed to drop column %s from table %s", cname, tname); } cf_free(tname); cf_free(cname); if (!(iname = get_iname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } if (0 > ai_drop_index(iname)) { cf_warning(AS_SINDEX, "Failed to drop index %s", iname); } cf_free(iname); AI_UNLOCK(); return AS_SINDEX_OK; }
/* NOTE: The creation of a secondary index is the following two commands 0.) optional: CREATE TABLE namespace (pk U160, __dummy TEXT) 1.) ALTER TABLE namespace ADD COLUMN binname columntype 2.) CREATE [UNIQUE] INDEX indexname ON namespace (binname) */ int ai_btree_create(as_sindex_metadata *imd, int simatch, int *bimatch, int nprts) { char *iname = NULL, *cname = NULL, *tname = NULL; int ret = AS_SINDEX_ERR, rv; if (1 != imd->num_bins) { cf_warning(AS_SINDEX, "Multi-bin indexes not supported"); return ret; } if (!(tname = create_tname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } if (!(cname = create_cname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } AI_GWLOCK(); int tmatch = find_table(tname); if (tmatch == -1) { if (0 > (rv = ai_create_table(tname))) { cf_warning(AS_SINDEX, "Create table %s failed (rv %d)", tname, rv); goto END; } tmatch = find_table(tname); } r_tbl_t *rt = &Tbl[tmatch]; // 1.) add entries in Aerospike Index's virtual TABLE int col_type = imd->btype[0]; icol_t *ic = find_column(tmatch, cname); if (!ic) { // COLUMN does not exist if (0 > ai_add_column(tname, cname, col_type)) { goto END; } // Add (cmatch+1) always non-zero SITRACE(imd->si, META, debug, "Added Mapping [BINNAME=%s: BINID=%d: COLID%d] [IMATCH=%d: SIMATCH=%d: INAME=%s]", imd->bnames[0], imd->binid[0], rt->col_count, Num_indx - 1, simatch, imd->iname); } //NOTE: COMMAND: CREATE PARTITIONED INDEX iname ON tname (cname) NUM = nprts if (!(iname = get_iname_from_imd(imd))) { ret = AS_SINDEX_ERR_NO_MEMORY; goto END; } if (0 > (rv = ai_create_index(iname, tname, cname, col_type, nprts))) { cf_warning(AS_SINDEX, "Create index %s failed (rv %d)", iname, rv); goto END; } *bimatch = match_partial_index_name(iname); GTRACE(META, debug, "cr8SecIndex: iname: %s bname: %s type: %d ns: %s set: %s tmatch: %d bimatch: %d", imd->iname, imd->bnames[0], imd->btype[0], imd->ns_name, imd->set, tmatch, *bimatch); ret = AS_SINDEX_OK; END: AI_UNLOCK(); cf_free(tname); cf_free(cname); cf_free(iname); return ret; }
/* * Aerospike Index interface to build a defrag_list. * * Returns : * AS_SINDEX_DONE ---> The current pimd has been scanned completely for defragging * AS_SINDEX_CONTINUE ---> Current pimd sill may have some candidate digest to be defragged * AS_SINDEX_ERR ---> Error. Abort this pimd. * * Notes : Caller has the responsibility to free the iterators. * Requires a proper offset value from the caller. */ int ai_btree_build_defrag_list(as_sindex_metadata *imd, as_sindex_pmetadata *pimd, ai_obj *icol, long *nofst, long limit, uint64_t * tot_processed, uint64_t * tot_found, cf_ll *gc_list) { int ret = AS_SINDEX_ERR; if (!pimd || !imd) { return ret; } as_namespace *ns = imd->si->ns; if (!ns) { ns = as_namespace_get_byname((char *)imd->ns_name); } char *iname = get_iname_from_imd(imd); if (!iname) { ret = AS_SINDEX_ERR_NO_MEMORY; return ret; } if (!pimd || !pimd->ibtr || !pimd->ibtr->numkeys) { goto END; } //Entry is range query, FROM previous icol TO maxKey(ibtr) if (icol->empty) { assignMinKey(pimd->ibtr, icol); // init first call } ai_obj iH; assignMaxKey(pimd->ibtr, &iH); btEntry *be = NULL; btSIter *bi = btGetRangeIter(pimd->ibtr, icol, &iH, 1); if (!bi) { goto END; } while ( true ) { be = btRangeNext(bi, 1); if (!be) { ret = AS_SINDEX_DONE; break; } ai_obj *acol = be->key; ai_nbtr *anbtr = be->val; long processed = 0; if (!anbtr) { break; } if (anbtr->is_btree) { processed = build_defrag_list_from_nbtr(ns, acol, anbtr->u.nbtr, *nofst, &limit, tot_found, gc_list); } else { processed = build_defrag_list_from_arr(ns, acol, anbtr->u.arr, *nofst, &limit, tot_found, gc_list); } if (processed < 0) { // error .. abort everything. cf_detail(AS_SINDEX, "build_defrag_list returns an error. Aborting defrag on current pimd"); ret = AS_SINDEX_ERR; break; } *tot_processed += processed; // This tree may have some more digest to defrag if (limit == 0) { *nofst = *nofst + processed; ai_objClone(icol, acol); cf_detail(AS_SINDEX, "Current pimd may need more iteration of defragging."); ret = AS_SINDEX_CONTINUE; break; } // We have finished this tree. Yet we have not reached our limit to defrag. // Goes to next iteration *nofst = 0; ai_objClone(icol, acol); }; btReleaseRangeIterator(bi); END: cf_free(iname); return ret; }
int ai_findandset_imatch(as_sindex_metadata *imd, as_sindex_pmetadata *pimd, int idx) { if (!Num_tbls) { return AS_SINDEX_ERR; } char *tname = NULL; char *cname = NULL; char *iname = NULL; if (!(tname = create_tname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } int ret = AS_SINDEX_ERR; AI_GRLOCK(); int tmatch = find_table(tname); if (tmatch == -1) { goto END; } if (imd->iname) { // This is always true if (!(iname = get_iname_from_imd(imd))) { ret = AS_SINDEX_ERR_NO_MEMORY; goto END; } char piname[INDD_HASH_KEY_SIZE]; snprintf(piname, sizeof(piname), "%s.%d", iname, idx); pimd->imatch = match_partial_index_name(piname); } else { // CAUTION : This will not work. Since ci->list is only populated for 0th pimd if (!(cname = create_cname_from_imd(imd))) { ret = AS_SINDEX_ERR_NO_MEMORY; goto END; } icol_t *ic = find_column(tmatch, cname); if (!ic) { goto END; } pimd->imatch = find_partial_index(tmatch, ic); cf_free(ic); } if (pimd->imatch == -1) { cf_debug(AS_SINDEX, "Index %s not found for %dth pimd", imd->iname, idx); goto END; } ret = AS_SINDEX_OK; END: AI_UNLOCK(); if (tname) { cf_free(tname); } if (iname) { cf_free(iname); } if (cname) { cf_free(cname); } return ret; }
/* NOTE: The creation of a secondary index is the following two commands 0.) optional: CREATE TABLE namespace (pk U160, __dummy TEXT) 1.) ALTER TABLE namespace ADD COLUMN binname columntype 2.) CREATE [UNIQUE] INDEX indexname ON namespace (binname) */ int ai_btree_create(as_sindex_metadata *imd, int simatch, int *bimatch, int nprts) { char *iname = NULL, *cname = NULL, *tname = NULL; int ret = AS_SINDEX_ERR, rv; if (!(tname = create_tname_from_imd(imd))) { return AS_SINDEX_ERR_NO_MEMORY; } if (!(cname = create_cname_from_imd(imd))) { if (tname) { cf_free(tname); } return AS_SINDEX_ERR_NO_MEMORY; } AI_GWLOCK(); // TODO : ai_create_table has this check. So this is redundant // 3 shash_get can be reduced to 1 through ai_get_or_create_table func int tmatch = find_table(tname); if (tmatch == -1) { if (0 > (rv = ai_create_table(tname))) { cf_warning(AS_SINDEX, "Create table %s failed (rv %d)", tname, rv); goto END; } tmatch = find_table(tname); } r_tbl_t *rt = &Tbl[tmatch]; // 1.) add entries in Aerospike Index's virtual TABLE int col_type = imd->btype; icol_t *ic = find_column(tmatch, cname); if (!ic) { // COLUMN does not exist if (0 > ai_add_column(tname, cname, col_type)) { goto END; } // Add (cmatch+1) always non-zero cf_debug(AS_SINDEX, "Added Mapping [BINNAME=%s: BINID=%d: COLID%d] [IMATCH=%d: SIMATCH=%d: INAME=%s]", imd->bname, imd->binid, rt->col_count, Num_indx - 1, simatch, imd->iname); } else { cf_free(ic); } //NOTE: COMMAND: CREATE PARTITIONED INDEX iname ON tname (cname) NUM = nprts if (!(iname = get_iname_from_imd(imd))) { ret = AS_SINDEX_ERR_NO_MEMORY; goto END; } if (0 > (rv = ai_create_index(iname, tname, cname, col_type, nprts))) { cf_warning(AS_SINDEX, "Create index %s failed (rv %d)", iname, rv); goto END; } *bimatch = match_partial_index_name(iname); cf_debug(AS_SINDEX, "cr8SecIndex: iname: %s bname: %s type: %d ns: %s set: %s tmatch: %d bimatch: %d", imd->iname, imd->bname, imd->btype, imd->ns_name, imd->set, tmatch, *bimatch); ret = AS_SINDEX_OK; END: AI_UNLOCK(); if (tname) { cf_free(tname); } if (cname) { cf_free(cname); } if (iname) { cf_free(iname); } return ret; }