//==============================================================
// 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...
}
}