1 /* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 /** 24 @file clone_handler.h 25 Clone handler interface to access clone plugin 26 */ 27 28 #ifndef CLONE_HANDLER_INCLUDED 29 #define CLONE_HANDLER_INCLUDED 30 31 #include <atomic> 32 #include <string> 33 34 #include "my_io.h" 35 #include "mysql.h" 36 #include "sql/sql_plugin_ref.h" // plugin_ref 37 38 class THD; 39 class Srv_session; 40 struct Mysql_clone; 41 struct MYSQL_SOCKET; 42 43 /** 44 Number of PSI_statement_info instruments 45 for clone statements. 46 */ 47 48 #define CLONE_PSI_STATEMENT_COUNT 5 49 50 /** 51 Clone plugin handler to convenient way to. Takes 52 */ 53 class Clone_handler { 54 public: 55 /** Constructor: Initialize plugin name */ Clone_handler(const char * plugin_name_arg)56 Clone_handler(const char *plugin_name_arg) : m_plugin_handle(nullptr) { 57 m_plugin_name.assign(plugin_name_arg); 58 } 59 60 /** Initialize plugin handle 61 @return error code */ 62 int init(); 63 64 /** Clone handler interface for local clone. 65 @param[in] thd server thread handle 66 @param[in] data_dir cloned data directory 67 @return error code */ 68 int clone_local(THD *thd, const char *data_dir); 69 70 /** Clone handler interface for remote clone client. 71 @param[in] thd server thread handle 72 @param[in] remote_host remote host IP address 73 @param[in] remote_port remote server port 74 @param[in] remote_user remote user name 75 @param[in] remote_passwd remote user's password 76 @param[in] data_dir cloned data directory 77 @param[in] ssl_mode remote connection ssl mode 78 @return error code */ 79 int clone_remote_client(THD *thd, const char *remote_host, uint remote_port, 80 const char *remote_user, const char *remote_passwd, 81 const char *data_dir, enum mysql_ssl_mode ssl_mode); 82 83 /** Clone handler interface for remote clone server. 84 @param[in] thd server thread handle 85 @param[in] socket network socket to remote client 86 @return error code */ 87 int clone_remote_server(THD *thd, MYSQL_SOCKET socket); 88 89 /** Get donor error and message for ER_CLONE_DONOR error. 90 @param[in] session server session 91 @param[out] error donor error number 92 @param[out] message error message 93 @return true, iff successful. */ 94 static bool get_donor_error(Srv_session *session, int &error, 95 const char *&message); 96 97 /** @return false only if no user data is dropped yet. */ is_data_dropped()98 static bool is_data_dropped() { return (s_is_data_dropped); } 99 100 /** Must set before dropping any user data. */ set_drop_data()101 static void set_drop_data() { s_is_data_dropped.store(true); } 102 103 /** @return true, if clone provisioning in progress. */ is_provisioning()104 static bool is_provisioning() { return (s_provision_in_progress > 0); } 105 106 /** @return true, if ordered commit should be forced. Currently 107 clone would force ordered commit at end while blocking XA operations */ need_commit_order()108 static bool need_commit_order() { return (s_xa_block_op.load()); } 109 110 /* Initialize XA counters and mutex. */ 111 static void init_xa(); 112 113 /* Destroy XA mutex. */ 114 static void uninit_xa(); 115 116 /* RAII guard for XA operation synchronization with clone. */ 117 struct XA_Operation { 118 /** Constructor: mark XA operation begin. 119 @param[in] thd session thread */ 120 explicit XA_Operation(THD *thd); 121 122 /** Destructor: mark XA operation end. */ 123 ~XA_Operation(); 124 125 /** Disable copy construction */ 126 XA_Operation(XA_Operation const &) = delete; 127 128 /** Disable assignment */ 129 XA_Operation &operator=(XA_Operation const &) = delete; 130 131 private: 132 /** Session thread holding the guard. */ 133 THD *m_thd; 134 }; 135 136 /* RAII guard for blocking and unblocking XA operations. */ 137 struct XA_Block { 138 /** Constructor: Block all XA operations. 139 @param[in] thd session thread */ 140 explicit XA_Block(THD *thd); 141 142 /** Destructor: unblock XA operations. */ 143 ~XA_Block(); 144 145 /** Disable copy construction */ 146 XA_Block(XA_Block const &) = delete; 147 148 /** Disable assignment */ 149 XA_Block &operator=(XA_Block const &) = delete; 150 151 /** @return true, if XA blocking is unsuccessful. */ 152 bool failed() const; 153 154 private: 155 /** If blocking is successful and there is no XA operations. */ 156 bool m_success; 157 }; 158 159 private: 160 /** Block new active XA operations and wait for existing ones to complete. 161 @param[in] thd session thread */ 162 static bool block_xa_operation(THD *thd); 163 164 /** Unblock waiting XA operations. */ 165 static void unblock_xa_operation(); 166 167 /** Increment XA operation count and wait if blocked by clone. 168 @param[in] thd session thread */ 169 static void begin_xa_operation(THD *thd); 170 171 /** Decrement XA operation count. */ 172 static void end_xa_operation(); 173 174 /** Validate clone data directory and convert to os format 175 @param[in] in_dir user specified clone directory 176 @param[out] out_dir data directory in native os format 177 @return error code */ 178 int validate_dir(const char *in_dir, char *out_dir); 179 180 private: 181 /** Number of XA operations (prepare/commit/rollback) in progress. */ 182 static std::atomic<int> s_xa_counter; 183 184 /** Set when clone blocks XA operations. XA operations currently are 185 not ordered between binlog and SE and needs to be synchronized for clone. */ 186 static std::atomic<bool> s_xa_block_op; 187 188 /** True if clone provisioning in progress. */ 189 static std::atomic<int> s_provision_in_progress; 190 191 /** True, if any user data is dropped by clone. */ 192 static std::atomic<bool> s_is_data_dropped; 193 194 /** Mutex to synchronize blocking XA operation. */ 195 static mysql_mutex_t s_xa_mutex; 196 197 /** Clone plugin name */ 198 std::string m_plugin_name; 199 200 /** Clone plugin handle */ 201 Mysql_clone *m_plugin_handle; 202 }; 203 204 /** Check if the clone plugin is installed and lock. If the plugin is ready, 205 return the handler to caller. 206 @param[in] thd server thread handle 207 @param[out] plugin plugin reference 208 @return clone handler on success otherwise NULL */ 209 Clone_handler *clone_plugin_lock(THD *thd, plugin_ref *plugin); 210 211 /** Unlock the clone plugin. 212 @param[in] thd server thread handle 213 @param[out] plugin plugin reference */ 214 void clone_plugin_unlock(THD *thd, plugin_ref plugin); 215 216 #endif /* CLONE_HANDLER_INCLUDED */ 217