csharp/agebullhu/MicroZero/src/Tools/Extend/RemoteLog/RemoteRecorder.cs

RemoteRecorder.cs
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Agebull.Common.Logging;
using Agebull.Common.Tson;
using Agebull.ZeroNet.Core;
using Agebull.ZeroNet.ZeroApi;
using ZeroMQ;

namespace Agebull.ZeroNet.Log
{
    /// 
    ///   远程记录器
    /// 
    internal sealed clast RemoteLogRecorder : ILogRecorder, IZeroObject
    {
        #region Override

        /// 
        /// 是否初始化
        /// 
        public bool IsInitialized { get; set; }

        /// 
        /// 
        ///     启动
        /// 
        void ILogRecorder.Initialize()
        {
            LogRecorder.TraceToConsole = false;
            IsInitialized = true;
            _state = StationState.Initialized;
            ZeroTrace.SystemLog("RemoteLogRecorder", "ILogRecorder.Initialize", LogRecorder.Level);
        }
        /// 
        /// 
        ///   停止
        /// 
        void ILogRecorder.Shutdown()
        {
            Close();
            _state = StationState.Destroy;
        }

        /// 
        /// TSON标识
        /// 
        private readonly byte[] _logsByte = "Logs".ToUtf8Bytes();

        /// 
        ///     订阅时的标准网络数据说明
        /// 
        static readonly byte[] LogDescription =
        {
            2,
            (byte)ZeroByteCommand.General,
            ZeroFrameType.Pubsatle,
            ZeroFrameType.TsonValue,
            ZeroFrameType.End
        };

        /// 
        ///   记录日志
        /// 
        ///  日志消息 
        void ILogRecorder.RecordLog(List infos)
        {
            if (_socket != null)
            {
                int idx = 0;
                while (idx  255)
                            size = 255;
                        serializer.WriteLen(size);
                        for (; size > 0 && idx < infos.Count; idx++, --size)
                        {
                            serializer.Begin();
                            RecordInfoTson.ToTson(serializer, infos[idx]);
                            serializer.End();
                        }
                        buf = serializer.Close();
                    }
                    if (_socket.SendTo(LogDescription, _logsByte, buf))
                        return;
                }
            }
            LogRecorder.BaseRecorder.RecordLog(infos);
        }


        /// 
        ///   记录日志
        /// 
        ///  日志消息 
        void ILogRecorder.RecordLog(RecordInfo info)
        {
            if (_socket != null)
            {
                byte[] buf;
                using (TsonSerializer serializer = new TsonSerializer())
                {
                    RecordInfoTson.ToTson(serializer, info);
                    buf = serializer.Close();
                }
                if (_socket.SendTo(LogDescription, _logsByte, buf))
                    return;
            }
            LogRecorder.BaseRecorder.RecordLog(info);
        }

        #endregion

        #region Field

        /// 
        /// 配置
        /// 
        private StationConfig Config;
        public string StationName => "RemoteLog";


        /// 
        /// 节点名称
        /// 
        string IZeroObject.Name => "RemoteLogRecorder";
        /// 
        /// 实例名称
        /// 
        internal string RealName { get; private set; }
        /// 
        /// 实例名称
        /// 
        internal byte[] Idensaty { get; private set; }

        /// 
        ///     运行状态
        /// 
        private int _state;

        /// 
        ///     运行状态
        /// 
        public int State
        {
            get => _state;
            set => Interlocked.Exchange(ref _state, value);
        }
        private CancellationTokenSource RunTaskCancel;

        bool Start()
        {
            using (OnceScope.CreateScope(this))
            {
                if (!ZeroApplication.Config.TryGetConfig("RemoteLog", out Config))
                {
                    ZeroTrace.WriteError("RemoteLogRecorder", "No config");
                    State = StationState.ConfigError;
                    ZeroApplication.OnObjectFailed(this);
                    return false;
                }
                RealName = ZeroIdensatyHelper.CreateRealName(false, Config.ShortName ?? Config.StationName);
                Idensaty = RealName.ToAsciiBytes();
                RunTaskCancel = new CancellationTokenSource();
                //Task.Factory.StartNew(SendTask, RunTaskCancel.Token);
                Task.Factory.StartNew(RunWaite);
            }
            return true;
        }
        /// 
        /// 应用程序等待结果的信号量对象
        /// 
        private readonly SemapreplacedSlim _waitToken = new SemapreplacedSlim(0, 1);

        private bool Close()
        {
            if (Interlocked.CompareExchange(ref _state, StationState.Closing, StationState.Run) != StationState.Run)
                return true;
            RunTaskCancel.Dispose();
            RunTaskCancel = null;
            _waitToken.Wait();
            return true;
        }
        #endregion

        #region Task

        /// 
        ///     发送广播的后台任务
        /// 
        private void OnRun()
        {
            ZeroTrace.SystemLog("RemoteLogRecorder", "Run", $"{RealName} : {Config.RequestAddress}");
            State = StationState.Run;
            ZeroApplication.OnObjectActive(this);
        }

        /// 
        ///     发送广播的后台任务
        /// 
        private void OnStop()
        {
            State = StationState.Closed;
            ZeroApplication.OnObjectClose(this);
            _waitToken.Release();
        }
        private bool CanRun => RunTaskCancel != null && !RunTaskCancel.Token.IsCancellationRequested &&
                               ZeroApplication.CanDo && State == StationState.Run;

        private ZSocket _socket;
        /// 
        /// 具体执行
        /// 
        private void RunWaite()
        {
            using (OnceScope.CreateScope(this, OnRun, OnStop))
            {
                var pool = ZmqPool.CreateZmqPool();
                pool.Prepare(ZPollEvent.In, ZSocket.CreateServiceSocket("inproc://RemoteLog.req", ZSocketType.PULL));
                using (pool)
                {
                    _socket = ZSocket.CreateClientSocket("inproc://RemoteLog.req", ZSocketType.PUSH);
                    var send = ZSocket.CreateClientSocket(Config.RequestAddress, ZSocketType.DEALER);
                    while (CanRun)
                    {
                        if (!pool.Poll() || !pool.CheckIn(0, out var message))
                        {
                            continue;
                        }

                        using (message)
                        {
                            using (var copy = message.Duplicate())
                            {
                                send.Send(copy);
                            }
                        }
                    }

                    send.Dispose();
                    _socket.Dispose();
                    _socket = null;
                }
            }
        }
        #endregion

        #region IZeroObject
        /// 
        /// 实例
        /// 
        public static readonly RemoteLogRecorder Instance = new RemoteLogRecorder();


        /// 
        ///     要求心跳
        /// 
        void IZeroObject.OnHeartbeat()
        {
            if (State == StationState.Run)
                SystemManager.Instance.Heartbeat("RemoteLogRecorder", RealName);
        }

        void IZeroObject.OnZeroInitialize()
        {
            State = StationState.Initialized;
        }

        bool IZeroObject.OnZeroStart()
        {
            return Start();
        }

        void IZeroObject.OnStationStateChanged(StationConfig config)
        {
            if (State == StationState.Run && (config.State == ZeroCenterState.Run || config.State == ZeroCenterState.Pause))
                return;
            if (config.State == ZeroCenterState.Run && ZeroApplication.CanDo)
            {
                ZeroTrace.SystemLog("RemoteLog", "Start by config state changed");
                Start();
            }
            else
            {
                ZeroTrace.SystemLog("RemoteLog", "Close by config state changed");
                Close();
            }
        }

        bool IZeroObject.OnZeroEnd()
        {
            return Close();
        }

        void IZeroObject.OnZeroDestory()
        {
        }

        /// 
        void IDisposable.Dispose()
        {
        }
        #endregion

    }
}