0 votes
by (250 points)

private void VNotifier_GetContentSurrogate(object sender, GetContentEventArgs e)
{
    if ((e.ContentParameters.AccessType.HasFlag(NodeContentAccess.Write)) && (e.Node.Exists()))
    {
        e.Node.Context = @"E:\Testdaten\TEMP\" + System.Guid.NewGuid().ToString("N");
        var vStream = new System.IO.FileStream(e.Node.Context as string, System.IO.FileMode.CreateNew, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None);
        e.ResultContent =  NodeContent.CreateDelayedWriteContent(vStream);
        e.MarkAsHandled();
    }
}

Applies to: File Server, Rebex SFTP

1 Answer

0 votes
by (75.8k points)

private class CloseNotifyingFileStream : System.IO.FileStream
{
    /// <summary>
    /// Raised before the stream is disposed.
    /// </summary>
    public EventHandler<EventArgs> Closing;

    /// <summary>
    /// Raised after the stream is closed.
    /// </summary>
    public EventHandler<EventArgs> Closed;

    public CloseNotifyingFileStream(string path, FileMode mode, FileAccess access, FileShare share) : base(path, mode, access, share)
    {
    }

    protected override void Dispose(bool disposing)
    {
        try
        {
            var closing = Closing;
            if (closing != null) closing(this, EventArgs.Empty);
        }
        finally
        {
            base.Dispose(disposing);
        }

        var closed = Closed;
        if (closed != null) closed(this, EventArgs.Empty);
    }
}

provider.GetFileSystemNotifier().GetContentSurrogate += (s, e) =>
{
    if ((e.ContentParameters.AccessType.HasFlag(NodeContentAccess.Write)) && (e.Node.Exists()))
    {
        e.Node.Context = @"E:\Testdaten\TEMP\" + System.Guid.NewGuid().ToString("N");
        var vStream = new CloseNotifyingFileStream(e.Node.Context as string, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None);
        var content = NodeContent.CreateDelayedWriteContent(vStream);

        vStream.Closing += (_, __) =>
        {
            Console.WriteLine("Closing {0} (length={1}).", vStream.Name, vStream.Length);

            // inform original node about the change => invokes the SetContentSurrogate event
            e.Node.SetContent(content);
        };

        vStream.Closed += (_, __) =>
        {
            Console.WriteLine("Closed {0}.", vStream.Name);

            // we don't need the file anymore
            File.Delete(vStream.Name);
        };

        e.ResultContent = content;
        e.MarkAsHandled();
    }
};
by (250 points)
Thank you very much...

One question though: would this custom-stream-based workaround still deliver a correct value for WasStreamClosedForcefully ?

Thanks in advance.
by (75.8k points)
Yes, it still should deliver the correct WasStreamClosedForcefully value.

If you for example do the following in the CloseNotifyingFileStream, the SetContentSurrogate event will be fired with WasStreamClosedForcefully=true.

    public override void Write(byte[] array, int offset, int count)
    {
        throw new InvalidOperationException("Error during write.");
    }
by (250 points)
I tried something similar what you describe (throw new FileSystemException) and WasStreamClosedForcefully was false unfortunately :-(
by (75.8k points)
I have tried to throw FileSystemException as well and I still get the correct value.

Can you please send us the code fragment to reproduce the behavior?
Probably all provider.GetFileSystemNotifier() handlers + your implementation fo the CloseNotifyingFileStream class.

It seems that you are doing something more (somewhere else), which changes the behavior.

You can either post it here or send it to support@rebex.net.
...