123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- using Force.Crc32;
- using PackageInterface;
- using System;
- using System.Collections.Concurrent;
- using System.Diagnostics;
- using System.IO;
- using System.IO.Compression;
- using System.Linq;
- using System.Threading.Tasks;
- namespace PackageServer
- {
- enum PackageTaskState
- {
- Running,
- Transfering,
- Executing,
- Closed,
- }
- class PackageTask
- {
- private uint _transferHashCode;
- private string _transferFolder;
- private string _packageFolder;
- private string _transferFilePath;
- private Stream _transferStream;
- private Process _runningProcess;
- public string Id { get; }
- public string Version { get; }
- public PackageTaskState State { get; private set; }
- public PackageTask(string version, string transferFolder, string packageFolder)
- {
- _transferFolder = transferFolder;
- _packageFolder = packageFolder;
- Id = Guid.NewGuid().ToString("N");
- Version = version;
- State = PackageTaskState.Running;
- }
- public void StartTransfer(uint hashCode)
- {
- if(!Directory.Exists(_transferFolder))
- {
- Directory.CreateDirectory(_transferFolder);
- }
- //Clean the package folder
- if(Directory.Exists(_packageFolder))
- {
- Directory.Delete(_packageFolder, true);
- }
- if(!Directory.Exists(_packageFolder))
- {
- Directory.CreateDirectory(_packageFolder);
- }
- _transferHashCode = hashCode;
- _transferFilePath = Path.Combine(_transferFolder, Guid.NewGuid().ToString("N") + ".zip");
- _transferStream = File.Open(_transferFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
- State = PackageTaskState.Transfering;
- }
- public void AddTransferData(byte[] data)
- {
- try
- {
- _transferStream.Write(data);
- }
- catch
- {
- Close();
- throw;
- }
- }
- public void EndTransfer()
- {
- try
- {
- _transferStream.Flush();
- _transferStream.Dispose();
- var zipData = File.ReadAllBytes(_transferFilePath);
- //check hash code.
- var hashCode = Crc32Algorithm.Compute(zipData);
- if (hashCode != _transferHashCode)
- {
- throw new InvalidDataException("Transfer hash code is not right.");
- }
- //Extract to package folder.
- ZipFile.ExtractToDirectory(_transferFilePath, _packageFolder, true);
- if (File.Exists(_transferFilePath))
- {
- File.Delete(_transferFilePath);
- }
- State = PackageTaskState.Running;
- }
- catch
- {
- Close();
- throw;
- }
- }
- public void Execute(string fileName)
- {
- try
- {
- //Execute bat file or exe file.
- var filePath = Path.Combine(_packageFolder, fileName);
- if (!File.Exists(filePath))
- {
- throw new InvalidDataException("The file is not exist.");
- }
- _runningProcess = Process.Start(new ProcessStartInfo() { FileName = filePath, Arguments=Version, UseShellExecute = true, WorkingDirectory = _packageFolder });
- State = PackageTaskState.Executing;
- Task.Run(() =>
- {
- _runningProcess.WaitForExit();
- State = PackageTaskState.Running;
- });
- }
- catch
- {
- Close();
- throw;
- }
- }
- public void Close()
- {
- if(_transferStream != null)
- {
- _transferStream.Dispose();
- _transferStream = null;
- }
- if(File.Exists(_transferFilePath))
- {
- File.Delete(_transferFilePath);
- }
- State = PackageTaskState.Closed;
- }
- /// <summary>
- /// Kill means force kill the running task.
- /// </summary>
- public void Kill()
- {
- if (_runningProcess != null)
- {
- _runningProcess.Kill();
- }
- Close();
- State = PackageTaskState.Closed;
- }
- }
- class Packager
- {
- private string _packagerFolder;
- private string _transferFolder;
- private string _packageFolder;
- public string Id { get; }
- public string ProjectName { get; }
- public PackageTask CurrentTask { get; private set; }
- public Packager(string projectName)
- {
- Id = Guid.NewGuid().ToString("N");
- ProjectName = projectName;
- _packagerFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Packages", ProjectName);
- if(!Directory.Exists(_packagerFolder))
- {
- Directory.CreateDirectory(_packagerFolder);
- }
- _transferFolder = Path.Combine(_packagerFolder, "Transfer");
- if(!Directory.Exists(_transferFolder))
- {
- Directory.CreateDirectory(_transferFolder);
- }
- _packageFolder = Path.Combine(_packagerFolder, "Dist");
- if(!Directory.Exists(_packageFolder))
- {
- Directory.CreateDirectory(_packageFolder);
- }
- }
- public void StartPackage(string version)
- {
- if (CurrentTask != null)
- {
- CurrentTask.Kill();
- CurrentTask = null;
- }
- CurrentTask = new PackageTask(version, _transferFolder, _packageFolder);
- }
- public void EndPackage()
- {
- if (CurrentTask != null)
- {
- CurrentTask.Close();
- CurrentTask = null;
- }
- }
- public void KillTask()
- {
- if(CurrentTask != null)
- {
- CurrentTask.Kill();
- CurrentTask = null;
- }
- }
- }
- class PackageManager : IPackageManager
- {
- private readonly ConcurrentDictionary<string, Packager> _packagers = new ConcurrentDictionary<string,Packager>();
- public void EndPackage(string packagerId, string taskId)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if (task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if (packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- packager.EndPackage();
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public void EndTransfer(string packagerId, string taskId)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if (task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if (packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- packager.CurrentTask.EndTransfer();
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public void Execute(string packagerId, string taskId, string fileName)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if (task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if (packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- packager.CurrentTask.Execute(fileName);
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public string GetOrCreatePackager(string projectName)
- {
- var packager = _packagers.Values.FirstOrDefault(x => x.ProjectName == projectName);
- if(packager == null)
- {
- packager = new Packager(projectName);
- _packagers.TryAdd(packager.Id, packager);
- }
- return packager.Id;
- }
- public string GetPackageTaskState(string packagerId, string taskId)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if (task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if (packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- return packager.CurrentTask.State.ToString();
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public void KillPackager(string packagerId)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- packager.KillTask();
- _packagers.TryRemove(packager.ProjectName, out _);
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public void KillPackageTask(string packagerId, string taskId)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if (task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if (packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- packager.KillTask();
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public string StartPackageTask(string packagerId, string version)
- {
- if(_packagers.TryGetValue(packagerId, out var packager))
- {
- packager.StartPackage(version);
- return packager.CurrentTask.Id;
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public void StartTransfer(string packagerId, string taskId, uint hashCode)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if(task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if(packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- packager.CurrentTask.StartTransfer(hashCode);
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- public void TransferData(string packagerId, string taskId, byte[] data)
- {
- if (_packagers.TryGetValue(packagerId, out var packager))
- {
- var task = packager.CurrentTask;
- if (task == null)
- {
- throw new InvalidOperationException("No task is running.");
- }
- if (packager.CurrentTask.Id != taskId)
- {
- throw new InvalidOperationException("The task is not current running task.");
- }
- packager.CurrentTask.AddTransferData(data);
- }
- else
- {
- throw new InvalidOperationException("Packager does not exist.");
- }
- }
- }
- }
|