using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Serialization;
using Stardust.Models;
using XCode;
using XCode.Membership;
namespace Stardust.Data.Nodes
{
/// <summary>节点在线</summary>
public partial class NodeOnline : Entity<NodeOnline>
{
#region 对象操作
static NodeOnline()
{
var df = Meta.Factory.AdditionalFields;
df.Add(__.PingCount);
Meta.Modules.Add<TimeModule>();
Meta.Modules.Add<IPModule>();
var sc = Meta.SingleCache;
sc.FindSlaveKeyMethod = k => Find(_.SessionID == k);
sc.GetSlaveKeyMethod = e => e.SessionID;
}
/// <summary>校验数据</summary>
/// <param name="isNew"></param>
public override void Valid(Boolean isNew)
{
// 截取部分进程字段,避免过长无法保存
if (Processes != null && Processes.Length > 2000) Processes = Processes.Substring(0, 1999);
if (MACs != null && MACs.Length > 200) MACs = MACs.Substring(0, 1999);
//if (COMs != null && COMs.Length > 200) COMs = COMs.Substring(0, 199);
base.Valid(isNew);
}
#endregion
#region 扩展属性
/// <summary>节点</summary>
[XmlIgnore, ScriptIgnore]
public Node Node => Extends.Get(nameof(Node), k => Node.FindByID(NodeID));
/// <summary>节点</summary>
[Map(__.NodeID)]
public String NodeName => Node + "";
/// <summary>省份</summary>
[XmlIgnore, IgnoreDataMember]
public Area Province => Extends.Get(nameof(Province), k => Area.FindByID(ProvinceID));
/// <summary>省份名</summary>
[Map(__.ProvinceID)]
public String ProvinceName => Province + "";
/// <summary>城市</summary>
[XmlIgnore, IgnoreDataMember]
public Area City => Extends.Get(nameof(City), k => Area.FindByID(CityID));
/// <summary>城市名</summary>
[Map(__.CityID)]
public String CityName => City?.Path;
#endregion
#region 扩展查询
/// <summary>根据会话查找</summary>
/// <param name="deviceid">会话</param>
/// <returns></returns>
public static NodeOnline FindByNodeId(Int32 deviceid) => Find(__.NodeID, deviceid);
/// <summary>根据会话查找</summary>
/// <param name="sessionid">会话</param>
/// <param name="cache">是否走缓存</param>
/// <returns></returns>
public static NodeOnline FindBySessionID(String sessionid, Boolean cache = true)
{
if (!cache) return Find(_.SessionID == sessionid);
return Meta.SingleCache.GetItemWithSlaveKey(sessionid) as NodeOnline;
}
/// <summary>根据节点查找所有在线记录</summary>
/// <param name="nodeId"></param>
/// <returns></returns>
public static IList<NodeOnline> FindAllByNodeId(Int32 nodeId) => FindAll(_.NodeID == nodeId);
#endregion
#region 高级查询
/// <summary>查询满足条件的记录集,分页、排序</summary>
/// <param name="nodeId">节点</param>
/// <param name="provinceId">省份</param>
/// <param name="cityId">城市</param>
/// <param name="category">类别</param>
/// <param name="start">开始时间</param>
/// <param name="end">结束时间</param>
/// <param name="key">关键字</param>
/// <param name="page">分页排序参数,同时返回满足条件的总记录数</param>
/// <returns>实体集</returns>
public static IList<NodeOnline> Search(Int32 nodeId, Int32 provinceId, Int32 cityId, String category, DateTime start, DateTime end, String key, PageParameter page)
{
var exp = new WhereExpression();
if (nodeId >= 0) exp &= _.NodeID == nodeId;
if (provinceId >= 0) exp &= _.ProvinceID == provinceId;
if (cityId >= 0) exp &= _.CityID == cityId;
if (!category.IsNullOrEmpty()) exp &= _.Category == category;
exp &= _.CreateTime.Between(start, end);
if (!key.IsNullOrEmpty()) exp &= _.Name.Contains(key) | _.Data.Contains(key) | _.SessionID.Contains(key);
return FindAll(exp, page);
}
/// <summary>根据产品,分组统计在线数</summary>
/// <returns></returns>
public static IDictionary<Int32, Int32> SearchGroupByProvince()
{
var list = FindAll(_.ProvinceID.GroupBy(), null, _.ID.Count() & _.ProvinceID);
return list.ToDictionary(e => e.ProvinceID, e => e.ID);
}
#endregion
#region 业务操作
/// <summary>根据编码查询或添加</summary>
/// <param name="sessionid"></param>
/// <returns></returns>
public static NodeOnline GetOrAdd(String sessionid) => GetOrAdd(sessionid, FindBySessionID, k => new NodeOnline { SessionID = k });
/// <summary>删除过期,指定过期时间</summary>
/// <param name="expire">超时时间,秒</param>
/// <returns></returns>
public static IList<NodeOnline> ClearExpire(TimeSpan expire)
{
if (Meta.Count == 0) return null;
// 10分钟不活跃将会被删除
var exp = _.UpdateTime < DateTime.Now.Subtract(expire);
var list = FindAll(exp, null, null, 0, 0);
list.Delete();
return list;
}
/// <summary>更新并保存在线状态</summary>
/// <param name="di"></param>
/// <param name="pi"></param>
/// <param name="token"></param>
/// <param name="ip"></param>
public void Save(NodeInfo di, PingInfo pi, String token, String ip)
{
var olt = this;
if (di != null)
{
olt.Fill(di);
olt.LocalTime = di.Time.ToLocalTime();
olt.MACs = di.Macs;
//olt.COMs = di.COMs;
}
else
{
olt.Fill(pi);
olt.CreateData(pi, ip);
}
olt.Token = token;
olt.PingCount++;
olt.UpdateIP = ip;
// 5秒内直接保存
if (olt.CreateTime.AddSeconds(5) > DateTime.Now)
olt.Save();
else
olt.SaveAsync();
}
/// <summary>填充节点信息</summary>
/// <param name="di"></param>
public void Fill(NodeInfo di)
{
var online = this;
online.LocalTime = di.Time.ToLocalTime();
online.MACs = di.Macs;
//online.COMs = di.COMs;
online.IP = di.IP;
if (di.AvailableMemory > 0) online.AvailableMemory = (Int32)(di.AvailableMemory / 1024 / 1024);
if (di.AvailableFreeSpace > 0) online.AvailableFreeSpace = (Int32)(di.AvailableFreeSpace / 1024 / 1024);
}
/// <summary>填充在线节点信息</summary>
/// <param name="inf"></param>
private void Fill(PingInfo inf)
{
var olt = this;
if (inf.AvailableMemory > 0) olt.AvailableMemory = (Int32)(inf.AvailableMemory / 1024 / 1024);
if (inf.AvailableFreeSpace > 0) olt.AvailableFreeSpace = (Int32)(inf.AvailableFreeSpace / 1024 / 1024);
if (inf.CpuRate > 0) olt.CpuRate = inf.CpuRate;
if (inf.Temperature > 0) olt.Temperature = inf.Temperature;
if (inf.Battery > 0) olt.Battery = inf.Battery;
if (inf.UplinkSpeed > 0) olt.UplinkSpeed = (Int64)inf.UplinkSpeed;
if (inf.DownlinkSpeed > 0) olt.DownlinkSpeed = (Int64)inf.DownlinkSpeed;
if (inf.ProcessCount > 0) olt.ProcessCount = inf.ProcessCount;
if (inf.TcpConnections > 0) olt.TcpConnections = inf.TcpConnections;
if (inf.TcpTimeWait > 0) olt.TcpTimeWait = inf.TcpTimeWait;
if (inf.TcpCloseWait > 0) olt.TcpCloseWait = inf.TcpCloseWait;
if (inf.Uptime > 0) olt.Uptime = inf.Uptime;
if (inf.Delay > 0) olt.Delay = inf.Delay;
var dt = inf.Time.ToDateTime().ToLocalTime();
if (dt.Year > 2000)
{
olt.LocalTime = dt;
olt.Offset = (Int32)Math.Round((dt - DateTime.Now).TotalSeconds);
}
if (!inf.Processes.IsNullOrEmpty()) olt.Processes = inf.Processes;
if (!inf.Macs.IsNullOrEmpty()) olt.MACs = inf.Macs;
//if (!inf.COMs.IsNullOrEmpty()) olt.COMs = inf.COMs;
if (!inf.IP.IsNullOrEmpty()) olt.IP = inf.IP;
//olt.Data = inf.ToJson();
var dic = inf.ToDictionary();
dic.Remove("Processes");
olt.Data = dic.ToJson();
}
private void CreateData(PingInfo inf, String ip)
{
var olt = this;
var dt = inf.Time.ToDateTime().ToLocalTime();
// 插入节点数据
var data = new NodeData
{
NodeID = olt.NodeID,
Name = olt.Name,
AvailableMemory = olt.AvailableMemory,
AvailableFreeSpace = olt.AvailableFreeSpace,
CpuRate = inf.CpuRate,
Temperature = inf.Temperature,
Battery = inf.Battery,
UplinkSpeed = (Int64)inf.UplinkSpeed,
DownlinkSpeed = (Int64)inf.DownlinkSpeed,
ProcessCount = inf.ProcessCount,
TcpConnections = inf.TcpConnections,
TcpTimeWait = inf.TcpTimeWait,
TcpCloseWait = inf.TcpCloseWait,
Uptime = inf.Uptime,
Delay = inf.Delay,
LocalTime = dt,
Offset = olt.Offset,
CreateIP = ip,
Creator = Environment.MachineName,
};
data.SaveAsync();
}
#endregion
}
}
|