static inline void instance__print_coords_to_log( fcs_dbm_solver_instance_t *const instance, FILE *const log_fh) { const fcs_dbm_variant_type_t local_variant = instance->local_variant; fprintf( log_fh, "At %ld iterations Coords=[", instance->count_num_processed); const pseduo_dfs_stack_item_t *stack_item = instance->stack; const pseduo_dfs_stack_item_t *const end_stack_item = stack_item + instance->stack_depth; for (; stack_item <= end_stack_item; stack_item++) { fprintf(log_fh, "%d,", stack_item->next_state_idx); } #if 1 { fcs_state_locs_struct_t locs; fc_solve_init_locs(&locs); char state_as_string[2000]; FCS__RENDER_STATE( state_as_string, &(end_stack_item->curr_state->s), &locs); printf("Found State=<<'STATE'\n%s\nSTATE\n\n", state_as_string); fflush(stdout); } #endif fprintf(log_fh, "]\n"); }
// The char * returned is malloc()ed and should be free()ed. DLLEXPORT char *fc_solve_user_INTERNAL_delta_states_enc_and_dec( const fcs_dbm_variant_type local_variant GCC_UNUSED, const char *const init_state_s, const char *const derived_state_s) { fcs_state_keyval_pair init_state, derived_state, new_derived_state; fcs_uchar enc_state[24]; fcs_bit_reader bit_r; fcs_state_locs_struct locs; fc_solve_init_locs(&locs); DECLARE_IND_BUF_T(indirect_stacks_buffer) DECLARE_IND_BUF_T(derived_stacks_buffer) DECLARE_IND_BUF_T(new_derived_indirect_stacks_buffer) fc_solve_initial_user_state_to_c(init_state_s, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer); fc_solve_initial_user_state_to_c(derived_state_s, &derived_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, derived_stacks_buffer); fcs_delta_stater delta; fc_solve_delta_stater_init(&delta, local_variant, &(init_state.s), STACKS_NUM, FREECELLS_NUM PASS_ON_NOT_FC_ONLY(FCS_SEQ_BUILT_BY_ALTERNATE_COLOR)); fc_solve_delta_stater_set_derived(&delta, &(derived_state.s)); fc_solve_state_init( &new_derived_state, STACKS_NUM, new_derived_indirect_stacks_buffer); fc_solve_bit_writer bit_w; fc_solve_bit_writer_init(&bit_w, enc_state); fc_solve_delta_stater_encode_composite(&delta, &bit_w); fc_solve_bit_reader_init(&bit_r, enc_state); fc_solve_delta_stater_decode(&delta, &bit_r, &(new_derived_state.s)); char *new_derived_as_str = SMALLOC(new_derived_as_str, 1000); FCS__RENDER_STATE(new_derived_as_str, &(new_derived_state.s), &locs); fc_solve_delta_stater_release(&delta); return new_derived_as_str; }
/* * The char * returned is malloc()ed and should be free()ed. */ DLLEXPORT int fc_solve_user_INTERNAL_perform_horne_prune( enum fcs_dbm_variant_type_t local_variant, const char * init_state_str_proto, char * * ret_state_s ) { fcs_state_keyval_pair_t init_state; fcs_state_locs_struct_t locs; int prune_ret; DECLARE_IND_BUF_T(indirect_stacks_buffer) fc_solve_init_locs(&locs); fc_solve_initial_user_state_to_c( init_state_str_proto, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer ); { fcs_which_moves_bitmask_t which_no_use = {{'\0'}}; prune_ret = horne_prune(local_variant, &init_state, &which_no_use, NULL, NULL); } *ret_state_s = fc_solve_state_as_string( &(init_state.s), &locs, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, 1, 0, 1 ); return prune_ret; }
/* * The char * returned is malloc()ed and should be free()ed. */ DLLEXPORT int fc_solve_user_INTERNAL_calc_derived_states_wrapper( enum fcs_dbm_variant_type_t local_variant, const char * init_state_str_proto, int * const num_out_derived_states, fcs_derived_state_debug_t * * out_derived_states, const fcs_bool_t perform_horne_prune ) { fcs_state_keyval_pair_t init_state; fc_solve_delta_stater_t * delta; fcs_encoded_state_buffer_t enc_state; fcs_state_locs_struct_t locs; fcs_derived_state_t * derived_list = NULL; fcs_derived_state_t * derived_list_recycle_bin = NULL; fcs_compact_allocator_t allocator; fcs_meta_compact_allocator_t meta_alloc; int states_count = 0; fcs_derived_state_t * iter; fcs_derived_state_debug_t * debug_ret; int idx = 0; DECLARE_IND_BUF_T(indirect_stacks_buffer) fc_solve_initial_user_state_to_c( init_state_str_proto, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer ); delta = fc_solve_delta_stater_alloc( &(init_state.s), STACKS_NUM, FREECELLS_NUM #ifndef FCS_FREECELL_ONLY , FCS_SEQ_BUILT_BY_ALTERNATE_COLOR #endif ); fcs_init_and_encode_state( delta, local_variant, &(init_state), &enc_state ); fc_solve_meta_compact_allocator_init (&meta_alloc); fc_solve_compact_allocator_init( &allocator, &meta_alloc); instance_solver_thread_calc_derived_states( local_variant, &init_state, NULL, &derived_list, &derived_list_recycle_bin, &allocator, perform_horne_prune ); iter = derived_list; while (iter) { states_count++; iter = iter->next; } *(num_out_derived_states) = states_count; debug_ret = SMALLOC(debug_ret, states_count); *(out_derived_states) = debug_ret; fc_solve_init_locs(&locs); iter = derived_list; while (iter) { debug_ret[idx].state_string = fc_solve_state_as_string( &(iter->state.s), &locs, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, 1, 0, 1 ); debug_ret[idx].move = iter->move; debug_ret[idx].core_irreversible_moves_count = iter->core_irreversible_moves_count; debug_ret[idx].num_non_reversible_moves_including_prune = iter->num_non_reversible_moves_including_prune; /* TODO : Put something meaningful there by passing it to the function. */ debug_ret[idx].which_irreversible_moves_bitmask = iter->which_irreversible_moves_bitmask; idx++; iter = iter->next; } assert(idx == states_count); fc_solve_compact_allocator_finish(&allocator); fc_solve_meta_compact_allocator_finish( &meta_alloc ); fc_solve_delta_stater_free (delta); return 0; }
/* * The char * returned is malloc()ed and should be free()ed. */ DLLEXPORT int fc_solve_user_INTERNAL_calc_derived_states_wrapper( fcs_dbm_variant_type_t local_variant, const char *init_state_str_proto, int *const num_out_derived_states, fcs_derived_state_debug_t **out_derived_states, const fcs_bool_t perform_horne_prune) { fcs_state_keyval_pair_t init_state; fcs_encoded_state_buffer_t enc_state; fcs_state_locs_struct_t locs; fcs_derived_state_t *derived_list = NULL; fcs_derived_state_t *derived_list_recycle_bin = NULL; fcs_compact_allocator_t allocator; fcs_meta_compact_allocator_t meta_alloc; size_t states_count = 0; fcs_derived_state_t *iter; DECLARE_IND_BUF_T(indirect_stacks_buffer) fc_solve_initial_user_state_to_c(init_state_str_proto, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer); fc_solve_delta_stater_t delta; fc_solve_delta_stater_init( &delta, &(init_state.s), STACKS_NUM, FREECELLS_NUM #ifndef FCS_FREECELL_ONLY , FCS_SEQ_BUILT_BY_ALTERNATE_COLOR #endif ); fcs_init_and_encode_state(&delta, local_variant, &(init_state), &enc_state); fc_solve_meta_compact_allocator_init(&meta_alloc); fc_solve_compact_allocator_init(&allocator, &meta_alloc); instance_solver_thread_calc_derived_states(local_variant, &init_state, NULL, &derived_list, &derived_list_recycle_bin, &allocator, perform_horne_prune); iter = derived_list; while (iter) { states_count++; iter = iter->next; } *(num_out_derived_states) = states_count; fcs_derived_state_debug_t *const debug_ret = SMALLOC(debug_ret, states_count); *(out_derived_states) = debug_ret; fc_solve_init_locs(&locs); iter = derived_list; size_t idx = 0; while (iter) { debug_ret[idx] = (typeof(debug_ret[idx])){ .state_string = SMALLOC(debug_ret[idx].state_string, 1000), .move = iter->move, .core_irreversible_moves_count = iter->core_irreversible_moves_count, .num_non_reversible_moves_including_prune = iter->num_non_reversible_moves_including_prune, .which_irreversible_moves_bitmask = iter->which_irreversible_moves_bitmask}; FCS__RENDER_STATE(debug_ret[idx].state_string, &(iter->state.s), &locs); /* TODO : Put something meaningful there by passing it to the function. */ idx++; iter = iter->next; } assert(idx == states_count); fc_solve_compact_allocator_finish(&allocator); fc_solve_meta_compact_allocator_finish(&meta_alloc); fc_solve_delta_stater_release(&delta); return 0; } /* * The char * returned is malloc()ed and should be free()ed. */ DLLEXPORT int fc_solve_user_INTERNAL_perform_horne_prune( fcs_dbm_variant_type_t local_variant, const char *init_state_str_proto, char **ret_state_s) { fcs_state_keyval_pair_t init_state; fcs_state_locs_struct_t locs; int prune_ret; DECLARE_IND_BUF_T(indirect_stacks_buffer) fc_solve_init_locs(&locs); fc_solve_initial_user_state_to_c(init_state_str_proto, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer); prune_ret = horne_prune__simple(local_variant, &init_state); *ret_state_s = SMALLOC(*ret_state_s, 1000); FCS__RENDER_STATE(*ret_state_s, &(init_state.s), &locs); return prune_ret; }
/* * The char * returned is malloc()ed and should be free()ed. */ DLLEXPORT int fc_solve_user_INTERNAL_find_fcc_start_points( enum fcs_dbm_variant_type_t local_variant, const char * init_state_str_proto, const int start_state_moves_count, const fcs_fcc_move_t * const start_state_moves, fcs_FCC_start_point_result_t * * out_fcc_start_points, long * out_num_new_positions ) { fcs_state_keyval_pair_t init_state; fc_solve_delta_stater_t * delta; fcs_encoded_state_buffer_t enc_state; fcs_state_locs_struct_t locs; int i; fcs_meta_compact_allocator_t meta_alloc; fcs_FCC_start_points_list_t start_points_list; dict_t * do_next_fcc_start_points_exist; dict_t * does_min_by_sorting_exist; fcs_lru_cache_t does_state_exist_in_any_FCC_cache; const int max_num_elements_in_cache = 1000; fcs_bool_t is_min_by_sorting_new; fcs_encoded_state_buffer_t min_by_sorting; fcs_fcc_moves_seq_allocator_t moves_list_allocator; fcs_fcc_moves_seq_t start_state_moves_seq; int states_count = 0; fcs_FCC_start_point_t * iter; fcs_FCC_start_point_result_t * ret; add_start_point_context_t add_start_point_context; void * tree_recycle_bin = NULL; fcs_compact_allocator_t moves_list_compact_alloc; DECLARE_IND_BUF_T(indirect_stacks_buffer) fc_solve_initial_user_state_to_c( init_state_str_proto, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer ); delta = fc_solve_delta_stater_alloc( &(init_state.s), STACKS_NUM, FREECELLS_NUM #ifndef FCS_FREECELL_ONLY , FCS_SEQ_BUILT_BY_ALTERNATE_COLOR #endif ); fcs_init_and_encode_state( delta, local_variant, &(init_state), &enc_state ); start_points_list.list = NULL; start_points_list.recycle_bin = NULL; fc_solve_meta_compact_allocator_init( &meta_alloc ); fc_solve_compact_allocator_init(&(start_points_list.allocator), &meta_alloc); do_next_fcc_start_points_exist = fc_solve_kaz_tree_create(fc_solve_compare_encoded_states, NULL, &meta_alloc, &tree_recycle_bin); does_min_by_sorting_exist = fc_solve_kaz_tree_create(fc_solve_compare_encoded_states, NULL, &meta_alloc, &tree_recycle_bin); cache_init(&does_state_exist_in_any_FCC_cache, max_num_elements_in_cache, &meta_alloc); fc_solve_compact_allocator_init(&(moves_list_compact_alloc), &(meta_alloc)); moves_list_allocator.recycle_bin = NULL; moves_list_allocator.allocator = &(moves_list_compact_alloc); start_state_moves_seq.count = start_state_moves_count; start_state_moves_seq.moves_list = NULL; { fcs_fcc_moves_list_item_t * * moves_iter = &(start_state_moves_seq.moves_list); for ( i=0 ; i < start_state_moves_count ; ) { if (i % FCS_FCC_NUM_MOVES_IN_ITEM == 0) { *(moves_iter) = fc_solve_fcc_alloc_moves_list_item(&moves_list_allocator); } (*moves_iter)->data.s[i % FCS_FCC_NUM_MOVES_IN_ITEM] = start_state_moves[i]; if ((++i) % FCS_FCC_NUM_MOVES_IN_ITEM == 0) { moves_iter = &((*moves_iter)->next); } } } add_start_point_context.do_next_fcc_start_points_exist = do_next_fcc_start_points_exist; add_start_point_context.next_start_points_list = &start_points_list; add_start_point_context.moves_list_allocator = &moves_list_allocator; perform_FCC_brfs( local_variant, &(init_state), enc_state, &start_state_moves_seq, fc_solve_add_start_point_in_mem, &add_start_point_context, &is_min_by_sorting_new, &min_by_sorting, does_min_by_sorting_exist, &does_state_exist_in_any_FCC_cache, out_num_new_positions, &moves_list_allocator, &meta_alloc ); iter = start_points_list.list; while (iter) { states_count++; iter = iter->next; } *out_fcc_start_points = ret = SMALLOC(ret, states_count+1); ret[states_count].count = 0; fc_solve_init_locs(&locs); iter = start_points_list.list; for (i = 0; i < states_count ; i++) { fcs_state_keyval_pair_t state; DECLARE_IND_BUF_T(state_indirect_stacks_buffer) ret[i].count = iter->moves_seq.count; ret[i].moves = SMALLOC(ret[i].moves, ret[i].count); { int moves_idx; fcs_fcc_moves_list_item_t * moves_iter = iter->moves_seq.moves_list; for (moves_idx = 0 ; moves_idx < ret[i].count ; ) { ret[i].moves[moves_idx] = moves_iter->data.s[moves_idx % FCS_FCC_NUM_MOVES_IN_ITEM]; if ((++moves_idx) % FCS_FCC_NUM_MOVES_IN_ITEM == 0) { moves_iter = moves_iter->next; } } } fc_solve_delta_stater_decode_into_state(delta, iter->enc_state.s, &(state), state_indirect_stacks_buffer); ret[i].state_as_string = fc_solve_state_as_string( &(state.s), &locs, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, 1, 0, 1 ); iter = iter->next; } fc_solve_compact_allocator_finish(&(start_points_list.allocator)); fc_solve_compact_allocator_finish(&(moves_list_compact_alloc)); fc_solve_delta_stater_free (delta); fc_solve_kaz_tree_destroy(do_next_fcc_start_points_exist); fc_solve_kaz_tree_destroy(does_min_by_sorting_exist); cache_destroy(&does_state_exist_in_any_FCC_cache); fc_solve_meta_compact_allocator_finish( &meta_alloc ); return 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); } } }
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; }