GroupFileContainer.cs 7.68 KB
using HslCommunication.Core;
using HslCommunication.LogNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace HslCommunication.Enthernet
{
    /// <summary>
    /// 文件集容器,绑定一个文件夹的文件信息组
    /// </summary>
    public class GroupFileContainer
    {
        #region Constructor

        /// <summary>
        /// 实例化一个新的数据管理容器
        /// </summary>
        /// <param name="logNet">日志记录对象,可以为空</param>
        /// <param name="path">文件的路径</param>
        public GroupFileContainer(ILogNet logNet, string path)
        {
            LogNet = logNet;
            GroupFileContainerLoadByPath(path);
        }

        #endregion

        #region Public Members

        /// <summary>
        /// 包含所有文件列表信息的json文本缓存
        /// </summary>
        public string JsonArrayContent
        {
            get { return m_JsonArrayContent; }
        }

        /// <summary>
        /// 获取文件的数量
        /// </summary>
        public int FileCount
        {
            get { return m_filesCount; }
        }

        #endregion

        #region Event Handle


        private void OnFileCountChanged()
        {
            FileCountChanged?.Invoke(m_filesCount);
        }

        /// <summary>
        /// 当文件数量发生变化的时候触发的事件
        /// </summary>
        public event Action<int> FileCountChanged;

        #endregion

        #region Upload Download Delete


        /// <summary>
        /// 下载文件时调用
        /// </summary>
        /// <param name="fileName">文件的实际名称</param>
        /// <returns>文件名映射过去的实际的文件名字</returns>
        public string GetCurrentFileMappingName(string fileName)
        {
            string source = Guid.NewGuid().ToString("N");
            hybirdLock.Enter();
            for (int i = 0; i < m_files.Count; i++)
            {
                if (m_files[i].FileName == fileName)
                {
                    source = m_files[i].MappingName;
                    m_files[i].DownloadTimes++;
                }
            }
            hybirdLock.Leave();

            // 更新缓存
            coordinatorCacheJsonArray.StartOperaterInfomation();

            return source;
        }

        /// <summary>
        /// 上传文件时掉用
        /// </summary>
        /// <param name="fileName">文件名,带后缀,不带任何的路径</param>
        /// <param name="fileSize">文件的大小</param>
        /// <param name="mappingName">文件映射名称</param>
        /// <param name="owner">文件的拥有者</param>
        /// <param name="description">文件的额外描述</param>
        /// <returns>映射的文件名称</returns>
        public string UpdateFileMappingName(string fileName, long fileSize, string mappingName, string owner, string description)
        {
            string source = string.Empty;
            hybirdLock.Enter();

            for (int i = 0; i < m_files.Count; i++)
            {
                if (m_files[i].FileName == fileName)
                {
                    source = m_files[i].MappingName;
                    m_files[i].MappingName = mappingName;
                    m_files[i].Description = description;
                    m_files[i].FileSize = fileSize;
                    m_files[i].Owner = owner;
                    m_files[i].UploadTime = DateTime.Now;
                    break;
                }
            }

            if (string.IsNullOrEmpty(source))
            {
                // 文件不存在
                m_files.Add(new GroupFileItem()
                {
                    FileName = fileName,
                    FileSize = fileSize,
                    DownloadTimes = 0,
                    Description = description,
                    Owner = owner,
                    MappingName = mappingName,
                    UploadTime = DateTime.Now
                });
            }

            hybirdLock.Leave();

            // 更新缓存
            coordinatorCacheJsonArray.StartOperaterInfomation();

            return source;
        }

        /// <summary>
        /// 删除一个文件信息
        /// </summary>
        /// <param name="fileName">实际的文件名称</param>
        /// <returns>映射之后的文件名</returns>
        public string DeleteFile(string fileName)
        {
            string source = string.Empty;
            hybirdLock.Enter();
            for (int i = 0; i < m_files.Count; i++)
            {
                if (m_files[i].FileName == fileName)
                {
                    source = m_files[i].MappingName;
                    m_files.RemoveAt(i);
                    break;
                }
            }
            hybirdLock.Leave();

            // 更新缓存
            coordinatorCacheJsonArray.StartOperaterInfomation();
            return source;
        }

        #endregion

        #region Private Method

        /// <summary>
        /// 缓存JSON文本的方法,该机制使用乐观并发模型完成
        /// </summary>
        private void CacheJsonArrayContent()
        {
            hybirdLock.Enter();
            m_filesCount = m_files.Count;
            m_JsonArrayContent = Newtonsoft.Json.Linq.JArray.FromObject(m_files).ToString();

            // 保存文件
            using (StreamWriter sw = new StreamWriter(m_filePath + FileListResources, false, Encoding.UTF8))
            {
                sw.Write(m_JsonArrayContent);
            }

            hybirdLock.Leave();
            // 通知更新
            OnFileCountChanged();
        }

        /// <summary>
        /// 从目录进行加载数据,必须实例化的时候加载,加载失败会导致系统异常,旧的文件丢失
        /// </summary>
        /// <param name="path"></param>
        private void GroupFileContainerLoadByPath(string path)
        {
            m_filePath = path;

            if (!Directory.Exists(m_filePath))
            {
                Directory.CreateDirectory(m_filePath);
            }

            if (File.Exists(m_filePath + FileListResources))
            {
                try
                {
                    using (StreamReader sr = new StreamReader(m_filePath + FileListResources, Encoding.UTF8))
                    {
                        m_files = Newtonsoft.Json.Linq.JArray.Parse(sr.ReadToEnd()).ToObject<List<GroupFileItem>>();
                    }
                }
                catch (Exception ex)
                {
                    LogNet?.WriteException("GroupFileContainer", "Load files txt failed,", ex);
                }
            }

            if (m_files == null)
            {
                m_files = new List<GroupFileItem>();
            }

            coordinatorCacheJsonArray = new HslAsyncCoordinator(CacheJsonArrayContent);

            CacheJsonArrayContent();
        }

        #endregion

        #region Private Members

        private const string FileListResources = "\\list.txt";            // 文件名
        private ILogNet LogNet;                                           // 日志对象
        private string m_JsonArrayContent = "[]";                         // 缓存数据
        private int m_filesCount = 0;                                     // 文件数量
        private SimpleHybirdLock hybirdLock = new SimpleHybirdLock();     // 简单混合锁
        private HslAsyncCoordinator coordinatorCacheJsonArray;            // 乐观并发模型
        private List<GroupFileItem> m_files;                              // 文件队列
        private string m_filePath;                                        // 文件路径

        #endregion
    }
}