示例#1
0
extern void fc_solve_dbm_store_offload_pre_cache(
    fcs_dbm_store store, fcs_pre_cache *const pre_cache)
{
    fcs_dbm *const db = (fcs_dbm *)store;
    dict_t *const kaz_tree = pre_cache->kaz_tree;
    DB *const dbp = db->dbp;

    for (dnode_t *node = fc_solve_kaz_tree_first(kaz_tree); node;
         node = fc_solve_kaz_tree_next(kaz_tree, node))
    {
        const_AUTO(kv, (pre_cache_key_val_pair *)(node->dict_key));

        db->key.data = kv->key.s + 1;
        db->key.size = kv->key.s[0];
        db->data.data = kv->parent.s + 1;
        db->data.size = kv->parent.s[0];
        int ret;
        if ((ret = dbp->put(dbp, NULL, &(db->key), &(db->data), 0)) != 0)
        {
            dbp->err(dbp, ret, "DB->put");
            my_close(dbp, ret);
        }
    }
}
示例#2
0
static inline void instance_check_key(fcs_dbm_solver_thread_t *const thread,
    fcs_dbm_solver_instance_t *const instance, const int key_depth,
    fcs_encoded_state_buffer_t *const key, fcs_dbm_record_t *const parent,
    const unsigned char move GCC_UNUSED,
    const fcs_which_moves_bitmask_t *const which_irreversible_moves_bitmask
#ifdef FCS_DBM_CACHE_ONLY
    ,
    const fcs_fcc_move_t *moves_to_parent
#endif
    )
{
#ifdef DEBUG_OUT
    fcs_state_locs_struct_t locs;
    fc_solve_init_locs(&locs);
    const_AUTO(local_variant, instance->common.variant);
#endif
    const_AUTO(coll, &(instance->coll));
    {
#ifdef FCS_DBM_WITHOUT_CACHES
        fcs_dbm_record_t *token;
#else
        fcs_dbm_record_t *token = key;
#endif
#ifndef FCS_DBM_WITHOUT_CACHES
        if (cache_does_key_exist(&(coll->cache_store.cache), key))
        {
            return;
        }
#ifndef FCS_DBM_CACHE_ONLY
        else if (pre_cache_does_key_exist(&(coll->cache_store.pre_cache), key))
        {
            return;
        }
#endif
#ifndef FCS_DBM_CACHE_ONLY
        else if (fc_solve_dbm_store_does_key_exist(
                     coll->cache_store.store, key->s))
        {
            cache_insert(&(coll->cache_store.cache), key, NULL, '\0');
            return;
        }
#endif
        else
#else
        if ((token = fc_solve_dbm_store_insert_key_value(
                 coll->cache_store.store, key, parent, TRUE)))
#endif
        {
#ifdef FCS_DBM_CACHE_ONLY
            fcs_cache_key_info_t *cache_key;
#endif

#ifndef FCS_DBM_WITHOUT_CACHES
#ifndef FCS_DBM_CACHE_ONLY
            pre_cache_insert(&(coll->cache_store.pre_cache), key, parent);
#else
            cache_key = cache_insert(
                &(coll->cache_store.cache), key, moves_to_parent, move);
#endif
#endif

            if (key_depth == instance->curr_depth)
            {
                /* Now insert it into the queue. */
                fcs_lock_lock(&instance->global_lock);

                fcs_depth_multi_queue__insert(
                    &(coll->depth_queue), thread->state_depth + 1,
#ifdef FCS_DBM_WITHOUT_CACHES
                    (const fcs_offloading_queue_item_t *)(&token)
#else
                    key
#endif
                        );

                instance->common.count_of_items_in_queue++;
                instance->common.num_states_in_collection++;

                instance_debug_out_state(instance, &(token->key));

                fcs_lock_unlock(&instance->global_lock);
            }
            else
            {
                /* Handle an irreversible move */

                /* Calculate the new fingerprint to which the exit
                 * point belongs. */
                fcs_which_moves_bitmask_t new_fingerprint = {{'\0'}};
                for (size_t i = 0; i < COUNT(new_fingerprint.s); i++)
                {
                    new_fingerprint.s[i] =
                        which_irreversible_moves_bitmask->s[i] +
                        instance->fingerprint_which_irreversible_moves_bitmask
                            .s[i];
                }
                int trace_num;
                fcs_encoded_state_buffer_t *trace;
                fcs_lock_lock(&instance->fcc_exit_points_output_lock);
                /* instance->storage_lock is already locked
                 * in instance_check_multiple_keys and we should not
                 * lock it here. */
                calc_trace(token, &trace, &trace_num);
                {
                    FccEntryPointNode fcc_entry_key;
                    fcc_entry_key.kv.key.key = trace[trace_num - 1];
                    FccEntryPointNode *val_proto = RB_FIND(FccEntryPointList,
                        &(instance->fcc_entry_points), &fcc_entry_key);
                    const long location_in_file =
                        val_proto->kv.val.location_in_file;
                    fseek(instance->fingerprint_fh, location_in_file, SEEK_SET);

#ifdef HAVE_GETLINE
                    getline(&(instance->fingerprint_line),
                        &(instance->fingerprint_line_size),
                        instance->fingerprint_fh);
#else
                    fgets(instance->fingerprint_line,
                        instance->fingerprint_line_size,
                        instance->fingerprint_fh);
#endif
                    char *const moves_to_state_enc =
                        strchr(
                            strchr(instance->fingerprint_line, ' ') + 1, ' ') +
                        1;
                    char *const trailing_newline =
                        strchr(moves_to_state_enc, '\n');
                    if (trailing_newline)
                    {
                        *trailing_newline = '\0';
                    }
                    const size_t string_len = strlen(moves_to_state_enc);
                    instance_alloc_num_moves(
                        instance, ((string_len * 3) >> 2) + 20);
                    base64_decode(moves_to_state_enc, string_len,
                        ((unsigned char *)instance->moves_to_state),
                        &(instance->moves_to_state_len));
                }

                const_SLOT(moves_to_state_len, instance);
                const size_t added_moves_to_output =
                    moves_to_state_len + trace_num - 1;
                instance_alloc_num_moves(instance, added_moves_to_output);
                unsigned char *const moves_to_state = instance->moves_to_state;
                for (int i = trace_num - 1; i > 0; i--)
                {
                    moves_to_state[moves_to_state_len + trace_num - 1 - i] =
                        get_move_from_parent_to_child(instance,
                            &(thread->delta_stater), trace[i], trace[i - 1]);
                }

                const size_t new_max_enc_len =
                    ((added_moves_to_output * 4) / 3) + 20;

                if (new_max_enc_len >
                    instance->moves_base64_encoding_buffer_max_len)
                {
                    instance->moves_base64_encoding_buffer =
                        SREALLOC(instance->moves_base64_encoding_buffer,
                            new_max_enc_len);
                    instance->moves_base64_encoding_buffer_max_len =
                        new_max_enc_len;
                }

                size_t unused_output_len;
                base64_encode(moves_to_state, added_moves_to_output,
                    instance->moves_base64_encoding_buffer, &unused_output_len);
                char fingerprint_base64[100];
                char state_base64[100];
                base64_encode(new_fingerprint.s, sizeof(new_fingerprint),
                    fingerprint_base64, &unused_output_len);
                base64_encode((unsigned char *)&(*key), sizeof(*key),
                    state_base64, &unused_output_len);
                /* Output the exit point. */
                fprintf(instance->fcc_exit_points_out_fh, "%s %s %zd %s\n",
                    fingerprint_base64, state_base64, added_moves_to_output,
                    instance->moves_base64_encoding_buffer);
#ifdef DEBUG_OUT
                {
                    fcs_state_keyval_pair_t state;
                    DECLARE_IND_BUF_T(indirect_stacks_buffer)
                    fc_solve_delta_stater_decode_into_state(
                        &(thread->delta_stater), key->s, &state,
                        indirect_stacks_buffer);
                    char state_str[2000];
                    FCS__RENDER_STATE(state_str, &(state.s), &locs);
                    fprintf(stderr,
                        "Check Key: <<<\n%s\n>>>\n\n[%s %s %ld %s]\n\n",
                        state_str, fingerprint_base64, state_base64,
                        added_moves_to_output,
                        instance->moves_base64_encoding_buffer);
                }
#endif
                fflush(instance->fcc_exit_points_out_fh);

                fcs_lock_unlock(&instance->fcc_exit_points_output_lock);

                free(trace);
            }
        }
    }
示例#3
0
static void *instance_run_solver_thread(void *const void_arg)
{
    fcs_dbm_queue_item_t physical_item;
    fcs_dbm_record_t *token = NULL;
    fcs_dbm_queue_item_t *item, *prev_item;
    fcs_derived_state_t *derived_list, *derived_list_recycle_bin, *derived_iter;
    fcs_compact_allocator_t derived_list_allocator;
    fcs_state_keyval_pair_t state;
    char *base64_encoding_buffer = NULL;
#if 0
    size_t base64_encoding_buffer_max_len = 0;
#endif

#ifdef DEBUG_OUT
    fcs_state_locs_struct_t locs;
    fc_solve_init_locs(&locs);
#endif
    DECLARE_IND_BUF_T(indirect_stacks_buffer)

    const_AUTO(thread, ((thread_arg_t *)void_arg)->thread);
    const_SLOT(instance, thread);
    const_AUTO(delta_stater, &(thread->delta_stater));
    const_AUTO(local_variant, instance->common.variant);

    prev_item = item = NULL;
    int queue_num_extracted_and_processed = 0;
    fc_solve_compact_allocator_init(
        &(derived_list_allocator), &(thread->thread_meta_alloc));
    derived_list_recycle_bin = NULL;
    derived_list = NULL;
    FILE *const out_fh = instance->common.out_fh;
    TRACE("%s\n", "instance_run_solver_thread start");
    const_AUTO(coll, &(instance->coll));
#if 0
    fcs_bool_t was_start_key_reachable = instance->was_start_key_reachable;
#endif
    while (1)
    {
        /* First of all extract an item. */
        fcs_lock_lock(&instance->global_lock);

        if (prev_item)
        {
            instance->common.queue_num_extracted_and_processed--;
        }

        if (instance->common.should_terminate == DONT_TERMINATE)
        {
            if (fcs_depth_multi_queue__extract(&(coll->depth_queue),
                    &(thread->state_depth),
                    (fcs_offloading_queue_item_t *)(&token)))
            {
                physical_item.key = token->key;
                item = &physical_item;
                instance_increment(instance);
            }
            else
            {
                item = NULL;
            }

            queue_num_extracted_and_processed =
                instance->common.queue_num_extracted_and_processed;
        }
        fcs_lock_unlock(&instance->global_lock);

        if ((instance->common.should_terminate != DONT_TERMINATE) ||
            (!queue_num_extracted_and_processed))
        {
            break;
        }

        if (!item)
        {
            /* Sleep until more items become available in the
             * queue. */
            usleep(5000);
        }
        else
        {
            /* Handle item. */
            fc_solve_delta_stater_decode_into_state(
                delta_stater, item->key.s, &state, indirect_stacks_buffer);

            /* A section for debugging. */
            FCS__OUTPUT_STATE(out_fh, "", &(state.s), &locs);
#if 0
        {
            FccEntryPointNode key;
            key.kv.key.key = item->key;
            fcs_lock_lock(&instance->fcc_entry_points_lock);
            FccEntryPointNode * val_proto = RB_FIND(
                FccEntryPointList,
                &(instance->fcc_entry_points),
                &(key)
            );

            fcs_bool_t to_prune = FALSE;
            fcs_bool_t to_output = FALSE;
            if (val_proto)
            {
                val_proto->kv.val.is_reachable = TRUE;
                const int moves_count = instance->start_key_moves_count
                    + item->moves_seq.count;

                if (was_start_key_reachable)
                {
                    if (val_proto->kv.val.depth <= moves_count)
                    {
                        /* We can prune based on here. */
                        to_prune = TRUE;
                    }
                    else
                    {
                        /* We can set it to the more pessimstic move count
                         * for future trimming. */
                        to_output = !(val_proto->kv.val.was_consumed);
                        val_proto->kv.val.depth = moves_count;
                        val_proto->kv.val.was_consumed = TRUE;
                    }
                }
                else
                {
                    if (! val_proto->kv.val.was_consumed)
                    {
                        to_output = TRUE;
                        if (val_proto->kv.val.depth >= moves_count)
                        {
                            val_proto->kv.val.depth = moves_count;
                            val_proto->kv.val.was_consumed = TRUE;
                        }
                    }
                }
            }
            fcs_lock_unlock(&instance->fcc_entry_points_lock);

            if (to_output)
            {
                const size_t needed_len = ( (sizeof(key.kv.key.key)+2) << 2 ) / 3 + 20;
                if (base64_encoding_buffer_max_len < needed_len)
                {
                    base64_encoding_buffer = SREALLOC(base64_encoding_buffer, needed_len);
                    base64_encoding_buffer_max_len = needed_len;
                }

                size_t unused_output_len;

                base64_encode(
                    (unsigned char *)&(key.kv.key.key),
                    sizeof(key.kv.key.key),
                    base64_encoding_buffer,
                    &unused_output_len
                );

                fcs_lock_lock(&instance->output_lock);
                fprintf(
                    instance->consumed_states_fh,
                    "%s\n", base64_encoding_buffer
                );
                fflush(instance->consumed_states_fh);
                fcs_lock_unlock(&instance->output_lock);
            }

            if (to_prune)
            {
                continue;
            }
        }
#endif

            if (instance_solver_thread_calc_derived_states(local_variant,
                    &state, token, &derived_list, &derived_list_recycle_bin,
                    &derived_list_allocator, TRUE))
            {
                fcs_lock_lock(&instance->global_lock);
                fcs_dbm__found_solution(&(instance->common), token, item);
                fcs_lock_unlock(&instance->global_lock);
                break;
            }

            /* Encode all the states. */
            for (derived_iter = derived_list; derived_iter;
                 derived_iter = derived_iter->next)
            {
                fcs_init_and_encode_state(delta_stater, local_variant,
                    &(derived_iter->state), &(derived_iter->key));
            }

            instance_check_multiple_keys(thread, instance, &(coll->cache_store),
                &(coll->queue_meta_alloc), &derived_list, 1
#ifdef FCS_DBM_CACHE_ONLY
                ,
                item->moves_to_key
#endif
                );

            /* Now recycle the derived_list */
            while (derived_list)
            {
#define derived_list_next derived_iter
                derived_list_next = derived_list->next;
                derived_list->next = derived_list_recycle_bin;
                derived_list_recycle_bin = derived_list;
                derived_list = derived_list_next;
#undef derived_list_next
            }
            /* End handle item. */
        }
        /* End of main thread loop */
        prev_item = item;
    }

    free(base64_encoding_buffer);

    fc_solve_compact_allocator_finish(&(derived_list_allocator));

    TRACE("%s\n", "instance_run_solver_thread end");

    return NULL;
}