static int32_t S_find_upper_bound(RangeCompiler *self, SortCache *sort_cache) { RangeQuery *parent = (RangeQuery*)RangeCompiler_IVARS(self)->parent; Obj *upper_term = RangeQuery_IVARS(parent)->upper_term; int32_t retval = INT32_MAX; if (upper_term) { int32_t hi_ord = SortCache_Find(sort_cache, upper_term); if (hi_ord < 0) { // The supplied term is lower than all terms in the field. retval = -1; } else { Obj *hi_found = SortCache_Value(sort_cache, hi_ord); bool exact_match = hi_found == NULL ? false : Obj_Equals(upper_term, (Obj*)hi_found); retval = hi_ord; if (exact_match && !RangeQuery_IVARS(parent)->include_upper) { retval--; } DECREF(hi_found); } } return retval; }
static int32_t S_find_lower_bound(RangeCompiler *self, SortCache *sort_cache) { RangeQuery *parent = (RangeQuery*)RangeCompiler_IVARS(self)->parent; Obj *lower_term = RangeQuery_IVARS(parent)->lower_term; int32_t lower_bound = 0; if (lower_term) { int32_t low_ord = SortCache_Find(sort_cache, lower_term); if (low_ord < 0) { // The supplied term is lower than all terms in the field. lower_bound = 0; } else { Obj *low_found = SortCache_Value(sort_cache, low_ord); bool exact_match = low_found == NULL ? false : Obj_Equals(lower_term, low_found); lower_bound = low_ord; if (!exact_match || !RangeQuery_IVARS(parent)->include_lower) { lower_bound++; } DECREF(low_found); } } return lower_bound; }
uint32_t SortFieldWriter_Refill_IMP(SortFieldWriter *self) { SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self); if (!ivars->sort_cache) { return 0; } // Sanity check, then reset the buffer and prepare to start loading items. uint32_t buf_count = SortFieldWriter_Buffer_Count(self); if (buf_count) { THROW(ERR, "Refill called but buffer contains %u32 items", buf_count); } SortFieldWriter_Clear_Buffer(self); Counter_Reset(ivars->counter); S_lazy_init_sorted_ids(self); const int32_t null_ord = ivars->null_ord; I32Array *const doc_map = ivars->doc_map; SortCache *const sort_cache = ivars->sort_cache; uint32_t count = 0; while (ivars->run_tick <= ivars->run_max && Counter_Get_Value(ivars->counter) < ivars->mem_thresh ) { int32_t raw_doc_id = ivars->sorted_ids[ivars->run_tick]; int32_t ord = SortCache_Ordinal(sort_cache, raw_doc_id); if (ord != null_ord) { int32_t remapped = doc_map ? I32Arr_Get(doc_map, raw_doc_id) : raw_doc_id; if (remapped) { Obj *val = SortCache_Value(sort_cache, ord); SortFieldWriter_Add(self, remapped, val); count++; DECREF(val); } } ivars->run_tick++; } if (ivars->run_tick > ivars->run_max) { DECREF(ivars->sort_cache); ivars->sort_cache = NULL; FREEMEM(ivars->sorted_ids); ivars->sorted_ids = NULL; } return count; }
i32_t SortCache_find(SortCache *self, Obj *term) { FieldType *const type = self->type; i32_t lo = 0; i32_t hi = self->num_uniq - 1; i32_t result = -100; ZombieCharBuf value = ZCB_BLANK; if ( term != NULL && !OBJ_IS_A(term, CHARBUF)) { THROW("term is a %o, and not comparable to a %o", Obj_Get_Class_Name(term), CHARBUF.name); } /* Binary search. */ while (hi >= lo) { const i32_t mid = lo + ((hi - lo) / 2); ViewCharBuf *val = SortCache_Value(self, mid, (ViewCharBuf*)&value); i64_t comparison = FType_Compare_Values(type, term, (Obj*)val); if (comparison < 0) { hi = mid - 1; } else if (comparison > 0) { lo = mid + 1; } else { result = mid; break; } } if (hi < 0) { /* Target is "less than" the first cache entry. */ return -1; } else if (result == -100) { /* If result is still -100, it wasn't set. */ return hi; } else { return result; } }
int32_t SortCache_Find_IMP(SortCache *self, Obj *term) { SortCacheIVARS *const ivars = SortCache_IVARS(self); FieldType *const type = ivars->type; int32_t lo = 0; int32_t hi = ivars->cardinality - 1; int32_t result = -100; // Binary search. while (hi >= lo) { const int32_t mid = lo + ((hi - lo) / 2); Obj *val = SortCache_Value(self, mid); int32_t comparison = FType_null_back_compare_values(type, term, val); DECREF(val); if (comparison < 0) { hi = mid - 1; } else if (comparison > 0) { lo = mid + 1; } else { result = mid; break; } } if (hi < 0) { // Target is "less than" the first cache entry. return -1; } else if (result == -100) { // If result is still -100, it wasn't set. return hi; } else { return result; } }
void SortColl_collect(SortCollector *self, int32_t doc_id) { SortCollectorIVARS *const ivars = SortColl_IVARS(self); // Add to the total number of hits. ivars->total_hits++; // Collect this hit if it's competitive. if (SI_competitive(ivars, doc_id)) { MatchDoc *const match_doc = ivars->bumped; MatchDocIVARS *const match_doc_ivars = MatchDoc_IVARS(match_doc); match_doc_ivars->doc_id = doc_id + ivars->base; if (ivars->need_score && match_doc_ivars->score == F32_NEGINF) { match_doc_ivars->score = Matcher_Score(ivars->matcher); } // Fetch values so that cross-segment sorting can work. if (ivars->need_values) { VArray *values = match_doc_ivars->values; for (uint32_t i = 0, max = ivars->num_rules; i < max; i++) { SortCache *cache = ivars->sort_caches[i]; Obj *old_val = (Obj*)VA_Delete(values, i); if (cache) { int32_t ord = SortCache_Ordinal(cache, doc_id); Obj *blank = old_val ? old_val : SortCache_Make_Blank(cache); Obj *val = SortCache_Value(cache, ord, blank); if (val) { VA_Store(values, i, (Obj*)val); } else { DECREF(blank); } } } } // Insert the new MatchDoc. ivars->bumped = (MatchDoc*)HitQ_Jostle(ivars->hit_q, (Obj*)match_doc); if (ivars->bumped) { if (ivars->bumped == match_doc) { /* The queue is full, and we have established a threshold for * this segment as to what sort of document is definitely not * acceptable. Turn off AUTO_ACCEPT and start actually * testing whether hits are competitive. */ ivars->bubble_score = match_doc_ivars->score; ivars->bubble_doc = doc_id; ivars->actions = ivars->derived_actions; } // Recycle. MatchDoc_IVARS(ivars->bumped)->score = ivars->need_score ? F32_NEGINF : F32_NAN; } else { // The queue isn't full yet, so create a fresh MatchDoc. VArray *values = ivars->need_values ? VA_new(ivars->num_rules) : NULL; float fake_score = ivars->need_score ? F32_NEGINF : F32_NAN; ivars->bumped = MatchDoc_new(INT32_MAX, fake_score, values); DECREF(values); } } }