btSIter *btSetFullRangeIter(btSIter *iter, bt *btr, bool asc, cswc_t *w) { cswc_t W; // used in setHigh() if (!btr->root || !btr->numkeys) return NULL; if (!w) w = &W; ai_obj *aL = &w->wf.alow, *aH = &w->wf.ahigh; if (!assignMinKey(btr, aL) || !assignMaxKey(btr, aH)) return NULL; btk_t btk; bool med; uint32 ksize; SETITER8R(iter, btr, asc, iter_leaf, iter_leaf_rev, iter_node, iter_node_rev); siter->scan = 1; setHigh(siter, asc ? aH : aL, btr->s.ktype); char *bkey = createBTKey(asc ? aL : aH, &med, &ksize, btr, &btk); //DEST 030 if (!bkey) goto frangeiter_err; bt_n *x = NULL; int i = -1; uchar *stream = setIter(btr, bkey, siter, asc ? aL : aH, &x, &i, asc); destroyBTKey(bkey, med); /* DESTROYED 030 */ if (!stream && siter->missed) return siter;//IILMISS if (!streamToBTEntry(stream, siter, x, i)) goto frangeiter_err; if (btr->dirty_left) siter->missed = 1; // FULL means 100% FULL return siter; frangeiter_err: btReleaseRangeIterator(siter); return NULL; }
btSIter *btGetFullXthIter(bt *btr, long oofst, bool asc, cswc_t *w, long lim) { ulong ofst = (ulong)oofst; cswc_t W; // used in setHigh() if (!btr->root || !btr->numkeys) return NULL; if (!w) w = &W; ai_obj *aL = &w->wf.alow, *aH = &w->wf.ahigh; if (!assignMinKey(btr, aL) || !assignMaxKey(btr, aH)) return NULL; CR8ITER8R(btr, asc, iter_leaf, iter_leaf_rev, iter_node, iter_node_rev); setHigh(siter, asc ? aH : aL, btr->s.ktype); if (btScionFind(siter, btr->root, ofst, btr, asc, w, lim)) siter->empty = 0; return siter; }
/* * Return 0 in case of success * -1 in case of failure */ static int add_recs_from_nbtr(as_sindex_metadata *imd, ai_obj *ikey, bt *nbtr, as_sindex_qctx *qctx, bool fullrng) { int ret = 0; ai_obj sfk, efk; init_ai_obj(&sfk); init_ai_obj(&efk); btSIter *nbi; btEntry *nbe; btSIter stack_nbi; if (fullrng) { nbi = btSetFullRangeIter(&stack_nbi, nbtr, 1, NULL); } else { // search from LAST batches end-point init_ai_objFromDigest(&sfk, &qctx->bdig); assignMaxKey(nbtr, &efk); nbi = btSetRangeIter(&stack_nbi, nbtr, &sfk, &efk, 1); } if (nbi) { while ((nbe = btRangeNext(nbi, 1))) { ai_obj *akey = nbe->key; // FIRST can be REPEAT (last batch) if (!fullrng && ai_objEQ(&sfk, akey)) { continue; } if (btree_addsinglerec(imd, ikey, (cf_digest *)&akey->y, qctx->recl, &qctx->n_bdigs, qctx->can_partition_query, qctx->partitions_pre_reserved)) { ret = -1; break; } if (qctx->n_bdigs == qctx->bsize) { if (ikey) { ai_objClone(qctx->bkey, ikey); } cloneDigestFromai_obj(&qctx->bdig, akey); break; } } btReleaseRangeIterator(nbi); } else { cf_warning(AS_QUERY, "Could not find nbtr iterator.. skipping !!"); } 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; }