1 public class SyncMemoryList<T>: SyncList<T>, IDisposable
2 {
3 private MemoryCache<T> _memoryCache = new MemoryCache<T>();
4
5 public new void Add(T item)
6 {
7 string json = $"{ToJson(item)}\n";
8 WriteCache(json);
9
10 base.Add(item);
11 }
12
13 private string ToJson(T item)
14 {
15 Type type = typeof(T);
16 if (type.IsClass)
17 return JsonExtensions.ToJson(item);
18 else
19 return item.ToString();
20 }
21
22 private void WriteCache(string text)
23 {
24 byte[] bytes = Encoding.UTF8.GetBytes(text);
25 if (_memoryCache.IsAllowWrite(bytes.Length))
26 {
27 _memoryCache.Write(bytes);
28 }
29 else
30 {
31 _memoryCache.Dispose();
32 _memoryCache = new MemoryCache<T>();
33 _memoryCache.Write(bytes);
34 }
35 }
36
37 #region IDisposable Support
38 private bool disposedValue = false; // 要检测冗余调用
39
40 protected virtual void Dispose(bool disposing)
41 {
42 if (!disposedValue)
43 {
44 if (disposing)
45 {
46 // TODO: 释放托管状态(托管对象)。
47 }
48
49 _memoryCache?.Dispose();
50 disposedValue = true;
51 }
52 }
53
54 // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
55 // ~SyncMemoryList() {
56 // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
57 // Dispose(false);
58 // }
59
60 // 添加此代码以正确实现可处置模式。
61 public void Dispose()
62 {
63 // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
64 Dispose(true);
65 // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
66 // GC.SuppressFinalize(this);
67 }
68 #endregion
69 }
70
71 internal class MemoryCache<T>:IDisposable
72 {
73 private readonly MemoryMappedFile _memoryMapped = null;
74 private readonly MemoryMappedViewStream _stream = null;
75 private static readonly long _defaultSize = 1024 * 1024;
76 private readonly long _capatity = 0;
77 public MemoryCache()
78 {
79 string mapname = $"{typeof(T).Name}";
80 string fileName = $"{typeof(T).Name}_{DateTime.Now:yyyy_M_d}.dat";
81 long maxlen = 0;
82 if (File.Exists(fileName))
83 {
84 (long size,long offset) = (0, 0);
85 FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
86 (size,offset) = GetFileInfo(stream);
87 //stream.Close();
88 maxlen = size + _defaultSize;
89 _memoryMapped = MemoryMappedFile.CreateFromFile(stream, mapname, maxlen, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false);
90 _stream = _memoryMapped.CreateViewStream();
91 _stream.Position = offset == 0 ? 16 : offset;
92 }
93 else
94 {
95 maxlen = _defaultSize + 16;
96 _memoryMapped = MemoryMappedFile.CreateFromFile(fileName, FileMode.OpenOrCreate, mapname, maxlen, MemoryMappedFileAccess.ReadWrite);
97 _stream = _memoryMapped.CreateViewStream();
98 _stream.Position = 16;
99 }
100
101 _capatity = maxlen - 16;
102 }
103
104 public long Position => _stream.Position;
105
106 private (long, long) GetFileInfo(Stream stream)
107 {
108 try
109 {
110 byte[] byteSize = new byte[8];
111 byte[] byteOffset = new byte[8];
112
113 stream.Read(byteSize, 0, byteSize.Length);
114 stream.Read(byteOffset, 0, byteOffset.Length);
115
116 return (BitConverter.ToInt64(byteSize, 0), BitConverter.ToInt64(byteOffset, 0));
117 }
118 catch (Exception e)
119 {
120 return (_defaultSize, 0);
121 }
122 }
123
124 public bool IsAllowWrite(long size)
125 {
126 return _capatity - _stream.Position > size;
127 }
128
129 public void WriteLength(long offset)
130 {
131 byte[] byteSize = BitConverter.GetBytes(_capatity);
132 byte[] byteOffset = BitConverter.GetBytes(offset);
133 _stream.Position = 0;
134 _stream.Write(byteSize, 0, byteSize.Length);
135 _stream.Write(byteOffset, 0, byteOffset.Length);
136 }
137
138 public void Write(byte[] bytes)
139 {
140 var _offset = _stream.Position;
141 WriteLength(_offset + bytes.Length);
142 _stream.Position = _offset;
143 _stream.Write(bytes, 0, bytes.Length);
144 }
145
146 public void Dispose()
147 {
148 _memoryMapped?.Dispose();
149 _stream?.Dispose();
150 }
151 }