servuo/Server/Persistence/SequentialFileWriter.cs
VitaNex f840e50340 Updated .editorconfig file with advanced configuration settings that will help maintain user code style and best practices with most IDE's.
Complete core housekeeping operation using "Profile 1" with new .editorconfig settings.
2021-01-15 12:51:10 -08:00

135 lines
3.3 KiB
C#

/***************************************************************************
* SequentialFileWriter.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id: SequentialFileWriter.cs 4 2006-06-15 04:28:39Z mark $
*
***************************************************************************/
/***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
using System.IO;
namespace Server
{
public sealed class SequentialFileWriter : Stream
{
private readonly SaveMetrics metrics;
private FileStream fileStream;
private FileQueue fileQueue;
private AsyncCallback writeCallback;
public SequentialFileWriter(string path, SaveMetrics metrics)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
this.metrics = metrics;
fileStream = FileOperations.OpenSequentialStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
fileQueue = new FileQueue(
Math.Max(1, FileOperations.Concurrency),
FileCallback);
}
public override long Position
{
get => fileQueue.Position;
set => throw new InvalidOperationException();
}
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length => Position;
public override void Write(byte[] buffer, int offset, int size)
{
fileQueue.Enqueue(buffer, offset, size);
}
public override void Flush()
{
fileQueue.Flush();
fileStream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new InvalidOperationException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new InvalidOperationException();
}
public override void SetLength(long value)
{
fileStream.SetLength(value);
}
protected override void Dispose(bool disposing)
{
if (fileStream != null)
{
Flush();
fileQueue.Dispose();
fileQueue = null;
fileStream.Close();
fileStream = null;
}
base.Dispose(disposing);
}
private void FileCallback(FileQueue.Chunk chunk)
{
if (FileOperations.AreSynchronous)
{
fileStream.Write(chunk.Buffer, chunk.Offset, chunk.Size);
if (metrics != null)
{
metrics.OnFileWritten(chunk.Size);
}
chunk.Commit();
}
else
{
if (writeCallback == null)
{
writeCallback = OnWrite;
}
fileStream.BeginWrite(chunk.Buffer, chunk.Offset, chunk.Size, writeCallback, chunk);
}
}
private void OnWrite(IAsyncResult asyncResult)
{
var chunk = asyncResult.AsyncState as FileQueue.Chunk;
fileStream.EndWrite(asyncResult);
if (metrics != null)
{
metrics.OnFileWritten(chunk.Size);
}
chunk.Commit();
}
}
}