query(" UPDATE ". BB_SEARCH_REBUILD ." SET rebuild_session_status = ". REBUILD_SEARCH_ABORTED ." WHERE rebuild_session_id = $last_session_id "); } bb_die(sprintf($lang['REBUILD_SEARCH_ABORTED'], $last_session_data['end_post_id']) .'

'. sprintf($lang['CLICK_RETURN_REBUILD_SEARCH'], '', '')); } // from which post to start processing $start = abs(intval(@$_REQUEST['start'])); // get the total number of posts in the db $total_posts = get_total_posts(); // clear the search tables and clear mode (delete or truncate) $clear_search = isset($_REQUEST['clear_search']) ? (int) $_REQUEST['clear_search'] : 0; // get the number of total/session posts already processed $total_posts_processed = ( $start != 0 ) ? get_total_posts('before', $last_session_data['end_post_id']) : 0; $session_posts_processed = ( $mode == 'refresh' ) ? get_processed_posts('session') : 0; // find how many posts aren't processed $total_posts_processing = $total_posts - $total_posts_processed; // how many posts to process in this session if ($session_posts_processing = @intval($_REQUEST['session_posts_processing'])) { if ($mode == 'submit') { // check if we passed over total_posts just after submitting if ($session_posts_processing + $total_posts_processed > $total_posts) { $session_posts_processing = $total_posts - $total_posts_processed; } } // correct it when posts are deleted during processing $session_posts_processing = ($session_posts_processing > $total_posts) ? $total_posts : $session_posts_processing; } else { // if we have finished, get all the posts, else only the remaining $session_posts_processing = (!$total_posts_processing) ? $total_posts : $total_posts_processing; } // how many posts to process per cycle $post_limit = isset($_REQUEST['post_limit']) ? (int) $_REQUEST['post_limit'] : $def_post_limit; // correct the post_limit when we pass over it if ( $session_posts_processed + $post_limit > $session_posts_processing ) { $post_limit = $session_posts_processing - $session_posts_processed; } // how much time to wait per cycle if (isset($_REQUEST['time_limit'])) { $time_limit = (int) $_REQUEST['time_limit']; } else { $time_limit = $def_time_limit; $time_limit_explain = $lang['TIME_LIMIT_EXPLAIN']; // check for safe mode timeout if ( ini_get('safe_mode') ) { // get execution time $max_execution_time = ini_get('max_execution_time'); $time_limit_explain .= '
' . sprintf($lang['TIME_LIMIT_EXPLAIN_SAFE'], $max_execution_time); if ( $time_limit > $max_execution_time ) { $time_limit = $max_execution_time; } } // check for webserver timeout (IE returns null) if ( isset($_SERVER["HTTP_KEEP_ALIVE"]) ) { // get webserver timeout $webserver_timeout = intval($_SERVER["HTTP_KEEP_ALIVE"]); $time_limit_explain .= '
' . sprintf($lang['TIME_LIMIT_EXPLAIN_WEBSERVER'], $webserver_timeout); if ( $time_limit > $webserver_timeout ) { $time_limit = $webserver_timeout; } } } // how much time to wait between page refreshes $refresh_rate = isset($_REQUEST['refresh_rate']) ? (int) $_REQUEST['refresh_rate'] : $def_refresh_rate; // check if the user gave wrong input if ($mode == 'submit') { if (($session_posts_processing || $post_limit || $refresh_rate || $time_limit) <= 0) { bb_die($lang['WRONG_INPUT'] .'

'. sprintf($lang['CLICK_RETURN_REBUILD_SEARCH'], '', '')); } } // Increase maximum execution time in case of a lot of posts, but don't complain about it if it isn't allowed. @set_time_limit($time_limit + 20); // check if we are should start processing if ($mode == 'submit' || $mode == 'refresh') { // check if we are in the beginning of processing if ($start == 0) { $last_session_data = get_empty_last_session_data(); clear_search_tables($clear_search); } // get the db sizes list($search_data_size, $search_index_size, $search_tables_size) = get_db_sizes(); // get the post subject/text of each post $result = DB()->query(" SELECT pt.post_id, pt.post_text, IF(p.post_id = t.topic_first_post_id, t.topic_title, '') AS post_subject FROM ". BB_POSTS_TEXT ." pt, ". BB_POSTS ." p, ". BB_TOPICS ." t WHERE p.post_id = pt.post_id AND t.topic_id = p.topic_id AND p.poster_id NOT IN(". BOT_UID .") AND pt.post_id >= $start ORDER BY pt.post_id ASC LIMIT $post_limit "); $expire_time = $start_time + $time_limit - 5; $start_post_id = $end_post_id = $num_rows = 0; $timer_expired = false; $words_sql = array(); while ($row = DB()->fetch_next($result) AND !$timer_expired) { @set_time_limit(600); $start_post_id = ($num_rows == 0) ? $row['post_id'] : $start_post_id; $end_post_id = $row['post_id']; // Get search words $s_post_text = str_replace('\n', "\n", $row['post_text']); $s_post_subject = str_replace('\n', "\n", $row['post_subject']); $words_sql[] = array( 'post_id' => (int) $row['post_id'], 'search_words' => add_search_words($row['post_id'], stripslashes($s_post_text), stripslashes($s_post_subject), true), ); $timer_expired = (TIMENOW > $expire_time); $num_rows++; } // Store search words if ($words_sql) { DB()->query("REPLACE INTO ". BB_POSTS_SEARCH . DB()->build_array('MULTI_INSERT', $words_sql)); } // find how much time the last cycle took $last_cycle_time = intval(TIMENOW - $start_time); // check if we had any data if ($num_rows != 0) { if ($mode == 'submit') { // insert a new session entry $args = DB()->build_array('INSERT', array( 'end_post_id' => (int) $end_post_id, 'end_time' => (int) TIMENOW, 'last_cycle_time' => (int) $last_cycle_time, 'session_time' => (int) $last_cycle_time, 'session_posts' => (int) $num_rows, 'session_cycles' => (int) 1, 'start_post_id' => (int) $start_post_id, 'start_time' => (int) $start_time, 'search_size' => (int) $search_tables_size, 'rebuild_session_status' => REBUILD_SEARCH_PROCESSED, )); DB()->query("REPLACE INTO ". BB_SEARCH_REBUILD . $args); } else // refresh { // update the last session entry DB()->query(" UPDATE ". BB_SEARCH_REBUILD ." SET end_post_id = $end_post_id, end_time = ". TIMENOW .", last_cycle_time = $last_cycle_time, session_time = session_time + $last_cycle_time, session_posts = session_posts + $num_rows, session_cycles = session_cycles + 1, rebuild_session_status = ". REBUILD_SEARCH_PROCESSED ." WHERE rebuild_session_id = $last_session_id "); } } $last_session_data = get_rebuild_session_details('last', 'all'); $template->assign_vars(array('TPL_REBUILD_SEARCH_PROGRESS' => true)); $processing_messages = ''; $processing_messages .= ($timer_expired) ? sprintf($lang['TIMER_EXPIRED'], TIMENOW - $start_time) : ''; $processing_messages .= ($start == 0 && $clear_search) ? $lang['CLEARED_SEARCH_TABLES'] : ''; // check if we have reached the end of our post processing $session_posts_processed = get_processed_posts('session'); $total_posts_processed = get_total_posts('before', $last_session_data['end_post_id']); $total_posts = get_total_posts(); if ( $session_posts_processed < $session_posts_processing && $total_posts_processed < $total_posts ) { $form_parameters = '&start='.($end_post_id+1); $form_parameters .= '&session_posts_processing='.$session_posts_processing; $form_parameters .= '&post_limit='.$post_limit; $form_parameters .= '&time_limit='.$time_limit; $form_parameters .= '&refresh_rate='.$refresh_rate; $form_action = 'admin_rebuild_search.php'.'?mode=refresh'.$form_parameters; $next_button = $lang['NEXT']; $progress_bar_img = $images['progress_bar']; $processing_messages .= sprintf($lang['PROCESSING_NEXT_POSTS'], $post_limit); meta_refresh($form_action, $refresh_rate); // create the meta tag for refresh $template->assign_vars(array( 'CANCEL_BUTTON' => true, )); } else // end of processing { $form_action = "admin_rebuild_search.php"; $next_button = $lang['FINISHED']; $progress_bar_img = $images['progress_bar_full']; $processing_messages .= ( $session_posts_processed < $session_posts_processing ) ? sprintf($lang['DELETED_POSTS'], $session_posts_processing - $session_posts_processed) : ''; $processing_messages .= ( $total_posts_processed == $total_posts ) ? $lang['ALL_POSTS_PROCESSED'] : $lang['ALL_SESSION_POSTS_PROCESSED']; // if we have processed all the db posts we need to update the rebuild_status DB()->query("UPDATE ". BB_SEARCH_REBUILD ." SET rebuild_session_status = ". REBUILD_SEARCH_COMPLETED ." WHERE rebuild_session_id = $last_session_id AND end_post_id = $max_post_id "); // optimize all search tables when finished $table_ary = array(BB_POSTS_SEARCH); foreach ($table_ary as $table) { DB()->query("ANALYZE TABLE $table"); DB()->query("OPTIMIZE TABLE $table"); } $processing_messages .= '
' . $lang['ALL_TABLES_OPTIMIZED']; } // calculate the percent if ($session_posts_processing > 0) { $session_percent = ($session_posts_processed / $session_posts_processing) * 100; } else { $session_percent = 100; } if ($total_posts > 0) { $total_percent = ($total_posts_processed / $total_posts) * 100; } else { $total_percent = 100; } // get the db sizes list($search_data_size, $search_index_size, $search_tables_size) = get_db_sizes(); // calculate the final (estimated) values $final_search_tables_size = ''; if ($search_tables_size) { $start_search_tables_size = $last_session_data['search_size']; $final_search_tables_size = $start_search_tables_size + round(($search_tables_size - $start_search_tables_size) * (100 / $session_percent)); } // calculate various times $session_time = $last_session_data['session_time']; if ($last_session_data['session_cycles'] > 0) { $session_average_cycle_time = round($session_time / $last_session_data['session_cycles']); } else { $session_average_cycle_time = 0; } $session_estimated_time = round($session_time * (100 / $session_percent)) - $session_time; // create the percent boxes create_percent_box('session', create_percent_color($session_percent), $session_percent); create_percent_box('total', create_percent_color($total_percent), $total_percent); $template->assign_vars(array( 'L_NEXT' => $next_button, 'L_TIME_LAST_POSTS_ADMIN' => sprintf($lang['TIME_LAST_POSTS'], $num_rows), 'PROCESSING_POSTS' => sprintf($lang['PROCESSED_POST_IDS'], $start_post_id, $end_post_id), 'PROCESSING_MESSAGES' => $processing_messages, 'PROGRESS_BAR_IMG' => $progress_bar_img, 'SESSION_DETAILS' => sprintf($lang['PROCESS_DETAILS'], $session_posts_processed - $num_rows + 1, $session_posts_processed, $session_posts_processing), 'SESSION_PERCENT' => sprintf($lang['PERCENT_COMPLETED'], round($session_percent, 2)), 'TOTAL_DETAILS' => sprintf($lang['PROCESS_DETAILS'], $total_posts_processed - $num_rows + 1, $total_posts_processed, $total_posts), 'TOTAL_PERCENT' => sprintf($lang['PERCENT_COMPLETED'], round($total_percent, 2)), 'LAST_CYCLE_TIME' => delta_time(TIMENOW), 'SESSION_TIME' => delta_time(($last_session_data['start_time'] == 0) ? TIMENOW : $last_session_data['start_time']), 'SESSION_AVERAGE_CYCLE_TIME'=> delta_time((int)$session_average_cycle_time, 0), 'SESSION_ESTIMATED_TIME' => delta_time((int)$session_estimated_time, 0), 'SEARCH_TABLES_SIZE' => humn_size($search_tables_size), 'FINAL_SEARCH_TABLES_SIZE' => humn_size($final_search_tables_size), 'SEARCH_DATA_SIZE' => humn_size($search_data_size), 'SEARCH_INDEX_SIZE' => humn_size($search_index_size), 'START_POST' => $last_session_data['start_post_id'], 'POST_LIMIT' => $num_rows, 'TIME_LIMIT' => $time_limit, 'REFRESH_RATE' => $refresh_rate, 'S_REBUILD_SEARCH_ACTION' => $form_action, )); } else // show the input page { // create the page // used only with the select input $post_limit_hidden = ( $def_post_limit > $total_posts ) ? $total_posts : $def_post_limit; $s_hidden_fields = ''; $s_hidden_fields .= ''; $next_start_post_id = 0; $last_saved_processing = ''; $clear_search_disabled = ''; if ($last_session_data['rebuild_session_id']) { $last_saved_post_id = $last_session_data['end_post_id']; $next_start_post_id = $last_saved_post_id + 1; $last_saved_date = bb_date($last_session_data['end_time']); // check our last status if ( $last_session_data['rebuild_session_status'] == REBUILD_SEARCH_PROCESSED ) { $last_saved_processing = sprintf($lang['INFO_PROCESSING_STOPPED'], $last_saved_post_id, $total_posts_processed, $last_saved_date); $clear_search_disabled = 'disabled="disabled"'; $template->assign_block_vars("start_select_input", array()); } elseif ( $last_session_data['rebuild_session_status'] == REBUILD_SEARCH_ABORTED ) { $last_saved_processing = sprintf($lang['INFO_PROCESSING_ABORTED'], $last_saved_post_id, $total_posts_processed, $last_saved_date); // check if the interrupted cycle has finished if ( TIMENOW - $last_session_data['end_time'] < $last_session_data['last_cycle_time'] ) { $last_saved_processing .= '
'.$lang['INFO_PROCESSING_ABORTED_SOON']; } $clear_search_disabled = 'disabled="disabled"'; $template->assign_block_vars("start_select_input", array()); } else // when finished { if ( $last_session_data['end_post_id'] < $max_post_id ) { $last_saved_processing = sprintf($lang['INFO_PROCESSING_FINISHED_NEW'], $last_saved_post_id, $total_posts_processed, $last_saved_date, ($total_posts - $total_posts_processed)); $clear_search_disabled = 'disabled="disabled"'; $template->assign_block_vars("start_select_input", array()); } else { $last_saved_processing = sprintf($lang['INFO_PROCESSING_FINISHED'], $total_posts, $last_saved_date); $template->assign_block_vars("start_text_input", array()); } } $template->assign_block_vars("last_saved_info", array()); } else { $template->assign_block_vars("start_text_input", array()); } // create the output of page $template->assign_vars(array( 'TPL_REBUILD_SEARCH_MAIN' => true, 'L_TIME_LIMIT_EXPLAIN' => $time_limit_explain, 'NEXT_START_POST_ID' => $next_start_post_id, 'CLEAR_SEARCH_DISABLED' => $clear_search_disabled, 'SESSION_POSTS_PROCESSING' => $session_posts_processing, 'POST_LIMIT' => $post_limit, 'REFRESH_RATE' => $refresh_rate, 'TIME_LIMIT' => $time_limit, 'LAST_SAVED_PROCESSING' => $last_saved_processing, 'SESSION_ID' => $userdata['session_id'], 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_REBUILD_SEARCH_ACTION' => "admin_rebuild_search.php?mode=submit", )); } print_page('admin_rebuild_search.tpl', 'admin'); // // Functions // function get_db_sizes () { $search_data_size = $search_index_size = 0; $search_table_like = DB()->escape(BB_POSTS_SEARCH); $sql = "SHOW TABLE STATUS FROM `". DB()->selected_db ."` LIKE '$search_table_like'"; foreach (DB()->fetch_rowset($sql) as $row) { $search_data_size += $row['Data_length']; $search_index_size += $row['Index_length']; } return array($search_data_size, $search_index_size, $search_data_size+$search_index_size); } // get the latest post_id in the forum function get_latest_post_id () { $row = DB()->fetch_row("SELECT MAX(post_id) as post_id FROM ". BB_POSTS_TEXT); return (int) $row['post_id']; } function get_empty_last_session_data () { return array( 'rebuild_session_id' => 0, 'start_post_id' => 0, 'end_post_id' => 0, 'start_time' => 0, 'end_time' => 0, 'last_cycle_time' => 0, 'session_time' => 0, 'session_posts' => 0, 'session_cycles' => 0, 'search_size' => 0, 'rebuild_session_status' => REBUILD_SEARCH_COMPLETED, ); } // get some or all of the rebuild details of a specific session or of the last session // $id is the id or the 'last' id // $details is one of the fields or 'all' of them function get_rebuild_session_details ($id, $details = 'all') { $session_details = get_empty_last_session_data(); if ($id != 'last') { $sql = "SELECT * FROM ". BB_SEARCH_REBUILD ." WHERE rebuild_session_id = $id"; } else { $sql = "SELECT * FROM ". BB_SEARCH_REBUILD ." ORDER BY rebuild_session_id DESC LIMIT 1"; } if ($row = DB()->fetch_row($sql)) { $session_details = ($details == 'all') ? $row : $row[$details]; } return $session_details; } // get the number of processed posts in the last session or in all sessions // 'total' to get the sum of posts of all sessions // 'session' to get the posts of the last session function get_processed_posts ($mode = 'session') { global $last_session_data; if ($mode == 'total') { $sql = "SELECT SUM(session_posts) as posts FROM ". BB_SEARCH_REBUILD; $row = DB()->fetch_row($sql); } else { $row['posts'] = $last_session_data['session_posts']; } return (int) $row['posts']; } // how many posts are in the db before or after a specific post_id // after/before require and the post_id function get_total_posts ($mode = 'after', $post_id = 0) { if ($post_id) { $sql = "SELECT COUNT(post_id) as total_posts FROM " . BB_POSTS_TEXT . " WHERE post_id " . (($mode == 'after') ? '>= ' : '<= ' ) . (int) $post_id; } else { $sql = "SELECT COUNT(*) as total_posts FROM " . BB_POSTS_TEXT; } $row = DB()->fetch_row($sql); $totalPosts = (int) $row['total_posts']; if ($totalPosts < 0) { return 0; } return $totalPosts; } function clear_search_tables ($mode = '') { DB()->query("DELETE FROM ". BB_SEARCH_REBUILD); if ($mode) { $table_ary = array(BB_POSTS_SEARCH); foreach ($table_ary as $table) { $sql = (($mode == 1) ? "DELETE FROM " : "TRUNCATE TABLE ") . $table; DB()->query($sql); } } } // Create the percent color // We use an array with the color percent limits. // One color stays constantly at FF when the percent is between its limits // and we adjust the other 2 accordingly to percent, from 200 to 0. // We limit the result to 200, in order to avoid white (255). function create_percent_color($percent) { $percent_ary = array( 'r' => array(86, 100), 'g' => array(0, 50), 'b' => array(51, 85), ); foreach ($percent_ary as $key => $value) { if ( $percent <= $value[1] ) { $percent_color = create_color($key, round(200-($percent-$value[0])*(200/($value[1]-$value[0])))); break; } } return $percent_color; } // create the hex representation of color function create_color($mode, $code) { return (($mode == 'r') ? 'FF': sprintf("%02X", $code)) . (($mode == 'g') ? 'FF': sprintf("%02X", $code)) . (($mode == 'b') ? 'FF': sprintf("%02X", $code)); } // create the percent bar & box function create_percent_box($box, $percent_color, $percent_width) { global $template; if ($box == 'session') { $template->assign_vars(array( 'SESSION_PERCENT_BOX' => true, 'SESSION_PERCENT_COLOR' => $percent_color, 'SESSION_PERCENT_WIDTH' => round($percent_width), )); } else { $template->assign_vars(array( 'TOTAL_PERCENT_BOX' => true, 'TOTAL_PERCENT_COLOR' => $percent_color, 'TOTAL_PERCENT_WIDTH' => round($percent_width), )); } }