//============================================================== // Copyright (C) 2020 Inc. All rights reserved. // //============================================================== // Create by 种道洋 at 2020/8/17 16:34:14. // Version 1.0 // 种道洋 //============================================================== using Cdy.Tag; using DBRuntime.RDDC; using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml.Linq; namespace DBRuntime { public class RDDCManager { #region ... Variables ... /// /// /// public static RDDCManager Manager = new RDDCManager(); private RDDCDataService mServer; private RDDCClient mClient; private DataSync mSync; private bool mIsInited = false; private object mLockObj = new object(); private WorkState mCurrentState = WorkState.Unknow; private bool mIsClosed = false; private Thread mScanThread; #endregion ...Variables... #region ... Events ... #endregion ...Events... #region ... Constructor... /// /// /// public RDDCManager() { } #endregion ...Constructor... #region ... Properties ... /// /// /// public bool EnableRDDC { get; set; } /// /// 当前状态 /// public WorkState CurrentState { get { return mCurrentState; } set { mCurrentState = value; if (mSync != null) { if (value == WorkState.Standby) { mSync.Enable = true; } else { mSync.Enable = false; } } } } /// /// /// public DateTime StartTime { get; set; } /// /// 服务端口 /// public int Port { get; set; } /// /// 备机IP /// public string RemoteIp { get; set; } /// /// /// public Func SwitchWorkStateAction { get; set; } #endregion ...Properties... #region ... Methods ... /// /// /// /// public void Load(string databaseName) { string spath = PathHelper.helper.GetDataPath(databaseName, "RDDC.cfg"); if(System.IO.File.Exists(spath)) { XElement xx = XElement.Load(spath); EnableRDDC = bool.Parse(xx.Attribute("Enable")?.Value); this.Port = int.Parse(xx.Attribute("Port")?.Value); this.RemoteIp = xx.Attribute("RemoteIp")?.Value; } } /// /// /// public void Start() { mIsInited = false; if (EnableRDDC) { mServer = new RDDCDataService(); mServer.Start(Port); mClient = new RDDCClient(); mClient.Connect(RemoteIp, Port); mClient.PropertyChanged += MClient_PropertyChanged; mSync = new DataSync() { Client = mClient }; mSync.Start(); mScanThread = new Thread(ThreadPro); mScanThread.IsBackground = true; mScanThread.Start(); CheckWorkState(); } else { CurrentState = WorkState.Primary; } mIsInited = true; } /// /// /// /// /// private void MClient_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if(mIsInited) { Task.Run(ProcessClientConnectChanged); } } /// /// /// public void Stop() { mIsClosed = true; mSync.Stop(); mServer.Stop(); mClient.PropertyChanged -= MClient_PropertyChanged; mClient.Close(); } private void ThreadPro() { while (!mIsClosed) { if (mClient.NeedReConnected) { //mClient.Connect(RemoteIp,Port); //Thread.Sleep(1000); } else if(mClient.IsConnected) { CheckRunWorkState(); Thread.Sleep(1000); } } } private void CheckRunWorkState() { try { var state = mClient.GetWorkState(); if (state.HasValue) { if (state.Value == WorkState.Primary && this.CurrentState == WorkState.Primary) { var time = mClient.GetStartTime(); var cc = time > this.StartTime ? WorkState.Primary : WorkState.Standby; if (cc == WorkState.Standby) { SwitchTo(cc); } } else if (state.Value == WorkState.Standby && this.CurrentState == WorkState.Standby) { var time = mClient.GetStartTime(); var cc = time > this.StartTime ? WorkState.Primary : WorkState.Standby; if (cc == WorkState.Primary) { SwitchTo(cc); } } } } catch { } } /// /// /// private void ProcessClientConnectChanged() { if (!mClient.IsConnected) { if(CurrentState != WorkState.Primary) { SwitchTo(WorkState.Primary); } } else { var state = mClient.GetWorkState(); if ((state == WorkState.Primary && this.CurrentState == WorkState.Primary) || (state == WorkState.Standby && this.CurrentState == WorkState.Standby)) { var time = mClient.GetStartTime(); var ss = time > this.StartTime ? WorkState.Primary : WorkState.Standby; SwitchTo(ss); } } } /// /// /// private void CheckWorkState() { int count = 0; while(!mClient.IsConnected) { Thread.Sleep(100); count++; if (count > 30) break; } if(!mClient.IsConnected) { CurrentState = WorkState.Primary; } else { var time = mClient.GetStartTime(); if(time!=null) { CurrentState = time > this.StartTime ? WorkState.Primary : WorkState.Standby; } else { CurrentState = WorkState.Standby; } } LoggerService.Service.Info("RDDCManager", "running in " + CurrentState.ToString(), ConsoleColor.Cyan); } /// /// 手动切换工作状态 /// /// public bool ManualSwitchTo(WorkState state) { if(mClient.IsConnected) { if (state == WorkState.Standby) { if(mClient.SwitchToPrimary(60000).Value) { return SwitchTo(WorkState.Standby); } else { return false; } } else { if(mClient.SwitchToStandby(60000).Value) { return SwitchTo(WorkState.Primary); } else { return false; } } } else { if(state == WorkState.Standby) { LoggerService.Service.Warn("RDDCManager", "remote is offline,local machine must be primary!"); return false; } else { return SwitchTo(state); } } } /// /// /// /// /// public bool SwitchTo(WorkState state) { if (CurrentState == WorkState.Switching) return true; LoggerService.Service.Warn("RDDCManager", "will switch to "+ state); lock (mLockObj) { var olds = CurrentState; CurrentState = WorkState.Switching; if (SwitchWorkStateAction != null) { if (SwitchWorkStateAction(state)) { CurrentState = state; return true; } else { CurrentState = olds; return false; } } CurrentState = state; return true; } } #endregion ...Methods... #region ... Interfaces ... #endregion ...Interfaces... } }