public void TestStreamCanI() { Stream stream; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { using (stream = cache.Open()) { Assert.IsTrue(stream.CanRead); Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } using (stream = ((IFactory <Stream>)cache).Create()) { Assert.IsTrue(stream.CanRead); Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } using (stream = cache.Open(FileAccess.Read)) { Assert.IsTrue(stream.CanRead); Assert.IsFalse(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } using (stream = cache.Open(FileAccess.Write)) { Assert.IsFalse(stream.CanRead); Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } } }
public void TestCacheRecoverAbandondStream() { Stream stream; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { if (true) { stream = cache.Open(); stream.Write(new byte[100], 25, 55); stream = null;//simulated "accidental" object abandonment... i.e. someone does something stupid. } GC.Collect(0, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); Thread t = new Thread( delegate() { using (stream = cache.Open(FileAccess.Read)) { Assert.AreEqual(new byte[55], IOStream.ReadAllBytes(stream)); } } ); t.IsBackground = true; t.Start(); Assert.IsTrue(t.Join(1000)); } }
private void ReadByteRange(Guid transferId, Salt sessionKey, string location, StreamCache streams, long offset, int count) { using (Message req = new Message(TransferState.DownloadBytesRequest, transferId, _publicKey, s => sessionKey)) { req.Write(location); req.Write(offset); req.Write(count); Stream response = SendPayload(req, location, req.ToStream(_privateKey)); using (Message rsp = new Message(response, _privateKey, s => sessionKey)) { Check.Assert <InvalidOperationException>(rsp.State == TransferState.DownloadBytesResponse); byte[] bytes = rsp.ReadBytes(100 * 1000 * 1024); Check.Assert <InvalidOperationException>(bytes.Length == count); rsp.VerifySignature(_publicKey); using (Stream io = streams.Open(FileAccess.Write)) { io.Seek(offset, SeekOrigin.Begin); io.Write(bytes, 0, count); } } } }
public void TestStreamCacheDisposes() { Stream stream; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { stream = cache.Open(); Assert.IsTrue(stream.CanRead && stream.CanWrite); } Assert.IsFalse(stream.CanRead || stream.CanWrite); try { stream.ReadByte(); Assert.Fail(); }/* why InvalidOperation?, the underlying stream was disposed, not the stream itself */ catch (InvalidOperationException) { } stream.Dispose(); try { stream.WriteByte(1); Assert.Fail(); }/* Now it's been disposed */ catch (ObjectDisposedException) { } }
public void TestStreamCanI() { Stream stream; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { using (stream = cache.Open()) { Assert.IsTrue(stream.CanRead); Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } using (stream = ((IFactory<Stream>)cache).Create()) { Assert.IsTrue(stream.CanRead); Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } using (stream = cache.Open(FileAccess.Read)) { Assert.IsTrue(stream.CanRead); Assert.IsFalse(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } using (stream = cache.Open(FileAccess.Write)) { Assert.IsFalse(stream.CanRead); Assert.IsTrue(stream.CanWrite); Assert.IsTrue(stream.CanSeek); } } }
public void TestCacheLimit() { bool finished = false; using (SharedMemoryStream shared = new SharedMemoryStream()) using (StreamCache cache = new StreamCache(shared, 1)) { ManualResetEvent ready = new ManualResetEvent(false); ManualResetEvent release = new ManualResetEvent(false); Thread t = new Thread( delegate() { using (Stream stream = cache.Open(FileAccess.ReadWrite)) { stream.Write(new byte[50], 0, 50); ready.Set(); release.WaitOne(); stream.Write(new byte[50], 0, 50); GC.KeepAlive(stream); finished = true; } } ); t.IsBackground = true; t.Start(); Assert.IsTrue(ready.WaitOne()); Assert.AreEqual(50, shared.Length); new Thread( delegate() { Thread.Sleep(10); release.Set(); } ).Start(); Assert.IsFalse(finished); using (Stream stream = cache.Open()) { Assert.IsTrue(finished); Assert.IsTrue(release.WaitOne(0, false)); Assert.AreEqual(100, stream.Read(new byte[100], 0, 100)); } Assert.IsTrue(t.Join(1000)); } }
public void TestStreamReadWrite() { Stream stream; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { using (stream = cache.Open()) { stream.Write(new byte[100], 25, 55); stream.Close(); } using (stream = cache.Open(FileAccess.Read)) { Assert.AreEqual(new byte[55], IOStream.ReadAllBytes(stream)); } } }
public void ChangeLogFile() { lock (this) { if (file != null) { logFiles.Close(file); } file = logFiles.Open(LogPath(pathFormat), true); } }
public void ChangeLogFile() { lock (this) { if (file != null) { logFiles.Close(file); } var path = LogPath(pathFormat); file = logFiles.Open(path, WillAppend(path)); } }
public void TestCacheRecoverAbandondMutex() { Stream stream = null; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { Thread t = new Thread(delegate() { stream = cache.Open(FileAccess.Read); }); t.Start(); t.Join(); //The exit of this thread releases the stream... using (Stream another = cache.Open()) { Assert.AreEqual(0, another.Position); // Another thread can then objtain the same underlying stream... we can demonstrate // this by the fact that the Position property affects both streams. stream.Position = 100; Assert.AreEqual(100, another.Position); } } }
public void TestFileStreamCache() { Stream stream; using (TempFile tempFile = new TempFile()) { using (StreamCache cache = new StreamCache(new FileStreamFactory(tempFile.TempPath, FileMode.Open))) { using (stream = cache.Open()) { stream.SetLength(100); stream.WriteByte(1); } } Assert.AreEqual(100, tempFile.Length); using (stream = tempFile.Open()) Assert.AreEqual(1, stream.ReadByte()); } }
private bool Download(string location, StreamCache output) { int maxMessageLength; long fileLength, bytesReceived = 0; Guid transferId = Guid.NewGuid(); byte[] serverKeyBits; byte[] nonce = GetNonce(transferId, location, out serverKeyBits); Hash hnonce = Hash.SHA256(nonce); //STEP 2: Create and send session key Salt clientKeyBits = new Salt(Salt.Size.b256); Salt sessionKey = SessionSecret(clientKeyBits, serverKeyBits); using (Message req = new Message(TransferState.DownloadRequest, transferId, _publicKey, NoSession)) { req.Write(hnonce.ToArray()); req.Write(location); req.Write(clientKeyBits.ToArray()); Stream response = SendPayload(req, location, req.ToStream(_privateKey)); using (Message rsp = new Message(response, _privateKey, s=>sessionKey)) { Check.Assert<InvalidOperationException>(rsp.State == TransferState.DownloadResponse); maxMessageLength = Check.InRange(rsp.ReadInt32(), 0, int.MaxValue); fileLength = Check.InRange(rsp.ReadInt64(), 0, 0x00FFFFFFFFFFFFFFL); byte[] bytes = rsp.ReadBytes(100 * 1000 * 1024); rsp.VerifySignature(_publicKey); using(Stream io = output.Open(FileAccess.Write)) { io.SetLength(fileLength); if (bytes.Length > 0) { io.Seek(0, SeekOrigin.Begin); io.Write(bytes, 0, bytes.Length); bytesReceived += bytes.Length; } } } } //STEP 3...n: Continue downloading other chunks of the file if (bytesReceived < fileLength) { bool[] failed = new bool[1]; using (WorkQueue queue = new WorkQueue(LimitThreads)) { queue.OnError += (o, e) => { failed[0] = true; }; while (bytesReceived < fileLength && !failed[0] && !_abort.WaitOne(0, false)) { int len = (int) Math.Min(fileLength - bytesReceived, maxMessageLength); BytesToRead task = new BytesToRead( this, LimitThreads, transferId, sessionKey, location, output, bytesReceived, len); queue.Enqueue(task.Send); OnProgressChanged(location, bytesReceived, fileLength); bytesReceived += len; } queue.Complete(true, failed[0] ? 5000 : 7200000); } if (_abort.WaitOne(0, false)) return false; Check.Assert<InvalidDataException>(failed[0] == false); // STEP 4: Complete the transfer using (Message req = new Message(TransferState.DownloadCompleteRequest, transferId, _publicKey, s => sessionKey)) { SendPayload(req, location, req.ToStream(_privateKey)).Dispose(); } } OnProgressChanged(location, fileLength, fileLength); return true; }
public void TestCacheRecoverAbandondStream() { Stream stream; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { if(true) { stream = cache.Open(); stream.Write(new byte[100], 25, 55); stream = null;//simulated "accidental" object abandonment... i.e. someone does something stupid. } GC.Collect(0, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); Thread t = new Thread( delegate() { using (stream = cache.Open(FileAccess.Read)) { Assert.AreEqual(new byte[55], IOStream.ReadAllBytes(stream)); } } ); t.IsBackground = true; t.Start(); Assert.IsTrue(t.Join(1000)); } }
public void TestCacheRecoverAbandondMutex() { Stream stream = null; using (StreamCache cache = new StreamCache(new SharedMemoryStream(), 1)) { Thread t = new Thread( delegate() { stream = cache.Open(FileAccess.Read); } ); t.Start(); t.Join(); //The exit of this thread releases the stream... using (Stream another = cache.Open()) { Assert.AreEqual(0, another.Position); // Another thread can then objtain the same underlying stream... we can demonstrate // this by the fact that the Position property affects both streams. stream.Position = 100; Assert.AreEqual(100, another.Position); } } }
/// <summary> Internal use to specify aligned IO when using NoBuffering file option </summary> protected FragmentedFile(IFactory<Stream> streamFactory, int blockSize, int growthRate, int cacheLimit, FileOptions options) { _useAlignedIo = (options & NoBuffering) == NoBuffering; _streamCache = new StreamCache(streamFactory, cacheLimit); _header = new FileBlock(blockSize, _useAlignedIo); _syncFreeBlock = new object(); try { long fallocated; bool canWrite; using (Stream s = _streamCache.Open(FileAccess.ReadWrite)) { canWrite = s.CanWrite; if (!s.CanRead) throw new InvalidOperationException("The stream does not support Read access."); _header.Read(s, blockSize); if ((_header.Flags & ~BlockFlags.HeaderFilter) != BlockFlags.HeaderFlags) throw new InvalidDataException(); _nextFree = _header.NextBlockId; SetBlockSize(_header.Length, out _blockSize, out _maskVersion, out _maskOffset); if (blockSize != _blockSize) throw new ArgumentOutOfRangeException("blockSize"); fallocated = LastAllocated(s); _reallocSize = growthRate * _blockSize; if (canWrite) { s.Position = 0; _header.NextBlockId = long.MinValue; _header.Write(s, FileBlock.HeaderSize); } } if (canWrite) { if ((_header.Flags & BlockFlags.ResizingFile) == BlockFlags.ResizingFile && _nextFree > 0) ResizeFile(_nextFree, Math.Max(fallocated, _nextFree + _reallocSize)); if (_nextFree == long.MinValue) _nextFree = RecoverFreeBlocks(); } } catch { _streamCache.Dispose(); throw; } }
private bool Download(string location, StreamCache output) { int maxMessageLength; long fileLength, bytesReceived = 0; Guid transferId = Guid.NewGuid(); byte[] serverKeyBits; byte[] nonce = GetNonce(transferId, location, out serverKeyBits); Hash hnonce = Hash.SHA256(nonce); //STEP 2: Create and send session key Salt clientKeyBits = new Salt(Salt.Size.b256); Salt sessionKey = SessionSecret(clientKeyBits, serverKeyBits); using (Message req = new Message(TransferState.DownloadRequest, transferId, _publicKey, NoSession)) { req.Write(hnonce.ToArray()); req.Write(location); req.Write(clientKeyBits.ToArray()); Stream response = SendPayload(req, location, req.ToStream(_privateKey)); using (Message rsp = new Message(response, _privateKey, s => sessionKey)) { Check.Assert <InvalidOperationException>(rsp.State == TransferState.DownloadResponse); maxMessageLength = Check.InRange(rsp.ReadInt32(), 0, int.MaxValue); fileLength = Check.InRange(rsp.ReadInt64(), 0, 0x00FFFFFFFFFFFFFFL); byte[] bytes = rsp.ReadBytes(100 * 1000 * 1024); rsp.VerifySignature(_publicKey); using (Stream io = output.Open(FileAccess.Write)) { io.SetLength(fileLength); if (bytes.Length > 0) { io.Seek(0, SeekOrigin.Begin); io.Write(bytes, 0, bytes.Length); bytesReceived += bytes.Length; } } } } //STEP 3...n: Continue downloading other chunks of the file if (bytesReceived < fileLength) { bool[] failed = new bool[1]; using (WorkQueue queue = new WorkQueue(LimitThreads)) { queue.OnError += (o, e) => { failed[0] = true; }; while (bytesReceived < fileLength && !failed[0] && !_abort.WaitOne(0, false)) { int len = (int)Math.Min(fileLength - bytesReceived, maxMessageLength); BytesToRead task = new BytesToRead( this, LimitThreads, transferId, sessionKey, location, output, bytesReceived, len); queue.Enqueue(task.Send); OnProgressChanged(location, bytesReceived, fileLength); bytesReceived += len; } queue.Complete(true, failed[0] ? 5000 : 7200000); } if (_abort.WaitOne(0, false)) { return(false); } Check.Assert <InvalidDataException>(failed[0] == false); // STEP 4: Complete the transfer using (Message req = new Message(TransferState.DownloadCompleteRequest, transferId, _publicKey, s => sessionKey)) { SendPayload(req, location, req.ToStream(_privateKey)).Dispose(); } } OnProgressChanged(location, fileLength, fileLength); return(true); }
private void ReadByteRange(Guid transferId, Salt sessionKey, string location, StreamCache streams, long offset, int count) { using (Message req = new Message(TransferState.DownloadBytesRequest, transferId, _publicKey, s=>sessionKey)) { req.Write(location); req.Write(offset); req.Write(count); Stream response = SendPayload(req, location, req.ToStream(_privateKey)); using (Message rsp = new Message(response, _privateKey, s=>sessionKey)) { Check.Assert<InvalidOperationException>(rsp.State == TransferState.DownloadBytesResponse); byte[] bytes = rsp.ReadBytes(100 * 1000 * 1024); Check.Assert<InvalidOperationException>(bytes.Length == count); rsp.VerifySignature(_publicKey); using(Stream io = streams.Open(FileAccess.Write)) { io.Seek(offset, SeekOrigin.Begin); io.Write(bytes, 0, count); } } } }