/// <summary> /// 文件流写入器 /// </summary> /// <param name="cacheFile"></param> internal FileStreamWriter(FileStreamWriter cacheFile) { cache = cacheFile.cache; Config = cacheFile.Config; bufferPool = SubBuffer.Pool.GetPool(Config.BufferSize); flushHandle = flush; }
/// <summary> /// 缓存主服务 /// </summary> /// <param name="config">缓存主服务配置</param> public MasterServer(MasterServerConfig config) { Config = config ?? defaultConfig; if (Config.MinCompressSize <= 0) { Config.MinCompressSize = int.MaxValue; } }
/// <summary> /// 缓存管理 /// </summary> /// <param name="config">缓存服务配置</param> /// <param name="tcpServer">缓存服务</param> internal CacheManager(MasterServerConfig config, AutoCSer.Net.TcpInternalServer.Server tcpServer) { Config = config; TcpServer = tcpServer; tcpQueue = tcpServer.CallQueue; shortPaths = new ShortPathItem[config.GetShortPathCount]; if (config.IsFile) { disposeHandle = Dispose; IsFile = true; File = new FileStreamWriter(this, config); foreach (Cache.MessageQueue.Node messageQueue in LoadMessageQueues) { messageQueue.Start(); } LoadMessageQueues.SetNull(); IsLoaded = CanWrite = true; AutoCSer.DomainUnload.Unloader.Add(disposeHandle, DomainUnload.Type.Action); } else { IsLoaded = CanWrite = true; } }
/// <summary> /// 文件流写入器 /// </summary> /// <param name="cache"></param> /// <param name="config"></param> internal FileStreamWriter(CacheManager cache, MasterServerConfig config) { this.cache = cache; Config = config; bufferPool = SubBuffer.Pool.GetPool(config.BufferSize); FileInfo file = new FileInfo(config.GetFileName); FileName = file.FullName; IsDisposed = 1; FileMode createMode = FileMode.CreateNew; FileBuffers buffer = default(FileBuffers); try { if (file.Exists) { if (file.Length == 0) { createMode = FileMode.Create; } else { fileStream = new FileStream(FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, bufferPool.Size, FileOptions.None); bufferPool.Get(ref buffer.Buffer); if (fileStream.Read(buffer.Buffer.Buffer, buffer.Buffer.StartIndex, fileHeaderSize) == fileHeaderSize) { fixed(byte *bufferFixed = buffer.Buffer.Buffer) { byte *bufferStart = bufferFixed + buffer.Buffer.StartIndex; if (*(int *)bufferStart == FileHeader) { Version = *(ulong *)(bufferStart + sizeof(int) * 2); FileInfo switchFile = new FileInfo(config.GetSwitchFileName); if (switchFile.Exists) { FileStream switchFileStream = new FileStream(switchFile.FullName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, bufferPool.Size, FileOptions.None); if (switchFileStream.Read(buffer.Buffer.Buffer, buffer.Buffer.StartIndex, fileHeaderSize) == fileHeaderSize && *(int *)bufferStart == FileHeader && *(ulong *)(bufferStart + sizeof(int) * 2) > Version) { fileStream.Dispose(); Version = *(ulong *)(bufferStart + sizeof(int) * 2); fileStream = switchFileStream; FileName = switchFile.FullName; isSwitchFile = true; } } if (Version > 0) { LoadData loadData = new LoadData { Buffer = BufferLink.Head }; int count = fileStream.Read(buffer.Buffer.Buffer, buffer.Buffer.StartIndex, buffer.Buffer.Length), index = 0, compressionDataSize; long nextLength = (FileLength = fileStream.Length) - fileHeaderSize - count; do { while (count >= sizeof(int) * 2) { byte *read = bufferStart + index; if ((compressionDataSize = *(int *)read) < 0) { if (count >= (compressionDataSize = -compressionDataSize) + sizeof(int) * 2) { buffer.CompressionBuffer.StartIndex = *(int *)(read + sizeof(int)); AutoCSer.IO.Compression.DeflateDeCompressor.Get(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + (index += sizeof(int) * 2), compressionDataSize, ref buffer.CompressionBuffer); if (buffer.CompressionBuffer.Buffer != null) { fixed(byte *dataFixed = buffer.CompressionBuffer.Buffer) { loadData.Set(buffer.CompressionBuffer.Buffer, buffer.CompressionBuffer.StartIndex, *(int *)(read + sizeof(int)), dataFixed); if (!cache.Load(ref loadData)) { throw new InvalidDataException(); } } index += compressionDataSize; count -= compressionDataSize + sizeof(int) * 2; buffer.CompressionBuffer.Free(); } else { throw new InvalidDataException(); } } else if (count + nextLength >= compressionDataSize + sizeof(int) * 2) { if (compressionDataSize + sizeof(int) * 2 <= buffer.Buffer.StartIndex) { break; } if (bigBuffer.Length < compressionDataSize) { bigBuffer = new byte[Math.Max(compressionDataSize, bigBuffer.Length << 1)]; } System.Buffer.BlockCopy(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + (index + sizeof(int) * 2), bigBuffer, 0, count -= sizeof(int) * 2); do { index = fileStream.Read(bigBuffer, count, compressionDataSize - count); nextLength -= index; count += index; }while (count != compressionDataSize); buffer.CompressionBuffer.StartIndex = *(int *)(read + sizeof(int)); AutoCSer.IO.Compression.DeflateDeCompressor.Get(bigBuffer, 0, compressionDataSize, ref buffer.CompressionBuffer); if (buffer.CompressionBuffer.Buffer != null) { fixed(byte *dataFixed = buffer.CompressionBuffer.Buffer) { loadData.Set(buffer.CompressionBuffer.Buffer, buffer.CompressionBuffer.StartIndex, *(int *)(read + sizeof(int)), dataFixed); if (!cache.Load(ref loadData)) { throw new InvalidDataException(); } } index = count = 0; buffer.CompressionBuffer.Free(); } else { throw new InvalidDataException(); } } else { endError(ref buffer.Buffer, nextLength, index, count); return; } } else if (count >= compressionDataSize + sizeof(int)) { loadData.Set(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + (index += sizeof(int)), compressionDataSize, bufferFixed); if (!cache.Load(ref loadData)) { throw new InvalidDataException(); } index += compressionDataSize; count -= compressionDataSize + sizeof(int); } else if (count + nextLength >= compressionDataSize + sizeof(int)) { if (compressionDataSize + sizeof(int) <= buffer.Buffer.StartIndex) { break; } if (bigBuffer.Length < compressionDataSize) { bigBuffer = new byte[Math.Max(compressionDataSize, bigBuffer.Length << 1)]; } System.Buffer.BlockCopy(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + (index + sizeof(int)), bigBuffer, 0, count -= sizeof(int)); do { index = fileStream.Read(bigBuffer, count, compressionDataSize - count); nextLength -= index; count += index; }while (count != compressionDataSize); fixed(byte *dataFixed = bigBuffer) { loadData.Set(bigBuffer, 0, compressionDataSize, dataFixed); if (!cache.Load(ref loadData)) { throw new InvalidDataException(); } } index = count = 0; } else { endError(ref buffer.Buffer, nextLength, index, count); return; } } if (nextLength == 0) { if (count == 0) { fileStream.Seek(0, SeekOrigin.End); IsDisposed = 0; } else { endError(ref buffer.Buffer, nextLength, index, count); } return; } if (count != 0) { System.Buffer.BlockCopy(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + index, buffer.Buffer.Buffer, buffer.Buffer.StartIndex, count); } index = fileStream.Read(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + count, buffer.Buffer.Length - count); nextLength -= index; count += index; index = 0; }while (true); } } } } if (!config.IsMoveBakUnknownFile) { throw new InvalidDataException(); } fileStream.Dispose(); AutoCSer.IO.File.MoveBak(FileName); } } fileStream = new FileStream(FileName, createMode, FileAccess.Write, FileShare.Read, bufferPool.Size, FileOptions.None); create(ref buffer.Buffer, Version); } finally { buffer.Free(); BufferLink.Head.Array.SetNull(); if (IsDisposed == 0) { fileFlushSeconds = config.FileFlushSeconds; Writers.PushNotNull(this); OnTime.Set(Date.NowTime.OnTimeFlag.CacheFile); } else if (fileStream != null) { fileStream.Dispose(); } } }