/// <summary> /// 写缓存数据 /// </summary> private void writeCache() { bool isError = true; FileBuffers buffer = default(FileBuffers); try { bufferPool.Get(ref buffer.Buffer); fixed(byte *bufferFixed = buffer.Buffer.Buffer) { byte *bufferStart = bufferFixed + buffer.Buffer.StartIndex; int index = sizeof(int), snapshotSize; long writeLength = 0; while ((snapshotSize = snapshot.NextSize()) != 0) { CHECK: if (snapshotSize + index <= buffer.Buffer.Length) { snapshot.CopyTo(bufferStart + index); index += snapshotSize; } else if (index == sizeof(int)) { if (bigBuffer.Length < (index = snapshotSize + sizeof(int))) bigBuffer = new byte[Math.Max(index, bigBuffer.Length << 1)]; fixed(byte *bigBufferFixed = bigBuffer) { snapshot.CopyTo(bigBufferFixed + sizeof(int)); if (snapshotSize >= Config.MinCompressSize) { if (AutoCSer.IO.Compression.DeflateCompressor.Get(bigBuffer, sizeof(int), snapshotSize, ref buffer.CompressionBuffer, ref buffer.CompressionData, sizeof(int) * 2, sizeof(int) * 2)) { writeCompression(ref buffer.CompressionData, snapshotSize); buffer.CompressionBuffer.TryFree(); writeLength += buffer.CompressionData.Length; index = sizeof(int); continue; } buffer.CompressionBuffer.TryFree(); } *(int *)bigBufferFixed = snapshotSize; } fileStream.Write(bigBuffer, 0, index); writeLength += index; index = sizeof(int); } else { if (index > Config.MinCompressSize) { if (AutoCSer.IO.Compression.DeflateCompressor.Get(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + sizeof(int), index - sizeof(int), ref buffer.CompressionBuffer, ref buffer.CompressionData, sizeof(int) * 2, sizeof(int) * 2)) { writeCompression(ref buffer.CompressionData, index - sizeof(int)); buffer.CompressionBuffer.TryFree(); writeLength += buffer.CompressionData.Length; index = sizeof(int); goto CHECK; } buffer.CompressionBuffer.TryFree(); } *(int *)bufferStart = index - sizeof(int); fileStream.Write(buffer.Buffer.Buffer, buffer.Buffer.StartIndex, index); writeLength += index; index = sizeof(int); goto CHECK; } } if (index != sizeof(int)) { if (index > Config.MinCompressSize) { if (AutoCSer.IO.Compression.DeflateCompressor.Get(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + sizeof(int), index - sizeof(int), ref buffer.CompressionBuffer, ref buffer.CompressionData, sizeof(int) * 2, sizeof(int) * 2)) { writeCompression(ref buffer.CompressionData, index - sizeof(int)); buffer.CompressionBuffer.TryFree(); writeLength += buffer.CompressionData.Length; goto FLUSH; } buffer.CompressionBuffer.TryFree(); } *(int *)bufferStart = index - sizeof(int); fileStream.Write(buffer.Buffer.Buffer, buffer.Buffer.StartIndex, index); writeLength += index; } FLUSH: fileStream.Flush(true); FileLength += writeLength; isError = false; } } finally { buffer.Free(); snapshot = null; if (isError) { cache.TcpServer.CallQueue.Add(new ServerCall.CacheManager(cache, ServerCall.CacheManagerServerCallType.CreateNewFileStreamError)); if (fileStream != null) { fileStream.Dispose(); } } } if (!isError) { writeQueue(); } }
/// <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(); } } }
/// <summary> /// 写入数据 /// </summary> /// <returns></returns> private bool write() { Buffer data = BufferLink.GetClear(); if (data != null) { FileBuffers buffer = default(FileBuffers); bufferPool.Get(ref buffer.Buffer); long writeLength = 0; try { fixed(byte *bufferFixed = buffer.Buffer.Buffer) { byte *bufferStart = bufferFixed + buffer.Buffer.StartIndex; int index = sizeof(int), bigBufferSize; START: if (data.Array.Length + index <= buffer.Buffer.Length) { if ((data = data.Copy(ref buffer.Buffer, ref index) ?? BufferLink.GetClear()) != null) { goto START; } } else if (index == sizeof(int)) { if (bigBuffer.Length < (bigBufferSize = data.Array.Length + sizeof(int))) { bigBuffer = new byte[Math.Max(bigBufferSize, bigBuffer.Length << 1)]; fixed(byte *bigBufferFixed = bigBuffer) { data = data.Copy(bigBuffer); if (bigBufferSize > Config.MinCompressSize) { if (AutoCSer.IO.Compression.DeflateCompressor.Get(bigBuffer, sizeof(int), bigBufferSize - sizeof(int), ref buffer.CompressionBuffer, ref buffer.CompressionData, sizeof(int) * 2, sizeof(int) * 2)) { writeCompression(ref buffer.CompressionData, bigBufferSize - sizeof(int)); buffer.CompressionBuffer.TryFree(); writeLength += buffer.CompressionData.Length; if (data == null && (data = BufferLink.GetClear()) == null) { return(true); } index = sizeof(int); goto START; } buffer.CompressionBuffer.TryFree(); } *(int *)bigBufferFixed = bigBufferSize - sizeof(int); } fileStream.Write(bigBuffer, 0, bigBufferSize); writeLength += bigBufferSize; if (data == null && (data = BufferLink.GetClear()) == null) return(true); } index = sizeof(int); goto START; } if (index > Config.MinCompressSize) { if (AutoCSer.IO.Compression.DeflateCompressor.Get(buffer.Buffer.Buffer, buffer.Buffer.StartIndex + sizeof(int), index - sizeof(int), ref buffer.CompressionBuffer, ref buffer.CompressionData, sizeof(int) * 2, sizeof(int) * 2)) { writeCompression(ref buffer.CompressionData, index - sizeof(int)); buffer.CompressionBuffer.TryFree(); writeLength += buffer.CompressionData.Length; if (data == null && (data = BufferLink.GetClear()) == null) { return(true); } index = sizeof(int); goto START; } buffer.CompressionBuffer.TryFree(); } *(int *)bufferStart = index - sizeof(int); fileStream.Write(buffer.Buffer.Buffer, buffer.Buffer.StartIndex, index); writeLength += index; if (data == null && (data = BufferLink.GetClear()) == null) { return(true); } index = sizeof(int); goto START; } } catch (Exception error) { writeLength = 0; AutoCSer.Log.Pub.Log.Add(Log.LogType.Fatal, error); fileStream.Dispose(); return(false); } finally { buffer.Free(); if (writeLength != 0) { fileStream.Flush(true); FileLength += writeLength; for (FileReader reader = Readers.End; reader != null; reader = reader.DoubleLinkPrevious) { isTryRead |= reader.TryRead(); } } } } return(true); }