Example #1
0
void
SortColl_set_reader(SortCollector *self, SegReader *reader) {
    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
    SortReader *sort_reader
        = (SortReader*)SegReader_Fetch(reader, VTable_Get_Name(SORTREADER));

    // Reset threshold variables and trigger auto-action behavior.
    MatchDocIVARS *const bumped_ivars = MatchDoc_IVARS(ivars->bumped);
    bumped_ivars->doc_id = INT32_MAX;
    ivars->bubble_doc    = INT32_MAX;
    bumped_ivars->score  = ivars->need_score ? F32_NEGINF : F32_NAN;
    ivars->bubble_score  = ivars->need_score ? F32_NEGINF : F32_NAN;
    ivars->actions       = ivars->auto_actions;

    // Obtain sort caches. Derive actions array for this segment.
    if (ivars->need_values && sort_reader) {
        for (uint32_t i = 0, max = ivars->num_rules; i < max; i++) {
            SortRule  *rule  = (SortRule*)VA_Fetch(ivars->rules, i);
            CharBuf   *field = SortRule_Get_Field(rule);
            SortCache *cache = field
                               ? SortReader_Fetch_Sort_Cache(sort_reader, field)
                               : NULL;
            ivars->sort_caches[i] = cache;
            ivars->derived_actions[i] = S_derive_action(rule, cache);
            if (cache) { ivars->ord_arrays[i] = SortCache_Get_Ords(cache); }
            else       { ivars->ord_arrays[i] = NULL; }
        }
    }
    ivars->seg_doc_max = reader ? SegReader_Doc_Max(reader) : 0;
    Coll_set_reader((Collector*)self, reader);
}
Example #2
0
HitQueue*
HitQ_init(HitQueue *self, Schema *schema, SortSpec *sort_spec,
          uint32_t wanted) {
    HitQueueIVARS *const ivars = HitQ_IVARS(self);
    if (sort_spec) {
        VArray   *rules      = SortSpec_Get_Rules(sort_spec);
        uint32_t  num_rules  = VA_Get_Size(rules);
        uint32_t  action_num = 0;

        if (!schema) {
            THROW(ERR, "Can't supply sort_spec without schema");
        }

        ivars->need_values = false;
        ivars->num_actions = num_rules;
        ivars->actions     = (uint8_t*)MALLOCATE(num_rules * sizeof(uint8_t));
        ivars->field_types = (FieldType**)CALLOCATE(num_rules, sizeof(FieldType*));

        for (uint32_t i = 0; i < num_rules; i++) {
            SortRule *rule      = (SortRule*)VA_Fetch(rules, i);
            int32_t   rule_type = SortRule_Get_Type(rule);
            bool      reverse   = SortRule_Get_Reverse(rule);

            if (rule_type == SortRule_SCORE) {
                ivars->actions[action_num++] = reverse
                                              ? COMPARE_BY_SCORE_REV
                                              : COMPARE_BY_SCORE;
            }
            else if (rule_type == SortRule_DOC_ID) {
                ivars->actions[action_num++] = reverse
                                              ? COMPARE_BY_DOC_ID_REV
                                              : COMPARE_BY_DOC_ID;
            }
            else if (rule_type == SortRule_FIELD) {
                String    *field = SortRule_Get_Field(rule);
                FieldType *type  = Schema_Fetch_Type(schema, field);
                if (type) {
                    ivars->field_types[action_num] = (FieldType*)INCREF(type);
                    ivars->actions[action_num++] = reverse
                                                  ? COMPARE_BY_VALUE_REV
                                                  : COMPARE_BY_VALUE;
                    ivars->need_values = true;
                }
                else {
                    // Skip over fields we don't know how to sort on.
                    continue;
                }
            }
            else {
                THROW(ERR, "Unknown SortRule type: %i32", rule_type);
            }
        }
    }
    else {
        ivars->num_actions = 2;
        ivars->actions     = (uint8_t*)MALLOCATE(ivars->num_actions * sizeof(uint8_t));
        ivars->actions[0]  = COMPARE_BY_SCORE;
        ivars->actions[1]  = COMPARE_BY_DOC_ID;
    }

    return (HitQueue*)PriQ_init((PriorityQueue*)self, wanted);
}
Example #3
0
SortCollector*
SortColl_init(SortCollector *self, Schema *schema, SortSpec *sort_spec,
              uint32_t wanted) {
    VArray *rules = sort_spec
                    ? (VArray*)INCREF(SortSpec_Get_Rules(sort_spec))
                    : S_default_sort_rules();
    uint32_t num_rules = VA_Get_Size(rules);

    // Validate.
    if (sort_spec && !schema) {
        THROW(ERR, "Can't supply a SortSpec without a Schema.");
    }
    if (!num_rules) {
        THROW(ERR, "Can't supply a SortSpec with no SortRules.");
    }

    // Init.
    Coll_init((Collector*)self);
    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
    ivars->total_hits    = 0;
    ivars->bubble_doc    = INT32_MAX;
    ivars->bubble_score  = F32_NEGINF;
    ivars->seg_doc_max   = 0;

    // Assign.
    ivars->wanted        = wanted;

    // Derive.
    ivars->hit_q         = HitQ_new(schema, sort_spec, wanted);
    ivars->rules         = rules; // absorb refcount.
    ivars->num_rules     = num_rules;
    ivars->sort_caches   = (SortCache**)CALLOCATE(num_rules, sizeof(SortCache*));
    ivars->ord_arrays    = (void**)CALLOCATE(num_rules, sizeof(void*));
    ivars->actions       = (uint8_t*)CALLOCATE(num_rules, sizeof(uint8_t));

    // Build up an array of "actions" which we will execute during each call
    // to Collect(). Determine whether we need to track scores and field
    // values.
    ivars->need_score  = false;
    ivars->need_values = false;
    for (uint32_t i = 0; i < num_rules; i++) {
        SortRule *rule   = (SortRule*)VA_Fetch(rules, i);
        int32_t rule_type  = SortRule_Get_Type(rule);
        ivars->actions[i] = S_derive_action(rule, NULL);
        if (rule_type == SortRule_SCORE) {
            ivars->need_score = true;
        }
        else if (rule_type == SortRule_FIELD) {
            CharBuf *field = SortRule_Get_Field(rule);
            FieldType *type = Schema_Fetch_Type(schema, field);
            if (!type || !FType_Sortable(type)) {
                THROW(ERR, "'%o' isn't a sortable field", field);
            }
            ivars->need_values = true;
        }
    }

    // Perform an optimization.  So long as we always collect docs in
    // ascending order, Collect() will favor lower doc numbers -- so we may
    // not need to execute a final COMPARE_BY_DOC_ID action.
    ivars->num_actions = num_rules;
    if (ivars->actions[num_rules - 1] == COMPARE_BY_DOC_ID) {
        ivars->num_actions--;
    }

    // Override our derived actions with an action which will be excecuted
    // autmatically until the queue fills up.
    ivars->auto_actions    = (uint8_t*)MALLOCATE(1);
    ivars->auto_actions[0] = wanted ? AUTO_ACCEPT : AUTO_REJECT;
    ivars->derived_actions = ivars->actions;
    ivars->actions         = ivars->auto_actions;


    // Prepare a MatchDoc-in-waiting.
    VArray *values = ivars->need_values ? VA_new(num_rules) : NULL;
    float   score  = ivars->need_score  ? F32_NEGINF : F32_NAN;
    ivars->bumped = MatchDoc_new(INT32_MAX, score, values);
    DECREF(values);

    return self;
}