You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

338 lines
11 KiB

using System;
using System.Collections.Generic;
using System.IO;
using Google.Protobuf.WellKnownTypes;
using Sog;
using FileTransDataObject;
namespace SMAgent
{
class AgentFileTransMng : Singleton<AgentFileTransMng>
{
public SMAgentDoCommandReq pullReq;
public bool isFinish;
public string errorMsg;
private FileTransMgr transMgr;
private long lastTickTime;
private int testMode;
public AgentFileTransMng()
{
transMgr = new FileTransMgr(SMAgentUtils.HostName);
transMgr._SendTransFileNotify = SendTransFileNotify;
isFinish = true;
}
public void Clear()
{
TraceLog.Debug("AgentFileTransMng.Clear");
pullReq = null;
errorMsg = null;
isFinish = true;
transMgr.Clear();
}
public void Tick(long nowMs)
{
if (nowMs < lastTickTime + 1000)
{
return;
}
lastTickTime = nowMs;
transMgr.Tick(nowMs);
if (! isFinish && transMgr.IsFinish())
{
isFinish = true;
Clear();
}
}
// pull文件时, SMAgentDoCommandRes直接回应Center, Center根据是不是在接收文件再确定是不是接收console的新命令
public int DoTransCmd(SMAgentDoCommandReq req)
{
if (pullReq != null)
{
errorMsg = string.Format("last file transfer not finish, cmd {0} file num {1}"
, pullReq.Command, transMgr.TotalFile);
TraceLog.Error("AgentFileTransMng.DoTransCmd {0}", errorMsg);
return -1;
}
pullReq = req;
if (BeginTrans() != 0)
{
TraceLog.Error("AgentFileTransMng.DoTransCmd {0}", errorMsg);
pullReq = null;
return -1;
}
testMode = req.TestMode;
// 测试模式, 每次传输1字节, 模拟大文件
if (testMode == 1)
{
transMgr.SetContentSlice(1);
}
return 0;
}
// 初始化文件列表
private List<FileData> GetTransFiles()
{
List<FileData> fileList = new List<FileData>();
if (pullReq.Command == "pullagentlog")
{
GetAgentLogFile(fileList);
}
else if (pullReq.Command == "pull")
{
GetPullFile(fileList);
}
return fileList;
}
public int BeginTrans()
{
var fileList = GetTransFiles();
if (fileList.Count == 0)
{
return -1;
}
var hostList = new List<string>();
hostList.Add(pullReq.CenterName);
if (transMgr.BeginTrans(fileList, hostList) != 0)
{
return -1;
}
isFinish = false;
return 0;
}
public void SendTransFileNotify(long transSeq, List<FileData> fileList, List<string> hostList)
{
var notify = new SMTransFileNotify {TransSeq = transSeq, HostName = SMAgentUtils.HostName};
foreach (FileData file in fileList)
{
var attr = new FileAttr
{
FileMd5 = file.fileMd5,
FileName = file.fileName,
FileSize = file.FileSize,
FilePath = file.writeFilePath,
FileTime = file.fileWriteTime.ToFileTimeUtc()
};
notify.FileList.Add(attr);
}
foreach (string name in hostList)
{
SMAgentNet.Instance.SendMsgToCenter(notify, SMMsgID.TransFileNotify);
}
}
public static int count = 0;
public void OnFileContentReq(SMFileContentReq req)
{
// 测试模式, 模拟50%丢包率
if (testMode == 1 && count++ % 2 == 1)
{
return;
}
var res = transMgr.OnFileContentReq(req);
SMAgentNet.Instance.SendMsgToCenter(res, SMMsgID.FileContentRes);
}
public void OnFileRecvStateReq(SMFileRecvStateReq req)
{
transMgr.OnFileRecvStateReq(req);
var res = new SMFileRecvStateRes {TransSeq = req.TransSeq, HostName = SMAgentUtils.HostName};
SMAgentNet.Instance.SendMsgToCenter(res, SMMsgID.FileRecvStateRes);
}
private int GetAgentLogFile(List<FileData> fileList)
{
try
{
// agent的运行目录可以选择硬编码完整路径,或根据center计算(center和agent的部署层次应该是一样)
string dir = "../log";
string logFullPath = Path.GetFullPath(dir);
foreach (string path in Directory.GetFiles(dir))
{
string name = Path.GetFileName(path);
if (name.Split('.')[0] != "smagent")
{
continue;
}
var file = FileUtils.CreateFileData(path, true);
if (file != null)
{
// 文件名加上host前缀作区分
file.fileName = SMAgentUtils.HostName + "_" + name;
// center和agent的部署层级应该是一样的, agent的log目录也是center的目录
file.writeFilePath = logFullPath;
fileList.Add(file);
}
}
}
catch (Exception e)
{
TraceLog.Exception(e);
errorMsg = e.Message + "\n" + e.StackTrace;
return -1;
}
return 0;
}
private int GetPullFile(List<FileData> fileList)
{
try
{
/* push 命令支持绝对路径,如果是相对路径,那么是center和agent所在的bin目录为当前目录
* 所以最好用绝对路径,不容易出错
* -r 表示递归
* push 1.200.1 -r /data/mmogrun/publish/cfg/* /data/mmogrun/publish/cfg/
*/
//先处理一下参数
bool recursive = false;
List<string> pushfileParams = new List<string>();
string[] cmdParams = pullReq.CmdArgs.Split(' ');
for (int i = 1; i < cmdParams.Length; i++)
{
var param = cmdParams[i];
if (param == "-r")
{
recursive = true;
}
else
{
pushfileParams.Add(param);
}
}
if (pushfileParams.Count != 2)
{
TraceLog.Error("AgentFileTransMng.GetPullFile invalid param");
return -1;
}
string srcFile, srcfullPath;
string dstPath = pushfileParams[1];
string srcfilePath = pushfileParams[0];
//补一下'/',否则Path.GetFullPath结果不会带有'/'
if (dstPath[dstPath.Length - 1] != '/' && dstPath[dstPath.Length - 1] != '\\')
{
dstPath += '/';
}
string dstfullPath = Path.GetFullPath(dstPath);
int lastindex = srcfilePath.LastIndexOf('/');
if (lastindex == -1)
{
lastindex = srcfilePath.LastIndexOf('\\');
if (lastindex == -1)
{
TraceLog.Error("AgentFileTransMng.GetPullFile invalid srcpath {0}", srcfilePath);
return -1;
}
}
//源是个目录而不是文件名或通配符,那么在最后加个*上去,这样统一了
if (recursive && Directory.Exists(srcfilePath))
{
if (srcfilePath[srcfilePath.Length - 1] != '/' && srcfilePath[srcfilePath.Length - 1] != '\\')
{
srcfilePath += '/';
}
srcFile = "*";
srcfullPath = Path.GetFullPath(srcfilePath);
srcfullPath = Path.GetDirectoryName(srcfullPath);
}
else
{
string srcPath = srcfilePath.Substring(0, lastindex + 1);
srcFile = srcfilePath.Substring(lastindex + 1);
srcfullPath = Path.GetFullPath(srcPath);
srcfullPath = Path.GetDirectoryName(srcfullPath);
}
//说明只传一个文件
if (srcFile.Contains('*') == false)
{
var filefullpath = srcfullPath + "/" + srcFile;
var file = FileUtils.CreateFileData(filefullpath, true);
file.writeFilePath = dstfullPath;
fileList.Add(file);
TraceLog.Trace("AgentFileTransMng.GetPullFile add file to list, path {0} file {1}"
, file.readFilePath, file.fileName);
return 0;
}
//根据通配符传送多个文件,先判断是否递归
SearchOption so = SearchOption.TopDirectoryOnly;
if (recursive)
{
so = SearchOption.AllDirectories;
}
foreach (string filefullpath in Directory.GetFiles(srcfullPath, srcFile, so))
{
var file = FileUtils.CreateFileData(filefullpath, true);
//判断是否子目录
file.writeFilePath = dstfullPath;
if (file.readFilePath != srcfullPath) //子目录
{
string addsubdir = file.readFilePath.Substring(srcfullPath.Length);
file.writeFilePath += addsubdir;
}
fileList.Add(file);
TraceLog.Trace("AgentFileTransMng.GetPullFile add file to list, path {0} file {1}"
, file.readFilePath, file.fileName);
}
}
catch (Exception e)
{
TraceLog.Exception(e);
errorMsg = e.Message + "\n" + e.StackTrace;
return -1;
}
return 0;
}
}
}