NewLife/NewLife.Remoting

增加采集 FreeMemory,在Linux上表示空闲内存,具有较大意义
智能大石头 authored at 2025-12-12 15:03:39
86631c2
Tree
1 Parent(s) e0af3d6
Summary: 13 changed files with 149 additions and 22 deletions.
Modified +1 -0
Modified +6 -0
Modified +1 -1
Modified +1 -1
Modified +2 -6
Modified +3 -2
Modified +12 -1
Modified +38 -0
Modified +27 -2
Modified +2 -1
Modified +53 -5
Modified +1 -1
Modified +2 -2
Modified +1 -0
diff --git a/NewLife.Remoting/Clients/ClientBase.cs b/NewLife.Remoting/Clients/ClientBase.cs
index 7fd598d..b3e4ecd 100644
--- a/NewLife.Remoting/Clients/ClientBase.cs
+++ b/NewLife.Remoting/Clients/ClientBase.cs
@@ -839,6 +839,7 @@ public abstract class ClientBase : DisposeBase, IApiClient, ICommandClient, IEve
 
             req.Memory = mi.Memory;
             req.AvailableMemory = mi.AvailableMemory;
+            req.FreeMemory = mi.FreeMemory;
             req.TotalSize = (UInt64)(driveInfo?.TotalSize ?? 0);
             req.AvailableFreeSpace = (UInt64)(driveInfo?.AvailableFreeSpace ?? 0);
             req.CpuRate = Math.Round(mi.CpuRate, 3);
Modified +6 -0
diff --git a/NewLife.Remoting/Models/PingRequest.cs b/NewLife.Remoting/Models/PingRequest.cs
index 28c106b..d485928 100644
--- a/NewLife.Remoting/Models/PingRequest.cs
+++ b/NewLife.Remoting/Models/PingRequest.cs
@@ -22,6 +22,9 @@ public interface IPingRequest2 : IPingRequest
     /// <summary>可用内存大小</summary>
     UInt64 AvailableMemory { get; set; }
 
+    /// <summary>空闲内存大小。在Linux上空闲内存不一定可用,部分作为缓存</summary>
+    UInt64 FreeMemory { get; set; }
+
     /// <summary>磁盘大小。应用所在盘</summary>
     UInt64 TotalSize { get; set; }
 
@@ -60,6 +63,9 @@ public class PingRequest : IPingRequest, IPingRequest2
     /// <summary>可用内存大小</summary>
     public UInt64 AvailableMemory { get; set; }
 
+    /// <summary>空闲内存大小。在Linux上空闲内存不一定可用,部分作为缓存</summary>
+    public UInt64 FreeMemory { get; set; }
+
     /// <summary>磁盘大小。应用所在盘</summary>
     public UInt64 TotalSize { get; set; }
 
Modified +1 -1
diff --git a/NewLife.Remoting/NewLife.Remoting.csproj b/NewLife.Remoting/NewLife.Remoting.csproj
index 0ad57ea..b2e9b78 100644
--- a/NewLife.Remoting/NewLife.Remoting.csproj
+++ b/NewLife.Remoting/NewLife.Remoting.csproj
@@ -54,7 +54,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Core" Version="11.9.2025.1112" />
+    <PackageReference Include="NewLife.Core" Version="11.9.2025.1212-beta0227" />
   </ItemGroup>
 
   <ItemGroup>
Modified +1 -1
diff --git a/Samples/Zero.Desktop/Zero.Desktop.csproj b/Samples/Zero.Desktop/Zero.Desktop.csproj
index 11e32df..680a901 100644
--- a/Samples/Zero.Desktop/Zero.Desktop.csproj
+++ b/Samples/Zero.Desktop/Zero.Desktop.csproj
@@ -27,7 +27,7 @@
 
   <ItemGroup>
     <PackageReference Include="NewLife.Stardust" Version="3.5.2025.1113" />
-    <PackageReference Include="System.Speech" Version="10.0.0" />
+    <PackageReference Include="System.Speech" Version="10.0.1" />
   </ItemGroup>
 
   <ItemGroup>
Modified +2 -6
diff --git a/Samples/ZeroServer/Areas/Nodes/Controllers/NodeController.cs b/Samples/ZeroServer/Areas/Nodes/Controllers/NodeController.cs
index 014bf27..ffde17f 100644
--- a/Samples/ZeroServer/Areas/Nodes/Controllers/NodeController.cs
+++ b/Samples/ZeroServer/Areas/Nodes/Controllers/NodeController.cs
@@ -1,13 +1,9 @@
-using Microsoft.AspNetCore.Mvc;
-using Zero.Data.Nodes;
-using NewLife;
+using NewLife;
 using NewLife.Cube;
-using NewLife.Cube.Extensions;
 using NewLife.Cube.ViewModels;
-using NewLife.Log;
 using NewLife.Web;
 using XCode.Membership;
-using static Zero.Data.Nodes.Node;
+using Zero.Data.Nodes;
 
 namespace ZeroServer.Areas.Nodes.Controllers;
 
Modified +3 -2
diff --git a/Samples/ZeroServer/Nodes/Model.xml b/Samples/ZeroServer/Nodes/Model.xml
index cc2629a..be6c4e2 100644
--- a/Samples/ZeroServer/Nodes/Model.xml
+++ b/Samples/ZeroServer/Nodes/Model.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<EntityModel xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="https://newlifex.com https://newlifex.com/Model202407.xsd" Document="https://newlifex.com/xcode/model" xmlns="https://newlifex.com/Model202407.xsd">
+<EntityModel xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="https://newlifex.com https://newlifex.com/Model202509.xsd" Document="https://newlifex.com/xcode/model" xmlns="https://newlifex.com/Model202509.xsd">
   <Option>
     <!--类名模板。其中{name}替换为Table.Name,如{name}Model/I{name}Dto等-->
     <ClassNameTemplate />
@@ -130,7 +130,8 @@
         <Column Name="OSKind" DataType="Int32" Description="系统种类。主流操作系统类型,不考虑子版本" Type="Stardust.Models.OSKinds" />
         <Column Name="Memory" DataType="Int32" Description="内存。单位M" />
         <Column Name="AvailableMemory" DataType="Int32" Description="可用内存。单位M" />
-        <Column Name="MemoryUsed" DataType="Int32" Description="已用内存。单位M" />
+        <Column Name="FreeMemory" DataType="Int32" Description="空闲内存。在Linux上空闲不一定可用,部分作为缓存,单位M" />
+        <Column Name="MemoryUsed" DataType="Int32" Description="已用内存。总内存减去空闲内存,单位M" />
         <Column Name="AvailableFreeSpace" DataType="Int32" Description="可用磁盘。应用所在盘,单位M" />
         <Column Name="SpaceUsed" DataType="Int32" Description="已用磁盘。应用所在盘,单位M" />
         <Column Name="DriveInfo" DataType="String" Length="500" Description="驱动器信息。各分区大小,逗号分隔" Category="硬件信息" />
Modified +12 -1
diff --git a/Samples/ZeroServer/Nodes/Zero.htm b/Samples/ZeroServer/Nodes/Zero.htm
index 92e8227..c9be17f 100644
--- a/Samples/ZeroServer/Nodes/Zero.htm
+++ b/Samples/ZeroServer/Nodes/Zero.htm
@@ -914,6 +914,17 @@
         </tr>
 
         <tr>
+            <td>FreeMemory</td>
+            <td>空闲内存</td>
+            <td>Int32</td>
+            <td></td>
+            <td></td>
+            <td></td>
+            <td>N</td>
+            <td>在Linux上空闲不一定可用,部分作为缓存,单位M</td>
+        </tr>
+
+        <tr>
             <td>MemoryUsed</td>
             <td>已用内存</td>
             <td>Int32</td>
@@ -921,7 +932,7 @@
             <td></td>
             <td></td>
             <td>N</td>
-            <td>单位M</td>
+            <td>总内存减去空闲内存,单位M</td>
         </tr>
 
         <tr>
Modified +38 -0
diff --git "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271.cs" "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271.cs"
index fab06ea..7792751 100644
--- "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271.cs"
+++ "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271.cs"
@@ -754,6 +754,44 @@ public partial class Node
     }
     #endregion
 
+    #region 高级查询
+    /// <summary>高级查询</summary>
+    /// <param name="code">编码。NodeKey</param>
+    /// <param name="productCode">产品。产品编码,用于区分不同类型节点</param>
+    /// <param name="category">分类</param>
+    /// <param name="ip">本地IP</param>
+    /// <param name="uuid">唯一标识</param>
+    /// <param name="machineGuid">机器标识</param>
+    /// <param name="mACs">网卡</param>
+    /// <param name="oSKind">系统种类。主流操作系统类型,不考虑子版本</param>
+    /// <param name="alarmOnOffline">下线告警。节点下线时,发送告警</param>
+    /// <param name="enable">启用</param>
+    /// <param name="start">更新时间开始</param>
+    /// <param name="end">更新时间结束</param>
+    /// <param name="key">关键字</param>
+    /// <param name="page">分页参数信息。可携带统计和数据权限扩展查询等信息</param>
+    /// <returns>实体列表</returns>
+    public static IList<Node> Search(String code, String productCode, String category, String ip, String uuid, String machineGuid, String mACs, Stardust.Models.OSKinds oSKind, Boolean? alarmOnOffline, Boolean? enable, DateTime start, DateTime end, String key, PageParameter page)
+    {
+        var exp = new WhereExpression();
+
+        if (!code.IsNullOrEmpty()) exp &= _.Code == code;
+        if (!productCode.IsNullOrEmpty()) exp &= _.ProductCode == productCode;
+        if (!category.IsNullOrEmpty()) exp &= _.Category == category;
+        if (!ip.IsNullOrEmpty()) exp &= _.IP == ip;
+        if (!uuid.IsNullOrEmpty()) exp &= _.Uuid == uuid;
+        if (!machineGuid.IsNullOrEmpty()) exp &= _.MachineGuid == machineGuid;
+        if (!mACs.IsNullOrEmpty()) exp &= _.MACs == mACs;
+        if (oSKind >= 0) exp &= _.OSKind == oSKind;
+        if (alarmOnOffline != null) exp &= _.AlarmOnOffline == alarmOnOffline;
+        if (enable != null) exp &= _.Enable == enable;
+        exp &= _.UpdateTime.Between(start, end);
+        if (!key.IsNullOrEmpty()) exp &= SearchWhereByKeys(key);
+
+        return FindAll(exp, page);
+    }
+    #endregion
+
     #region 字段名
     /// <summary>取得节点字段信息的快捷方式</summary>
     public partial class _
Modified +27 -2
diff --git "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\216\206\345\217\262.cs" "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\216\206\345\217\262.cs"
index 25dbeb9..7d8e39e 100644
--- "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\216\206\345\217\262.cs"
+++ "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\216\206\345\217\262.cs"
@@ -204,14 +204,39 @@ public partial class NodeHistory
     }
     #endregion
 
+    #region 高级查询
+    /// <summary>高级查询</summary>
+    /// <param name="nodeId">节点</param>
+    /// <param name="action">操作</param>
+    /// <param name="success">成功</param>
+    /// <param name="start">编号开始</param>
+    /// <param name="end">编号结束</param>
+    /// <param name="key">关键字</param>
+    /// <param name="page">分页参数信息。可携带统计和数据权限扩展查询等信息</param>
+    /// <returns>实体列表</returns>
+    public static IList<NodeHistory> Search(Int32 nodeId, String action, Boolean? success, DateTime start, DateTime end, String key, PageParameter page)
+    {
+        var exp = new WhereExpression();
+
+        if (nodeId >= 0) exp &= _.NodeId == nodeId;
+        if (!action.IsNullOrEmpty()) exp &= _.Action == action;
+        if (success != null) exp &= _.Success == success;
+        exp &= _.Id.Between(start, end, Meta.Factory.Snow);
+        if (!key.IsNullOrEmpty()) exp &= SearchWhereByKeys(key);
+
+        return FindAll(exp, page);
+    }
+    #endregion
+
     #region 数据清理
     /// <summary>清理指定时间段内的数据</summary>
     /// <param name="start">开始时间。未指定时清理小于指定时间的所有数据</param>
     /// <param name="end">结束时间</param>
+    /// <param name="maximumRows">最大删除行数。清理历史数据时,避免一次性删除过多导致数据库IO跟不上,0表示所有</param>
     /// <returns>清理行数</returns>
-    public static Int32 DeleteWith(DateTime start, DateTime end)
+    public static Int32 DeleteWith(DateTime start, DateTime end, Int32 maximumRows = 0)
     {
-        return Delete(_.Id.Between(start, end, Meta.Factory.Snow));
+        return Delete(_.Id.Between(start, end, Meta.Factory.Snow), maximumRows);
     }
     #endregion
 
Modified +2 -1
diff --git "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.Biz.cs" "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.Biz.cs"
index 227daf4..7a8ed86 100644
--- "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.Biz.cs"
+++ "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.Biz.cs"
@@ -248,7 +248,8 @@ public partial class NodeOnline : Entity<NodeOnline>, IOnlineModel2
 
         if (inf.Memory > 0) online.Memory = (Int32)(inf.Memory / 1024 / 1024);
         if (inf.AvailableMemory > 0) online.AvailableMemory = (Int32)(inf.AvailableMemory / 1024 / 1024);
-        MemoryUsed = online.Memory - online.AvailableMemory;
+        if (inf.FreeMemory > 0) online.FreeMemory = (Int32)(inf.FreeMemory / 1024 / 1024);
+        MemoryUsed = online.Memory - online.FreeMemory > 0 ? online.FreeMemory : online.AvailableMemory;
         if (inf.AvailableFreeSpace > 0) online.AvailableFreeSpace = (Int32)(inf.AvailableFreeSpace / 1024 / 1024);
         if (inf.TotalSize > 0) online.SpaceUsed = (Int32)(inf.TotalSize / 1024 / 1024) - online.AvailableFreeSpace;
         if (inf.CpuRate > 0) online.CpuRate = inf.CpuRate;
Modified +53 -5
diff --git "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.cs" "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.cs"
index 07247eb..8057f4f 100644
--- "a/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.cs"
+++ "b/Samples/ZeroServer/Nodes/\350\212\202\347\202\271\345\234\250\347\272\277.cs"
@@ -146,12 +146,20 @@ public partial class NodeOnline
     [BindColumn("AvailableMemory", "可用内存。单位M", "")]
     public Int32 AvailableMemory { get => _AvailableMemory; set { if (OnPropertyChanging("AvailableMemory", value)) { _AvailableMemory = value; OnPropertyChanged("AvailableMemory"); } } }
 
+    private Int32 _FreeMemory;
+    /// <summary>空闲内存。在Linux上空闲不一定可用,部分作为缓存,单位M</summary>
+    [DisplayName("空闲内存")]
+    [Description("空闲内存。在Linux上空闲不一定可用,部分作为缓存,单位M")]
+    [DataObjectField(false, false, false, 0)]
+    [BindColumn("FreeMemory", "空闲内存。在Linux上空闲不一定可用,部分作为缓存,单位M", "")]
+    public Int32 FreeMemory { get => _FreeMemory; set { if (OnPropertyChanging("FreeMemory", value)) { _FreeMemory = value; OnPropertyChanged("FreeMemory"); } } }
+
     private Int32 _MemoryUsed;
-    /// <summary>已用内存。单位M</summary>
+    /// <summary>已用内存。总内存减去空闲内存,单位M</summary>
     [DisplayName("已用内存")]
-    [Description("已用内存。单位M")]
+    [Description("已用内存。总内存减去空闲内存,单位M")]
     [DataObjectField(false, false, false, 0)]
-    [BindColumn("MemoryUsed", "已用内存。单位M", "")]
+    [BindColumn("MemoryUsed", "已用内存。总内存减去空闲内存,单位M", "")]
     public Int32 MemoryUsed { get => _MemoryUsed; set { if (OnPropertyChanging("MemoryUsed", value)) { _MemoryUsed = value; OnPropertyChanged("MemoryUsed"); } } }
 
     private Int32 _AvailableFreeSpace;
@@ -401,6 +409,7 @@ public partial class NodeOnline
             "OSKind" => _OSKind,
             "Memory" => _Memory,
             "AvailableMemory" => _AvailableMemory,
+            "FreeMemory" => _FreeMemory,
             "MemoryUsed" => _MemoryUsed,
             "AvailableFreeSpace" => _AvailableFreeSpace,
             "SpaceUsed" => _SpaceUsed,
@@ -450,6 +459,7 @@ public partial class NodeOnline
                 case "OSKind": _OSKind = (Stardust.Models.OSKinds)value.ToInt(); break;
                 case "Memory": _Memory = value.ToInt(); break;
                 case "AvailableMemory": _AvailableMemory = value.ToInt(); break;
+                case "FreeMemory": _FreeMemory = value.ToInt(); break;
                 case "MemoryUsed": _MemoryUsed = value.ToInt(); break;
                 case "AvailableFreeSpace": _AvailableFreeSpace = value.ToInt(); break;
                 case "SpaceUsed": _SpaceUsed = value.ToInt(); break;
@@ -502,6 +512,38 @@ public partial class NodeOnline
     }
     #endregion
 
+    #region 高级查询
+    /// <summary>高级查询</summary>
+    /// <param name="sessionId">会话</param>
+    /// <param name="nodeId">节点</param>
+    /// <param name="provinceId">省份</param>
+    /// <param name="cityId">城市</param>
+    /// <param name="token">令牌</param>
+    /// <param name="webSocket">长连接。WebSocket长连接</param>
+    /// <param name="oSKind">系统种类。主流操作系统类型,不考虑子版本</param>
+    /// <param name="start">更新时间开始</param>
+    /// <param name="end">更新时间结束</param>
+    /// <param name="key">关键字</param>
+    /// <param name="page">分页参数信息。可携带统计和数据权限扩展查询等信息</param>
+    /// <returns>实体列表</returns>
+    public static IList<NodeOnline> Search(String sessionId, Int32 nodeId, Int32 provinceId, Int32 cityId, String token, Boolean? webSocket, Stardust.Models.OSKinds oSKind, DateTime start, DateTime end, String key, PageParameter page)
+    {
+        var exp = new WhereExpression();
+
+        if (!sessionId.IsNullOrEmpty()) exp &= _.SessionId == sessionId;
+        if (nodeId >= 0) exp &= _.NodeId == nodeId;
+        if (provinceId >= 0) exp &= _.ProvinceID == provinceId;
+        if (cityId >= 0) exp &= _.CityID == cityId;
+        if (!token.IsNullOrEmpty()) exp &= _.Token == token;
+        if (webSocket != null) exp &= _.WebSocket == webSocket;
+        if (oSKind >= 0) exp &= _.OSKind == oSKind;
+        exp &= _.UpdateTime.Between(start, end);
+        if (!key.IsNullOrEmpty()) exp &= SearchWhereByKeys(key);
+
+        return FindAll(exp, page);
+    }
+    #endregion
+
     #region 字段名
     /// <summary>取得节点在线字段信息的快捷方式</summary>
     public partial class _
@@ -551,7 +593,10 @@ public partial class NodeOnline
         /// <summary>可用内存。单位M</summary>
         public static readonly Field AvailableMemory = FindByName("AvailableMemory");
 
-        /// <summary>已用内存。单位M</summary>
+        /// <summary>空闲内存。在Linux上空闲不一定可用,部分作为缓存,单位M</summary>
+        public static readonly Field FreeMemory = FindByName("FreeMemory");
+
+        /// <summary>已用内存。总内存减去空闲内存,单位M</summary>
         public static readonly Field MemoryUsed = FindByName("MemoryUsed");
 
         /// <summary>可用磁盘。应用所在盘,单位M</summary>
@@ -686,7 +731,10 @@ public partial class NodeOnline
         /// <summary>可用内存。单位M</summary>
         public const String AvailableMemory = "AvailableMemory";
 
-        /// <summary>已用内存。单位M</summary>
+        /// <summary>空闲内存。在Linux上空闲不一定可用,部分作为缓存,单位M</summary>
+        public const String FreeMemory = "FreeMemory";
+
+        /// <summary>已用内存。总内存减去空闲内存,单位M</summary>
         public const String MemoryUsed = "MemoryUsed";
 
         /// <summary>可用磁盘。应用所在盘,单位M</summary>
Modified +1 -1
diff --git a/Test/Test.csproj b/Test/Test.csproj
index 73a421b..1decd1e 100644
--- a/Test/Test.csproj
+++ b/Test/Test.csproj
@@ -10,7 +10,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="NewLife.Core" Version="11.9.2025.1112" />
+    <PackageReference Include="NewLife.Core" Version="11.9.2025.1212-beta0227" />
   </ItemGroup>
 
   <ItemGroup>
Modified +2 -2
diff --git a/XUnitTest/XUnitTest.csproj b/XUnitTest/XUnitTest.csproj
index 624de92..f65e206 100644
--- a/XUnitTest/XUnitTest.csproj
+++ b/XUnitTest/XUnitTest.csproj
@@ -9,10 +9,10 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
     <PackageReference Include="Moq" Version="4.20.72" />
-    <PackageReference Include="NewLife.Core" Version="11.9.2025.1112" />
+    <PackageReference Include="NewLife.Core" Version="11.9.2025.1212-beta0227" />
     <PackageReference Include="NewLife.UnitTest" Version="1.0.2025.101" />
     <PackageReference Include="xunit" Version="2.9.3" />
     <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">