From feb562e77bc06e8b7aa84e0f0e223b1ba7d27631 Mon Sep 17 00:00:00 2001 From: Tomas Srnka Date: Sun, 30 Aug 2009 14:54:36 +0000 Subject: [PATCH] Replication support - tomas_zahra branch merged --- db_structure.php | 38 +- lang/english-utf-8.inc.php | 46 ++ libraries/db_structure.lib.php | 12 +- libraries/replication.inc.php | 372 ++++++++++++++ libraries/replication_gui.lib.php | 189 +++++++ libraries/server_links.inc.php | 4 + server_databases.php | 41 +- server_replication.php | 489 +++++++++++++++++++ server_status.php | 175 ++----- themes/darkblue_orange/img/s_replication.png | Bin 0 -> 447 bytes themes/original/img/s_replication.png | Bin 0 -> 447 bytes 11 files changed, 1210 insertions(+), 156 deletions(-) create mode 100644 libraries/replication.inc.php create mode 100644 libraries/replication_gui.lib.php create mode 100644 server_replication.php create mode 100644 themes/darkblue_orange/img/s_replication.png create mode 100644 themes/original/img/s_replication.png diff --git a/db_structure.php b/db_structure.php index 7bad957c2..d526de07b 100644 --- a/db_structure.php +++ b/db_structure.php @@ -42,6 +42,8 @@ if (empty($is_info)) { // Gets the database structure $sub_part = '_structure'; require './libraries/db_info.inc.php'; + + require_once './libraries/replication.inc.php'; } // 1. No tables @@ -134,7 +136,7 @@ PMA_listNavigator($total_num_tables, $pos, $_url_params, 'db_structure.php', 'fr $each_table) { 0) || (strlen(array_search($db, $server_slave_Do_DB))>0) || (count($server_slave_Do_DB)==1 && count($server_slave_Ignore_DB)==1)) { + $do = true; + } + foreach ($server_slave_Wild_Do_Table as $table) { + if (($db == PMA_replication_strout($table)) && (ereg("^".substr(PMA_replication_strout($table, true), 0, strlen(PMA_replication_strout($table, true))-1), $truename))) + $do = true; + } + //////////////////////////////////////////////////////////////////// + if ((strlen(array_search($truename, $server_slave_Ignore_Table))>0) || (strlen(array_search($db, $server_slave_Ignore_DB))>0)) { + $ignored = true; + } + foreach ($server_slave_Wild_Ignore_Table as $table) { + if (($db == PMA_replication_strout($table)) && (ereg("^".substr(PMA_replication_strout($table, true), 0, strlen(PMA_replication_strout($table, true))-1), $truename))) + $ignored = true; + } + }/* elseif ($server_master_status) { + if ((strlen(array_search($db, $server_master_Do_DB))>0) || count($server_master_Do_DB)==1) + $do = true; + elseif ((strlen(array_search($db, $server_master_Ignore_DB))>0) || count($server_master_Ignore_DB)==1) + $ignored = true; + }*/ ?> @@ -339,9 +369,9 @@ foreach ($tables as $keyname => $each_table) { value="" id="checkbox_tbl_" /> - + title="" style=""> + ' : ''. $do ? ' REPLICATED' : ''; ?> diff --git a/lang/english-utf-8.inc.php b/lang/english-utf-8.inc.php index c899aeec1..25e9062da 100644 --- a/lang/english-utf-8.inc.php +++ b/lang/english-utf-8.inc.php @@ -1569,4 +1569,50 @@ $strYes = 'Yes'; $strZeroRemovesTheLimit = 'Note: Setting these options to 0 (zero) removes the limit.'; $strZip = '"zipped"'; + + +///////// NEW STRINGS +$strReplcationSelectDatabases = 'Please select databases:'; +$strReplcationSynchronize = 'Synchronize databases with master'; +$strReplicationAddLines = 'Now, add following lines at the end of your my.cnf and please restart the mysql server afterwards.'; +$strReplicationAddSlaveUser = 'Add slave replication user?'; +$strReplicationChangedSuccesfully = 'Master server changed succesfully to %s'; +$strReplicationConfiguredMaster = 'This server is configured as master in replication process.'; +$strReplicationControlSlave = 'Control slave:'; +$strReplicationMaster = 'Master Replication'; +$strReplicationMasterChooseAll = 'Replicate all databases; Ignore:'; +$strReplicationMasterChooseIgn = 'Ignore all databases; Replicate:'; +$strReplicationMasterChooseMode = 'This server is not configured as master server in replication process. You can choose from either replicating all databases and ignoring certain (useful if you want to replicate majority of databases) or you can choose to ignore all databases by default and allow only certain databases to be replicated. Please select the mode:'; +$strReplicationMasterConfiguration = 'Master Configuration'; +$strReplicationRestartServer = 'Once you restarted MySQL server, please click on Go button. Afterwards, you should see a message informating you, that this server is configured as master'; +$strReplicationServernConfiguredMaster = 'This server is not configured as master in replication process. Would you like to configure it?'; +$strReplicationShowMasterStatus = 'Show master status'; +$strReplicationSkippingErrorWarn = 'Skiping error(s) might lead into unsynchronized master and slave!'; +$strReplicationSlave = 'Slave Replication'; +$strReplicationSlaveChangeMaster = 'Change or reconfigure master server'; +$strReplicationSlaveConfigured = 'Server is configured as slave in replication process. Would you like to:'; +$strReplicationSlaveNotConfigured = 'This server is not configured as slave in replication process. Would you like to configure it?'; +$strReplicationSlaveErrorManagement = 'Error management:'; +$strReplicationSlaveIOThread = 'IO Thread %s only'; +$strReplicationSlaveReset = 'Reset Slave'; +$strReplicationSlaveSQLThread = 'SQL Thread %s only'; +$strReplicationSlaveSeeStatus = 'See slave status table'; +$strReplicationSlaveSkipCurrentError = 'Skip current error'; +$strReplicationSlaveSkipNext = 'Skip next'; +$strReplicationSlaveSkipNextErrors = 'errors.'; +$strReplicationStatus = 'Replication status'; +$strPort = 'Port'; +$strFull = 'Full'; +$strStop = 'Stop'; +$strStart ='Start'; +$strShowMasterStatus = 'Show master status'; +$strSlaveConfigure = 'Make sure, you have unique server-id in your configuration file (my.cnf). If not, please add following line into [mysqld] section:'; + +$strDataSyn = 'Data Synchronization'; +$strStructureSyn = 'Structure Synchronization'; +$strSynchronizationNote='Target database will completely synchronize with source database.Source database will remain unchanged.'; +$strSynchronize = 'Synchronize'; +$strSynchronizeDb= 'Synchronize Databases'; +$strReplicationUnknownError = 'Unknown error'; +$strReplicationUnableToChange = 'Unable to change master'; ?> diff --git a/libraries/db_structure.lib.php b/libraries/db_structure.lib.php index 0ad779bd8..11219bb84 100644 --- a/libraries/db_structure.lib.php +++ b/libraries/db_structure.lib.php @@ -28,8 +28,9 @@ if (! defined('PHPMYADMIN')) { * @uses $GLOBALS['structure_tbl_col_cnt'] * @uses PMA_SortableTableHeader() * @param boolean $db_is_information_schema + * @param boolean $replication */ -function PMA_TableHeader($db_is_information_schema = false) +function PMA_TableHeader($db_is_information_schema = false, $replication = false) { $cnt = 0; // Let's count the columns... @@ -42,8 +43,13 @@ function PMA_TableHeader($db_is_information_schema = false) echo '' . "\n" .'' . "\n" .'' . "\n" - .' ' . "\n" - .' ' . "\n"; + if ($replication) { + echo ' '; + } + echo ' ' // larger values are more interesting so default sort order is DESC diff --git a/libraries/replication.inc.php b/libraries/replication.inc.php new file mode 100644 index 000000000..a2da0de18 --- /dev/null +++ b/libraries/replication.inc.php @@ -0,0 +1,372 @@ + 'No', + 'Slave_SQL_Running' => 'No' + ); +$slave_variables_oks = array( + 'Slave_IO_Running' => 'Yes', + 'Slave_SQL_Running' => 'Yes' + ); + +$serverid = time(); + +// check which replication is available and set $server_{master/slave}_status and assign values +foreach ($replication_types as $type) { + if (count(${"server_{$type}_replication"}) > 0) + ${"server_{$type}_status"} = true; + else + ${"server_{$type}_status"} = false; + + if (${"server_{$type}_status"}) { + if ($type=="master") { + ${"server_{$type}_Do_DB"} = split (",", $server_master_replication[0]["Binlog_Do_DB"]); + ${"server_{$type}_Ignore_DB"} = split (",", $server_master_replication[0]["Binlog_Ignore_DB"]); + } elseif ($type=="slave") { + ${"server_{$type}_Do_DB"} = split (",", $server_slave_replication[0]["Replicate_Do_DB"]); + ${"server_{$type}_Ignore_DB"} = split (",", $server_slave_replication[0]["Replicate_Ignore_DB"]); + + ${"server_{$type}_Do_Table"} = split (",", $server_slave_replication[0]["Replicate_Do_Table"]); + ${"server_{$type}_Ignore_Table"} = split (",", $server_slave_replication[0]["Replicate_Ignore_Table"]); + + ${"server_{$type}_Wild_Do_Table"} = split(",", $server_slave_replication[0]["Replicate_Wild_Do_Table"]); + ${"server_{$type}_Wild_Ignore_Table"} = split(",", $server_slave_replication[0]["Replicate_Wild_Ignore_Table"]); + } + } +} + + +/** + * @param $string - + * @param $table - + * @return + */ +function PMA_replication_strout($string, $table=false) { + $list = explode(".", $string); + + return $list[(int)$table]; +} +/** + * @param String $action - possible values: START or STOP + * @param String $control - default: null, possible values: SQL_THREAD or IO_THREAD or null. If it is set to null, it controls both SQL_THREAD and IO_THREAD + * @param mixed $link - mysql link + * + * @return mixed output of PMA_DBI_try_query + */ +function PMA_replication_slave_control ($action, $control=null, $link=null) +{ + $action = strtoupper($action); + $control = strtoupper($control); + + + if ($action!="START" && $action!="STOP") + return -1; + if ($control!="SQL_THREAD" && $control!="IO_THREAD" && $control!=null) + return -1; + return PMA_DBI_try_query($action." SLAVE ".$control.";", $link); +} +/** + * @param String $user - replication user on master + * @param String $password - password for the user + * @param String $host - master's hostname or IP + * @param int $port - port, where mysql is running + * @param array $pos - position of mysql replication, array should contain fields File and Position + * @param boolean $stop - shall we stop slave? + * @param boolean $start - shall we start slave? + * @param mixed $link - mysql link + * + * @return output of CHANGE MASTER mysql command + */ +function PMA_replication_slave_change_master($user, $password, $host, $port, $pos, $stop=true, $start=true, $link=null) +{ + if ($stop) + PMA_replication_slave_control("STOP", null, $link); + + $out = PMA_DBI_try_query('CHANGE MASTER TO '. + 'MASTER_HOST=\''.$host.'\','. + 'MASTER_PORT='.($port*1).','. + 'MASTER_USER=\''.$user.'\','. + 'MASTER_PASSWORD=\''.$password.'\','. + 'MASTER_LOG_FILE=\''.$pos["File"].'\','. + 'MASTER_LOG_POS='.$pos["Position"].';', $link); + + if ($start) + PMA_replication_slave_control("START", null, $link); + + return $out; +} + +/** + * This function provides connection to remote mysql server + * + * @param String $user - mysql username + * @param String $password - password for the user + * @param String $host - mysql server's hostname or IP + * @param int $port - mysql remote port + * @param String $socket - path to unix socket + * + * @return mixed $link mysql link on success + */ +function PMA_replication_connect_to_master($user, $password, $host=null, $port=null, $socket=null) +{ + $server = array(); + $server["host"] = $host; + $server["port"] = $port; + $server["socket"] = $socket; + + return PMA_DBI_connect($user, $password, false, $server); +} +/** + * @param $link - mysql link + * + * @return array - containing File and Position in MySQL replication on master server, useful for PMA_replication_slave_change_master + */ +function PMA_replication_slave_bin_log_master($link=null) +{ + $data = PMA_DBI_fetch_result('SHOW MASTER STATUS', null, null, $link); + + $output = array(); + $output["File"] = $data[0]["File"]; + $output["Position"] = $data[0]["Position"]; + + return $output; +} + +/** + * Get list of replicated databases on master server + * + * @param mixed mysql link + * + * @return array array of replicated databases + */ + +function PMA_replication_master_replicated_dbs($link=null) +{ + $data = PMA_DBI_fetch_result('SHOW MASTER STATUS', null, null, $link); // let's find out, which databases are replicated + + $do_db = array(); + $ignore_db = array(); + + if (!empty($data[0]['Binlog_Do_DB'])) + $do_db = explode($data[0]['Binlog_Do_DB'], ','); + if (!empty($data[0]['Binlog_Ignore_DB'])) + $ignore_db = explode($data[0]['Binlog_Ignore_DB'], ','); + + $tmp_alldbs = PMA_DBI_query('SHOW DATABASES;', $link); + while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) { + if ($tmp_row[0] == 'information_schema') + continue; + if (count($do_db)==0) { + if (array_search($tmp_row[0], $ignore_db)!==false) { + continue; + } + $dblist[] = $tmp_row[0]; + + } else { + if (array_search($tmp_row[0], $do_db)!==false) { + $dblist[] = $tmp_row[0]; + } + } + } // end while + + return $link; +} +/** + * This function provides synchronization of structure and data between two mysql servers. + * TODO: improve code sharing between the function and synchronization + * + * @param String $db - name of database, which should be synchronized + * @param mixed $src_link - link of source server, note: if the server is current PMA server, use null + * @param mixed $trg_link - link of target server, note: if the server is current PMA server, use null + * @param boolean $data - if true, then data will be copied as well + */ + +function PMA_replication_synchronize_DB($db, $src_link, $trg_link, $data=true) +{ + $src_db = $db; + $trg_db = $db; + $src_connection = PMA_DBI_select_db($db, $src_link); + $trg_connection = PMA_DBI_select_db($db, $trg_link); + + $src_tables = PMA_DBI_get_tables($src_db, $src_link); + $source_tables_num = sizeof($src_tables); + + $trg_tables = PMA_DBI_get_tables($trg_db, $trg_link); + $target_tables_num = sizeof($trg_tables); + /** + * initializing arrays to save table names + */ + $unmatched_num_src = 0; + $source_tables_uncommon = array(); + $unmatched_num_trg = 0; + $target_tables_uncommon = array(); + $matching_tables = array(); + $matching_tables_num = 0; + + /** + * Criterion for matching tables is just their names. + * Finding the uncommon tables for the source database + * BY comparing the matching tables with all the tables in the source database + */ + PMA_getMatchingTables($trg_tables, $src_tables, $matching_tables, $source_tables_uncommon); + + /** + * Finding the uncommon tables for the target database + * BY comparing the matching tables with all the tables in the target database + */ + PMA_getNonMatchingTargetTables($trg_tables, $matching_tables, $target_tables_uncommon); + + /** + * + * ********************************************* Comparing Data In the Matching Tables ****************************************** + * *********************It is assumed that the matching tables are structurally and typely exactly the same ********************* + */ + $fields_num = array(); + $matching_tables_fields = array(); + $matching_tables_keys = array(); + $insert_array = array(array(array())); + $update_array = array(array(array())); + $delete_array = array(); + $row_count = array(); + $uncommon_tables_fields = array(); + $matching_tables_num = sizeof($matching_tables); + + for($i=0; $i< sizeof($matching_tables); $i++) + { + PMA_dataDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $matching_tables_fields, $update_array, $insert_array, + $delete_array, $fields_num, $i, $matching_tables_keys); + } + for($j=0; $j< sizeof($source_tables_uncommon); $j++) + { + PMA_dataDiffInUncommonTables($source_tables_uncommon, $src_db, $src_link, $j, $row_count); + } + /** + * INTEGRATION OF STRUCTURE DIFFERENCE CODE + * + */ + $source_columns = array(); + $target_columns = array(); + $alter_str_array = array(array()); + $add_column_array = array(array()); + $uncommon_columns = array(); + $target_tables_keys = array(); + $source_indexes = array(); + $target_indexes = array(); + $add_indexes_array = array(); + $remove_indexes_array = array(); + $criteria = array('Field', 'Type', 'Null', 'Collation', 'Key', 'Default', 'Comment'); + + for ($counter= 0; $counter< $matching_tables_num; $counter++) + { +// PMA_structureDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_columns, +// $target_columns, $alter_str_array, $add_column_array, $uncommon_columns, $criteria, $matching_tables_keys, +// $target_tables_keys, $matching_tables_fields, $counter); +// +// PMA_indexesDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_indexes, $target_indexes, +// $add_indexes_array, $remove_indexes_array, $counter); + PMA_structureDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_columns, + $target_columns, $alter_str_array, $add_column_array, $uncommon_columns, $criteria, $target_tables_keys, $counter); + + PMA_indexesDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_indexes, $target_indexes, + $add_indexes_array, $alter_indexes_array,$remove_indexes_array, $counter); + } + + + + $matching_table_data_diff = array(); + $matching_table_structure_diff = array(); + $uncommon_table_structure_diff = array(); + $uncommon_table_data_diff = array(); + $uncommon_tables = $source_tables_uncommon; + + /** + * Generating Create Table query for all the non-matching tables present in Source but not in Target and populating tables. + */ + for($q=0; $q < sizeof($source_tables_uncommon) ;$q++) + { + if (isset($uncommon_tables[$q])) { + PMA_createTargetTables($src_db, $trg_db, $src_link, $trg_link, $source_tables_uncommon, $q, $uncommon_tables_fields, false); + } + if (isset($row_count[$q]) && $data) { + PMA_populateTargetTables($src_db, $trg_db, $src_link, $trg_link, $source_tables_uncommon, $q, $uncommon_tables_fields, false); + } + } +} +?> \ No newline at end of file diff --git a/libraries/replication_gui.lib.php b/libraries/replication_gui.lib.php new file mode 100644 index 000000000..76ca27a6f --- /dev/null +++ b/libraries/replication_gui.lib.php @@ -0,0 +1,189 @@ +log-bin=mysql-bin
log-error=mysql-bin.err
";'."\n". + 'var c_ignore = "binlog_ignore_db=";'."\n". + 'var c_do = "binlog_do_db=";'."\n". + + '$(\'db_reset_href\').addEvent(\'click\', function() {'."\n". + ' $(\'db_select\').getSelected().each(function(el) {'."\n". + ' el.selected = false;'."\n". + ' });'."\n". + ' $(\'rep\').set(\'html\', c_text);'."\n". + '});'."\n". + '$(\'db_type\').addEvent(\'change\',function() {'."\n". + ' if ($(\'db_type\').getSelected().get(\'value\')=="all")'."\n". + ' $(\'rep\').set(\'html\', c_text+c_ignore+c_output+\';\');'."\n". + ' else'."\n". + ' $(\'rep\').set(\'html\', c_text+c_do+c_output+\';\');'."\n". + '});'."\n". + + '$(\'db_select\').addEvent(\'change\',function() {'."\n". + ' var count = 0;'."\n". + + ' $(\'db_select\').getSelected().each(function(el) { '."\n". + ' if (count==0)'."\n". + ' c_output = el.get(\'value\');'."\n". + ' else'."\n". + ' c_output = c_output + \',\' +el.get(\'value\');'."\n". + + ' count=count+1;'."\n". + + ' if ($(\'db_select\').getSelected().length==count) {'."\n". + ' if ($(\'db_type\').getSelected().get(\'value\')=="all")'."\n". + ' $(\'rep\').set(\'html\', c_text+c_ignore+c_output);'."\n". + ' else'."\n". + ' $(\'rep\').set(\'html\', c_text+c_do+c_output);'."\n". + ' count = 0;'."\n". + ' }'."\n". + ' });'."\n". + '});'."\n"; + +$jscode['slave_control'] = + 'divShowHideFunc(\'slave_status_href\', \'replication_slave_section\');'."\n". + 'divShowHideFunc(\'slave_control_href\', \'slave_control_gui\');'."\n". + 'divShowHideFunc(\'slave_errormanagement_href\',\'slave_errormanagement_gui\'); '."\n"; + +$jscode['slave_control_sync'] = + 'divShowHideFunc(\'slave_synchronization_href\', \'slave_synchronization_gui\');'."\n"; +/** + * returns code for selecting databases + * + * @return String HTML code + */ +function PMA_replication_db_multibox() +{ + $multi_values = ''; + $multi_values .= ''; + $multi_values .= '
Uncheck all'; + + return $multi_values; +} + +/** + * prints out code for changing master + * + * @param String $submitname - submit button name + */ + +function PMA_replication_gui_changemaster($submitname) { + global $username_length; + global $hostname_length; + + echo ''."\n"; + echo PMA_generate_common_hidden_inputs('', ''); + echo '
'."\n"; + echo ' Slave configuration - change master server'."\n"; + echo $GLOBALS['strSlaveConfigure'].'
'."\n"; + echo '
server-id='.time().'
'."\n"; + echo '
'."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo '
'."\n"; + echo '
'."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo '
'."\n"; + echo '
'."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo '
'."\n"; + echo '
'."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo '
'."\n"; + echo '
'."\n"; + echo ' '."\n"; + echo ''."\n"; + +} +/** + * This function prints out table with replication status. + * + * @param String type - either master or slave + * @param boolean $hidden - if true, then default style is set to hidden, default value false + * @param boolen $title - if true, then title is displayed, default true + */ +function PMA_replication_print_status_table ($type, $hidden=false, $title=true) { + global ${"{$type}_variables"}; + global ${"{$type}_variables_alerts"}; + global ${"{$type}_variables_oks"}; + global ${"server_{$type}_replication"}; + global ${"strReplicationStatus_{$type}"}; + + echo '
'."\n"; + + if ($title) { + echo '

'.${"strReplicationStatus_{$type}"} .'

'."\n"; + } else { + echo '
'."\n"; + } + + echo '
' . PMA_SortableTableHeader($GLOBALS['strTable'], 'table') . '' . "\n" + .' ' . PMA_SortableTableHeader($GLOBALS['strTable'], 'table') . '' . "\n" + .' ' . "Replication" . "\n" + .' ' . "\n" .' ' . $GLOBALS['strAction'] . "\n" .'
'."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + + $odd_row = true; + foreach(${"{$type}_variables"} as $variable) { + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + echo ' '."\n"; + + $odd_row = !$odd_row; + } + + echo ' '."\n"; + echo '
'. $GLOBALS['strVar'] .''. $GLOBALS['strValue'] .'
'."\n"; + echo $variable."\n"; + echo ' '."\n"; + + if (isset(${"{$type}_variables_alerts"}[$variable]) && ${"{$type}_variables_alerts"}[$variable] == ${"server_{$type}_replication"}[0][$variable]) + echo ''."\n"; + if (isset(${"{$type}_variables_oks"}[$variable]) && ${"{$type}_variables_oks"}[$variable] == ${"server_{$type}_replication"}[0][$variable]) + echo ''."\n"; + else + echo ''."\n"; + echo ${"server_{$type}_replication"}[0][$variable]; + echo ''."\n"; + + echo '
'."\n"; + echo '
'."\n"; + echo ''."\n"; + +} +?> + diff --git a/libraries/server_links.inc.php b/libraries/server_links.inc.php index 9ba9b8408..9ede6e98d 100644 --- a/libraries/server_links.inc.php +++ b/libraries/server_links.inc.php @@ -64,6 +64,10 @@ if ($is_superuser) { $tabs['rights']['icon'] = 's_rights.png'; $tabs['rights']['link'] = 'server_privileges.php'; $tabs['rights']['text'] = $strPrivileges; + + $tabs['replication']['icon'] = 's_replication.png'; + $tabs['replication']['link'] = 'server_replication.php'; + $tabs['replication']['text'] = "Replication"; } if (! empty($binary_logs)) { diff --git a/server_databases.php b/server_databases.php index 6b29f774f..27026c4e2 100644 --- a/server_databases.php +++ b/server_databases.php @@ -14,6 +14,7 @@ require_once './libraries/common.inc.php'; $GLOBALS['js_include'][] = 'functions.js'; require './libraries/server_common.inc.php'; +require './libraries/replication.inc.php'; /** * avoids 'undefined index' errors @@ -34,7 +35,7 @@ if (isset($_REQUEST['sort_order']) $dbstats = empty($_REQUEST['dbstats']) ? 0 : 1; $pos = empty($_REQUEST['pos']) ? 0 : (int) $_REQUEST['pos']; - + /** * Drops multiple databases */ @@ -187,6 +188,17 @@ if ($databases_count > 0) { .' ' . "\n"; } } + + foreach ($replication_types as $type) + { + if ($type=="master") + $name = "strReplicationMaster"; + elseif($type == "slave") + $name = "strReplicationSlave"; + if (${"server_{$type}_status"}) + echo ' '.$GLOBALS[$name].'' . "\n"; + } + if ($is_superuser) { echo ' ' . ($cfg['PropertiesIconic'] ? '' : $strAction) . "\n" . ' ' . "\n"; @@ -247,7 +259,25 @@ if ($databases_count > 0) { } } } - + foreach ($replication_types as $type) { + if (${"server_{$type}_status"}) { + echo '' . "\n"; + + if (strlen(array_search($current["SCHEMA_NAME"], ${"server_{$type}_Ignore_DB"}))>0) { + echo 'REPLICATED' . "\n"; + } else { + $key = array_search($current["SCHEMA_NAME"], ${"server_{$type}_Do_DB"}); + + if (strlen($key)>0 || (${"server_{$type}_Do_DB"}[0]=="" && count(${"server_{$type}_Do_DB"})==1)) // if ($key != null) did not work for index "0" + echo 'REPLICATED' . "\n"; + else + echo ''; + } + + echo ''; + } + } + if ($is_superuser) { echo ' ' . "\n" . ' ' . "\n"; + } + if ($is_superuser) { echo ' ' . "\n"; } diff --git a/server_replication.php b/server_replication.php new file mode 100644 index 000000000..b4ec67097 --- /dev/null +++ b/server_replication.php @@ -0,0 +1,489 @@ +' . "\n" + . PMA_getIcon('s_replication.png') + . $GLOBALS['strReplication'] . "\n" + . '' . "\n"; + PMA_Message::error('strNoPrivileges')->display(); + require_once './libraries/footer.inc.php'; +} + +/** + * Handling control requests + */ + +if (isset($GLOBALS['sr_take_action'])) { + $refresh = false; + if (isset($GLOBALS['slave_chagemaster'])) { + $_SESSION['replication']['m_username'] = $sr['username'] = PMA_sqlAddslashes($GLOBALS['username']); + $_SESSION['replication']['m_password'] = $sr['pma_pw'] = PMA_sqlAddslashes($GLOBALS['pma_pw']); + $_SESSION['replication']['m_hostname'] = $sr['hostname'] = PMA_sqlAddslashes($GLOBALS['hostname']); + $_SESSION['replication']['m_port'] = $sr['port'] = PMA_sqlAddslashes($GLOBALS['port']); + $_SESSION['replication']['m_correct'] = ''; + $_SESSION['replication']['sr_action_status'] = 'error'; + $_SESSION['replication']['sr_action_info'] = $strReplicationUnknownError; + $url = $sr['hostname']; + + if ($sr['port']!='') + $url .= ':'.$sr['port']; + + $check_master = null; + error_reporting(0); + $check_master = @mysql_connect($url, $sr['username'], $sr['pma_pw']); + error_reporting(15); + unset($url); + + if (!$check_master) { + $_SESSION['replication']['sr_action_status'] = 'error'; + $_SESSION['replication']['sr_action_info'] = 'Unable to connect to master '. $sr['hostname'] .'. '; + } else { + $link_to_master = PMA_replication_connect_to_master($sr['username'], $sr['pma_pw'], $sr['hostname'], $sr['port']); + $position = PMA_replication_slave_bin_log_master($link_to_master); + + $_SESSION['replication']['m_correct'] = true; + + if (PMA_replication_slave_change_master($sr['username'], $sr['pma_pw'], $sr['hostname'], $sr['port'], $position, true, false)) { + $_SESSION['replication']['sr_action_status'] = 'error'; + $_SESSION['replication']['sr_action_info'] = $GLOBALS['strReplicationUnableToChange']; + } else { + $_SESSION['replication']['sr_action_status'] = 'success'; + $_SESSION['replication']['sr_action_info'] = sprintf($GLOBALS['strReplicationChangedSuccesfully'], $sr['hostname']); + } + } + } elseif (isset($GLOBALS['sr_slave_server_control'])) { + if ($GLOBALS['sr_slave_action']=='reset') { + PMA_replication_slave_control("STOP"); + PMA_DBI_try_query("RESET SLAVE;"); + PMA_replication_slave_control("START"); + } else { + PMA_replication_slave_control($GLOBALS['sr_slave_action'], $GLOBALS['sr_slave_control_parm']); + } + $refresh = true; + } elseif (isset($GLOBALS['sr_slave_skip_error'])) { + $count = 1; + if (isset($GLOBALS['sr_skip_errors_count'])) { + $count = $GLOBALS['sr_skip_errors_count']*1; + } + PMA_replication_slave_control("STOP"); + PMA_DBI_try_query("SET GLOBAL SQL_SLAVE_SKIP_COUNTER = ".$count.";"); + PMA_replication_slave_control("START"); + } elseif (isset($GLOBALS['sl_sync'])) { + $src_link = PMA_replication_connect_to_master($_SESSION['replication']['m_username'], $_SESSION['replication']['m_password'], $_SESSION['replication']['m_hostname'], $_SESSION['replication']['m_port']); + $trg_link = null; + + $data = PMA_DBI_fetch_result('SHOW MASTER STATUS', null, null, $src_link); // let's find out, which databases are replicated + + $do_db = array(); + $ignore_db = array(); + + if (!empty($data[0]['Binlog_Do_DB'])) + $do_db = explode($data[0]['Binlog_Do_DB'], ','); + if (!empty($data[0]['Binlog_Ignore_DB'])) + $ignore_db = explode($data[0]['Binlog_Ignore_DB'], ','); + + $tmp_alldbs = PMA_DBI_query('SHOW DATABASES;', $src_link); + while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) { + if ($tmp_row[0] == 'information_schema') + continue; + if (count($do_db)==0) { + if (array_search($tmp_row[0], $ignore_db)!==false) { + continue; + } + $dblist[] = $tmp_row[0]; + + PMA_DBI_query('CREATE DATABASE IF NOT EXISTS '.$tmp_row[0], $trg_link); + } else { + if (array_search($tmp_row[0], $do_db)!==false) { + $dblist[] = $tmp_row[0]; + PMA_DBI_query('CREATE DATABASE IF NOT EXISTS '.$tmp_row[0], $trg_link); + } + } + } // end while + if (isset($GLOBALS['repl_data'])) + $data = true; + else + $data = false; + foreach ($dblist as $db) { + PMA_replication_synchronize_db($db, $src_link, $trg_link, $data); + } + } + + if ($refresh) + Header("Location: ". PMA_generate_common_url($GLOBALS['url_params'])); + unset($refresh); +} +/** + * Displays the links + */ +require './libraries/server_links.inc.php'; + + echo '
'."\n"; + echo '

'."\n"; + echo ' '."\n"; + echo $GLOBALS['strReplication']."\n"; + echo '

'."\n"; + + if (isset($_SESSION['replication']['sr_action_status']) && isset($_SESSION['replication']['sr_action_info'])) { + if ($_SESSION['replication']['sr_action_status']=='error') { + PMA_Message::error($_SESSION['replication']['sr_action_info'])->display(); + $_SESSION['replication']['sr_action_status'] = 'unknown'; + } elseif ($_SESSION['replication']['sr_action_status']=='success') { + PMA_Message::success($_SESSION['replication']['sr_action_info'])->display(); + $_SESSION['replication']['sr_action_status'] = 'unknown'; + } + } + + if ($server_master_status) { + if (!isset($GLOBALS['repl_clear_scr'])) { + echo PMA_js_mootools_domready($jscode['master_replication']); + echo '
'."\n"; + echo ''. $GLOBALS['strReplicationMaster'] .''."\n"; + echo $GLOBALS['strReplicationConfiguredMaster']."\n"; + echo '
    '."\n"; + echo '
  • '. $GLOBALS['strReplicationShowMasterStatus'] .'
  • '; + PMA_replication_print_status_table('master', true, false); + $_url_params = $GLOBALS['url_params']; + $_url_params['mr_adduser'] = true; + $_url_params['repl_clear_scr'] = true; + + echo '
  • '. $GLOBALS['strReplicationAddSlaveUser'] .'
  • '; + } + if (isset($GLOBALS['mr_adduser'])) { + $fields_info = PMA_DBI_get_fields('mysql', 'user'); + $username_length = 16; + $hostname_length = 41; + foreach ($fields_info as $key => $val) { + if ($val['Field'] == 'User') { + strtok($val['Type'], '()'); + $v = strtok('()'); + if (is_int($v)) { + $username_length = $v; + } + } elseif ($val['Field'] == 'Host') { + strtok($val['Type'], '()'); + $v = strtok('()'); + if (is_int($v)) { + $hostname_length = $v; + } + } + } + unset($fields_info); + + if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) { + $GLOBALS['pred_username'] = 'any'; + } + echo '
    '."\n"; + echo '
    '."\n"; + echo PMA_generate_common_hidden_inputs('', ''); + echo '
    ' . "\n" + . ''.$GLOBALS['strReplicationAddSlaveUser'].'' . "\n" + . ''. "\n" + . ''. "\n" + . '
    ' . "\n" + . '' . "\n" + . '' . "\n" + . ' ' . "\n" + . '' . "\n" + . '' . "\n" + . '
    ' . "\n" + . '
    ' . "\n" + . '' . "\n" + . '' . "\n" + . ' ' . "\n" + . '' . "\n" + . '' . "\n" + . PMA_showHint($GLOBALS['strHostTableExplanation']) + . '
    ' . "\n" + . '
    ' . "\n" + . '' . "\n" + . '' . "\n" + . ' ' . "\n" + . '' . "\n" + . '' . "\n" + . '
    ' . "\n" + . '
    ' . "\n" + . '' . "\n" + . ' ' . "\n" + . '' . "\n" + . '
    ' . "\n" + . '
    ' . "\n" + . '' . "\n" + . '' . "\n" + . ' ' . "\n" + . '' . "\n" + . '' . "\n" + . '
    ' . "\n" + . '
    ' . "\n"; + echo '' . "\n"; + echo '
    '."\n"; + echo '
    '."\n";/////// + } elseif (!isset($GLOBALS['repl_clear_scr'])) { + echo "
\n"; + echo '
'."\n"; + } +} elseif (!isset($GLOBALS['mr_configure']) && !isset($GLOBALS['repl_clear_scr'])) { + $_url_params = $GLOBALS['url_params']; + $_url_params['mr_configure'] = true; + + echo '
'."\n"; + echo ''. $GLOBALS['strReplicationMaster'] .''."\n"; + echo sprintf($GLOBALS['strReplicationServernConfiguredMaster'], PMA_generate_common_url($_url_params)) ."\n"; + echo '
'."\n"; +} + +if (isset($GLOBALS['mr_configure'])) { + echo PMA_js_mootools_domready($jscode['configure_master']); + echo '
'."\n"; + echo ''. $GLOBALS['strReplicationMasterConfiguration'] .''."\n"; + echo $GLOBALS['strReplicationMasterChooseMode'].'

'."\n"; + + echo ''."\n"; + echo '

'."\n"; + echo $GLOBALS['strReplcationSelectDatabases'].'
'."\n"; + echo PMA_replication_db_multibox(); + echo '

'."\n"; + echo $GLOBALS['strReplicationAddLines'].'
'."\n"; + echo '
server-id='. $serverid .'
log-bin=mysql-bin
log-error=mysql-bin.err
'."\n"; + echo $GLOBALS['strReplicationRestartServer'] ."\n"; + echo '
'."\n"; + echo '
'; + echo '
'."\n"; + echo PMA_generate_common_hidden_inputs('', ''); + echo ' '; + echo '
'."\n"; + echo '
'; + + require_once './libraries/footer.inc.php'; + exit; +} + +echo '
'; + +if (!isset($GLOBALS['repl_clear_scr'])) { + echo '
'."\n"; + echo 'Server Replication'."\n"; + if ($server_slave_status) { + echo PMA_js_mootools_domready($jscode['slave_control']); + echo '
'."\n"; + + $_url_params = $GLOBALS['url_params']; + $_url_params['sr_take_action'] = true; + $_url_params['sr_slave_server_control'] = true; + + if ($server_slave_replication[0]['Slave_IO_Running']=='No') + $_url_params['sr_slave_action'] = 'start'; + else + $_url_params['sr_slave_action'] = 'stop'; + $_url_params['sr_slave_control_parm'] = 'IO_THREAD'; + $slave_control_io_link = PMA_generate_common_url($_url_params); + + if ($server_slave_replication[0]['Slave_SQL_Running']=='No') + $_url_params['sr_slave_action'] = 'start'; + else + $_url_params['sr_slave_action'] = 'stop'; + $_url_params['sr_slave_control_parm'] = 'SQL_THREAD'; + $slave_control_sql_link = PMA_generate_common_url($_url_params); + + if ($server_slave_replication[0]['Slave_IO_Running']=='No' || $server_slave_replication[0]['Slave_SQL_Running']=='No') + $_url_params['sr_slave_action'] = 'start'; + else + $_url_params['sr_slave_action'] = 'stop'; + $_url_params['sr_slave_control_parm'] = null; + $slave_control_full_link = PMA_generate_common_url($_url_params); + + $_url_params['sr_slave_action'] = 'reset'; + $slave_control_reset_link = PMA_generate_common_url($_url_params); + + $_url_params = $GLOBALS['url_params']; + $_url_params['sr_slave_skip_error'] = true; + $slave_skip_error_link = PMA_generate_common_url($_url_params); + + if ($server_slave_replication[0]['Slave_SQL_Running']=='No') + PMA_Message::warning('Slave SQL Thread not running!')->display(); + if ($server_slave_replication[0]['Slave_IO_Running']=='No') + PMA_Message::warning('Slave IO Thread not running!')->display(); + + $_url_params = $GLOBALS['url_params']; + $_url_params['sl_configure'] = true; + $_url_params['repl_clear_scr'] = true; + + $reconfiguremaster_link = PMA_generate_common_url($_url_params); + + echo $GLOBALS['strReplicationSlaveConfigured']."\n"; + echo '
'."\n"; + echo ''."\n"; + + } elseif (!isset($GLOBALS['sl_configure'])) { + $_url_params = $GLOBALS['url_params']; + $_url_params['sl_configure'] = true; + $_url_params['repl_clear_scr'] = true; + + echo sprintf($GLOBALS['strReplicationSlaveNotConfigured'], PMA_generate_common_url($_url_params))."\n"; + } + echo '
'."\n"; +} +if (isset($GLOBALS['sl_configure'])) { + PMA_replication_gui_changemaster("slave_chagemaster"); +} +echo ''."\n"; +require_once './libraries/footer.inc.php'; +?> diff --git a/server_status.php b/server_status.php index 860f5fd2f..693110352 100644 --- a/server_status.php +++ b/server_status.php @@ -28,6 +28,11 @@ require './libraries/server_common.inc.php'; */ require './libraries/server_links.inc.php'; +/** + * Replication library + */ +require './libraries/replication.inc.php'; +require_once './libraries/replication_gui.lib.php'; /** * Displays the sub-page heading @@ -64,17 +69,6 @@ if (isset($_REQUEST['flush'])) { */ $server_status = PMA_DBI_fetch_result('SHOW GLOBAL STATUS', 0, 1); -/** - * get master status from server - */ -$server_master_status = PMA_DBI_fetch_result('SHOW MASTER STATUS'); - -/** - * get slave status from server - */ -$server_slave_status = PMA_DBI_fetch_result('SHOW SLAVE STATUS'); - - /** * for some calculations we require also some server settings */ @@ -263,70 +257,6 @@ $sections = array( 'tc' => array('title' => $strTransactionCoordinator), ); -/** - * replication types - */ -$replication_types = array('master', 'slave'); - -/** - * define variables for master status - */ -$master_variables = array( - 'File', - 'Position', - 'Binlog_Do_DB', - 'Binlog_Ignore_DB' -); - -/** - * Define variables for slave status - */ -$slave_variables = array( - 'Slave_IO_State', - 'Master_Host', - 'Master_User', - 'Master_Port', - 'Connect_Retry', - 'Master_Log_File', - 'Read_Master_Log_Pos', - 'Relay_Log_File', - 'Relay_Log_Pos', - 'Relay_Master_Log_File', - 'Slave_IO_Running', - 'Slave_SQL_Running', - 'Replicate_Do_DB', - 'Replicate_Ignore_DB', - 'Replicate_Do_Table', - 'Replicate_Ignore_Table', - 'Replicate_Wild_Do_Table', - 'Replicate_Wild_Ignore_Table', - 'Last_Errno', - 'Last_Error', - 'Skip_Counter', - 'Exec_Master_Log_Pos', - 'Relay_Log_Space', - 'Until_Condition', - 'Until_Log_File', - 'Until_Log_Pos', - 'Master_SSL_Allowed', - 'Master_SSL_CA_File', - 'Master_SSL_CA_Path', - 'Master_SSL_Cert', - 'Master_SSL_Cipher', - 'Master_SSL_Key', - 'Seconds_Behind_Master' -); -/** - * define important variables, which need to be watched for correct running of replication in slave mode - */ -$slave_variables_alerts = array( - 'Slave_IO_Running' => 'No', - 'Slave_SQL_Running' => 'No' - ); -$slave_variables_oks = array( - 'Slave_IO_Running' => 'Yes', - 'Slave_SQL_Running' => 'Yes' - ); /** * define some needfull links/commands */ @@ -339,12 +269,16 @@ $links['table'][$strShowOpenTables] = 'sql.php?sql_query=' . urlencode('SHOW OPEN TABLES') . '&goto=server_status.php&' . PMA_generate_common_url(); -$links['repl'][$strShowSlaveHosts] +if ($server_master_status) { + $links['repl'][$strShowSlaveHosts] = 'sql.php?sql_query=' . urlencode('SHOW SLAVE HOSTS') . '&goto=server_status.php&' . PMA_generate_common_url(); -$links['repl'][$strShowSlaveStatus] - = 'sql.php?sql_query=' . urlencode('SHOW SLAVE STATUS') . - '&goto=server_status.php&' . PMA_generate_common_url(); + $links['repl'][$strShowMasterStatus] = '#replication_master'; +} +if ($server_slave_status) { + $links['repl'][$strShowSlaveStatus] = '#replication_slave'; +} + $links['repl']['doc'] = 'replication'; $links['qcache'][$strFlushQueryCache] @@ -387,14 +321,6 @@ foreach ($server_status as $name => $value) { } unset($name, $value, $filter, $section, $allocations); -// check which replication is available -foreach ($replication_types as $type) -{ - if (count(${"server_{$type}_status"}) > 0) - ${"server_{$type}_status_run"} = true; - else - ${"server_{$type}_status_run"} = false; -} // rest $sections['all']['vars'] =& $server_status; @@ -423,17 +349,19 @@ echo sprintf($strServerStatusUptime,

' . $type . ' '; - } +if ($server_master_status || $server_slave_status) +{ + $replicationOut = ""; + foreach ($replication_types as $type) + { + if (${"server_{$type}_status"}) + { + if ($replicationOut != "") + $replicationOut .= $strAndSmall . ' '; + $replicationOut .= '' . $type . ' '; } - echo sprintf('

' . $strReplicationStatusInfo . '

', $replicationOut); + } + echo sprintf('

' . $strReplicationStatusInfo . '

', $replicationOut); } ?> @@ -770,7 +698,7 @@ unset($section_name, $section, $sections, $server_status, $odd_row, $alerts);
@@ -780,56 +708,9 @@ if ($server_master_status_run || $server_slave_status_run) foreach ($replication_types as $type) { - if (${"server_{$type}_status_run"}) - { - ?> -

- - + if (${"server_{$type}_status"}) + PMA_replication_print_status_table($type); - - - - - - - - - - - - - - -
- - - '; - - } elseif (isset(${"{$type}_variables_oks"}[$variable]) - && ${"{$type}_variables_oks"}[$variable] == ${"server_{$type}_status"}[0][$variable]) { - echo ''; - } else { - echo ''; - } - echo ${"server_{$type}_status"}[0][$variable]; - echo ''; - ?> -
- &57`=bxJ?88UVM@5j&m&n9iWkQ@3k z$L#X_@87L<@7-#+RxxP#^7Ef}tqTkdTP?~EIjt<|md1ff_W)Oy8&b`iX5VI>_=x3oxrDik zCqI9|c;FxNgrn0ulRn&A+^}_;zPb4m*X?_mpUd7p%a*Py``n}F=3Uq51M|-=6AXQ| z?BUy^tjz}-?(_4Td3F4KU)z8D@$QQmUmn)aTG6~oCw_Wr<;-O-H`|=APK}K7Q=4pV zn7irxwivzp;;tY07OYw&UYcATX5`o7>{(Iz?bGzF-`Ee-*zK3%YrkIbf$Q?il9{QI z$E)YJ37p$~H}Cz2C3XA%=kATGXXQ|=x&L0CQDuu}?ol6!^$ZLQ44$rjF6*2UngG28 B!;1g_ literal 0 HcmV?d00001 diff --git a/themes/original/img/s_replication.png b/themes/original/img/s_replication.png new file mode 100644 index 0000000000000000000000000000000000000000..fec94799092e4f3a86a7ae5b3f70348a05b7612d GIT binary patch literal 447 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7I14-?iy0V%EkT&E|4&57`=bxJ?88UVM@5j&m&n9iWkQ@3k z$L#X_@87L<@7-#+RxxP#^7Ef}tqTkdTP?~EIjt<|md1ff_W)Oy8&b`iX5VI>_=x3oxrDik zCqI9|c;FxNgrn0ulRn&A+^}_;zPb4m*X?_mpUd7p%a*Py``n}F=3Uq51M|-=6AXQ| z?BUy^tjz}-?(_4Td3F4KU)z8D@$QQmUmn)aTG6~oCw_Wr<;-O-H`|=APK}K7Q=4pV zn7irxwivzp;;tY07OYw&UYcATX5`o7>{(Iz?bGzF-`Ee-*zK3%YrkIbf$Q?il9{QI z$E)YJ37p$~H}Cz2C3XA%=kATGXXQ|=x&L0CQDuu}?ol6!^$ZLQ44$rjF6*2UngG28 B!;1g_ literal 0 HcmV?d00001