You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
8.4 KiB

4 years ago
  1. #if MYSQL_6_10
  2. // Copyright ?2014, 2018, Oracle and/or its affiliates. All rights reserved.
  3. //
  4. // MySQL Connector/NET is licensed under the terms of the GPLv2
  5. // <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
  6. // MySQL Connectors. There are special exceptions to the terms and
  7. // conditions of the GPLv2 as it is applied to this software, see the
  8. // FLOSS License Exception
  9. // <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
  10. //
  11. // This program is free software; you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published
  13. // by the Free Software Foundation; version 2 of the License.
  14. //
  15. // This program is distributed in the hope that it will be useful, but
  16. // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  18. // for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License along
  21. // with this program; if not, write to the Free Software Foundation, Inc.,
  22. // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. using System;
  24. using System.Collections.Generic;
  25. using System.ComponentModel;
  26. using System.Text;
  27. namespace Externals.MySql.Data.MySqlClient.Replication
  28. {
  29. /// <summary>
  30. /// Base class used to implement load balancing features.
  31. /// </summary>
  32. internal abstract class ReplicationServerGroup
  33. {
  34. /// <summary>
  35. /// List of servers available for replication.
  36. /// </summary>
  37. protected List<ReplicationServer> servers = new List<ReplicationServer>();
  38. /// <param name="name">The group name.</param>
  39. /// <param name="retryTime">The number of seconds to perform a retry.</param>
  40. public ReplicationServerGroup(string name, int retryTime)
  41. {
  42. Servers = servers;
  43. Name = name;
  44. RetryTime = retryTime;
  45. }
  46. /// <summary>
  47. /// Gets the group name.
  48. /// </summary>
  49. public string Name { get; protected set; }
  50. /// <summary>
  51. /// Gets the retry time between connections to failed servers.
  52. /// </summary>
  53. public int RetryTime { get; protected set; }
  54. /// <summary>
  55. /// Gets the server list in the group.
  56. /// </summary>
  57. protected IList<ReplicationServer> Servers { get; private set; }
  58. /// <summary>
  59. /// Adds a server into the group.
  60. /// </summary>
  61. /// <param name="name">The server name.</param>
  62. /// <param name="isMaster">A flag indicating if the server to add is master or slave.</param>
  63. /// <param name="connectionString">The connection string used by this server.</param>
  64. /// <returns>A <see cref="ReplicationServer"/> object representing the recently added object.</returns>
  65. internal protected ReplicationServer AddServer(string name, bool isMaster, string connectionString)
  66. {
  67. ReplicationServer server = new ReplicationServer(name, isMaster, connectionString);
  68. servers.Add(server);
  69. return server;
  70. }
  71. /// <summary>
  72. /// Removes a server from the group.
  73. /// </summary>
  74. /// <param name="name">The server name.</param>
  75. internal protected void RemoveServer(string name)
  76. {
  77. ReplicationServer serverToRemove = GetServer(name);
  78. if (serverToRemove == null)
  79. throw new MySqlException(String.Format(Resources.ReplicationServerNotFound, name));
  80. servers.Remove(serverToRemove);
  81. }
  82. /// <summary>
  83. /// Gets a server by name.
  84. /// </summary>
  85. /// <param name="name">The server name.</param>
  86. /// <returns>The replication server.</returns>
  87. internal protected ReplicationServer GetServer(string name)
  88. {
  89. foreach (var server in servers)
  90. if (String.Compare(name, server.Name, StringComparison.OrdinalIgnoreCase) == 0) return server;
  91. return null;
  92. }
  93. /// <summary>
  94. /// Must be implemented. Defines the next server for a custom load balancing implementation.
  95. /// </summary>
  96. /// <param name="isMaster">Defines if the server to return is a master or any.</param>
  97. /// <returns>The next server based on the load balancing implementation.
  98. /// Null if no available server is found.
  99. /// </returns>
  100. internal protected abstract ReplicationServer GetServer(bool isMaster);
  101. /// <summary>
  102. /// Defines the next server for a custom load balancing implementation.
  103. /// </summary>
  104. /// <param name="isMaster">Defines if the server to return is a master or any.</param>
  105. /// <param name="settings">Currently not being used.</param>
  106. /// <returns>The next server based on the load balancing implementation.
  107. /// Null if no available server is found.
  108. /// </returns>
  109. internal protected virtual ReplicationServer GetServer(bool isMaster, MySqlConnectionStringBuilder settings)
  110. {
  111. return GetServer(isMaster);
  112. }
  113. /// <summary>
  114. /// Handles a failed connection to a server.
  115. /// </summary>
  116. /// <param name="server">The failed server.</param>
  117. /// <remarks>This method can be overrided to implement a custom failover handling.</remarks>
  118. internal protected virtual void HandleFailover(ReplicationServer server)
  119. {
  120. BackgroundWorker worker = new BackgroundWorker();
  121. worker.DoWork += delegate (object sender, DoWorkEventArgs e)
  122. {
  123. bool isRunning = false;
  124. ReplicationServer server1 = e.Argument as ReplicationServer;
  125. #if !NETSTANDARD1_3
  126. System.Timers.Timer timer = new System.Timers.Timer(RetryTime * 1000.0);
  127. System.Timers.ElapsedEventHandler elapsedEvent = delegate (object sender1, System.Timers.ElapsedEventArgs e1)
  128. {
  129. if (isRunning) return;
  130. try
  131. {
  132. isRunning = true;
  133. using (MySqlConnection connectionFailed = new MySqlConnection(server.ConnectionString))
  134. {
  135. connectionFailed.Open();
  136. server1.IsAvailable = true;
  137. timer.Stop();
  138. }
  139. }
  140. catch
  141. {
  142. MySqlTrace.LogWarning(0,
  143. string.Format(Resources.Replication_ConnectionAttemptFailed, server1.Name));
  144. }
  145. finally
  146. {
  147. isRunning = false;
  148. }
  149. };
  150. timer.Elapsed += elapsedEvent;
  151. timer.Start();
  152. elapsedEvent(sender, null);
  153. #else
  154. Windows.UI.Xaml.DispatcherTimer timer = new Windows.UI.Xaml.DispatcherTimer();
  155. TimeSpan ts = new TimeSpan(RetryTime * 1000);
  156. System.EventHandler<object> elapsedEvent = (TickSender, TickEventArgs) =>
  157. {
  158. if (isRunning) return;
  159. try
  160. {
  161. isRunning = true;
  162. using (MySqlConnection connectionFailed = new MySqlConnection(server.ConnectionString))
  163. {
  164. connectionFailed.Open();
  165. server1.IsAvailable = true;
  166. timer.Stop();
  167. }
  168. }
  169. catch
  170. {
  171. MySqlTrace.LogWarning(0,
  172. string.Format(Properties.Resources.Replication_ConnectionAttemptFailed, server1.Name));
  173. }
  174. finally
  175. {
  176. isRunning = false;
  177. }
  178. };
  179. timer.Tick += elapsedEvent;
  180. elapsedEvent(sender, null);
  181. timer.Start();
  182. #endif
  183. };
  184. worker.RunWorkerAsync(server);
  185. }
  186. /// <summary>
  187. /// Handles a failed connection to a server.
  188. /// </summary>
  189. /// <param name="server">The failed server.</param>
  190. /// <param name="exception">The exception that caused the failover.</param>
  191. internal protected virtual void HandleFailover(ReplicationServer server, Exception exception)
  192. {
  193. HandleFailover(server);
  194. }
  195. }
  196. }
  197. #endif