public Result <string> TryAcquireLease(string containerName, string blobName) { var path = Path.Combine(_root, containerName, blobName); try { var file = new FileInfo(path); if (!file.Exists) { return(null); } using (var stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (var epStream = new MetadataPrefixStream(stream)) { var flags = epStream.ReadFlags(); if ((flags & 0x1) == 0x1) { // already locked, conflict return(Result <string> .CreateError("Conflict")); } epStream.WriteFlags((byte)(flags | 0x1)); return(Result.CreateSuccess(epStream.ReadETag())); } } catch (FileNotFoundException) { return(Result <string> .CreateError("NotFound")); } catch (DirectoryNotFoundException) { return(Result <string> .CreateError("NotFound")); } }
public string GetBlobEtag(string containerName, string blobName) { var path = Path.Combine(_root, containerName, blobName); try { var file = new FileInfo(path); if (!file.Exists) { return(null); } using (var stream = file.OpenRead()) using (var epStream = new MetadataPrefixStream(stream)) { return(epStream.ReadETag()); } } catch (FileNotFoundException) { return(null); } catch (DirectoryNotFoundException) { return(null); } }
public Maybe <object> GetBlob(string containerName, string blobName, Type type, out string etag, IDataSerializer serializer = null) { var path = Path.Combine(_root, containerName, blobName); try { var file = new FileInfo(path); if (!file.Exists) { etag = null; return(Maybe <object> .Empty); } using (var stream = file.OpenRead()) using (var epStream = new MetadataPrefixStream(stream)) { etag = epStream.ReadETag(); var deserialized = (serializer ?? _defaultSerializer).TryDeserialize(epStream, type); return(deserialized.IsSuccess ? new Maybe <object>(deserialized.Value) : Maybe <object> .Empty); } } catch (FileNotFoundException) { etag = null; return(Maybe <object> .Empty); } catch (DirectoryNotFoundException) { etag = null; return(Maybe <object> .Empty); } }
/// <returns>New ETag</returns> private string WriteToStream(MetadataPrefixStream stream, object item, Type type, IDataSerializer serializer = null) { byte[] result; using (var resultStream = new MemoryStream()) { (serializer ?? _defaultSerializer).Serialize(item, resultStream, type); result = resultStream.ToArray(); } stream.Seek(0, SeekOrigin.Begin); stream.Write(result, 0, result.Length); stream.SetLength(result.Length); return(stream.WriteNewETag()); }
private string WriteToStream(MetadataPrefixStream stream, Stream item) { byte[] result; using (var resultStream = new MemoryStream()) { item.Position = 0; item.CopyTo(resultStream); result = resultStream.ToArray(); } stream.Seek(0, SeekOrigin.Begin); stream.Write(result, 0, result.Length); stream.SetLength(result.Length); stream.Seek(0, SeekOrigin.Begin); return(stream.WriteNewETag()); }
public Maybe <Stream> GetBlobStream(string containerName, string blobName, out string etag) { var path = Path.Combine(_root, containerName, blobName); try { var file = new FileInfo(path); if (!file.Exists) { etag = null; return(Maybe <Stream> .Empty); } using (var stream = file.OpenRead()) using (var epStream = new MetadataPrefixStream(stream)) { etag = epStream.ReadETag(); int length = (int)epStream.Length; epStream.Seek(0, SeekOrigin.Begin); var returnStream = new MemoryStream(length); byte[] buffer = new byte[8192]; int bytesRead = 1; while (length > 0 && bytesRead > 0) { bytesRead = epStream.Read(buffer, 0, Math.Min(length, buffer.Length)); returnStream.Write(buffer, 0, bytesRead); length -= bytesRead; } returnStream.Position = 0; return(new Maybe <Stream>(returnStream)); } } catch (FileNotFoundException) { etag = null; return(Maybe <Stream> .Empty); } catch (DirectoryNotFoundException) { etag = null; return(Maybe <Stream> .Empty); } }
public Result <string> TryRenewLease(string containerName, string blobName, string leaseId) { var path = Path.Combine(_root, containerName, blobName); try { var file = new FileInfo(path); if (!file.Exists) { return(null); } using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None)) using (var epStream = new MetadataPrefixStream(stream)) { var flags = epStream.ReadFlags(); if ((flags & 0x1) == 0x0) { // not locked return(Result <string> .CreateError("NotFound")); } if (leaseId != epStream.ReadETag()) { // locked by another leaseId, conflict return(Result <string> .CreateError("Conflict")); } return(Result.CreateSuccess("OK")); } } catch (FileNotFoundException) { return(Result <string> .CreateError("NotFound")); } catch (DirectoryNotFoundException) { return(Result <string> .CreateError("NotFound")); } }
public Maybe <XElement> GetBlobXml(string containerName, string blobName, out string etag, IDataSerializer serializer = null) { var formatter = (serializer ?? _defaultSerializer) as IIntermediateDataSerializer; if (formatter == null) { etag = null; return(Maybe <XElement> .Empty); } var path = Path.Combine(_root, containerName, blobName); try { var file = new FileInfo(path); if (!file.Exists) { etag = null; return(Maybe <XElement> .Empty); } using (var stream = file.OpenRead()) using (var epStream = new MetadataPrefixStream(stream)) { etag = epStream.ReadETag(); var unpacked = formatter.TryUnpackXml(epStream); return(unpacked.IsSuccess ? new Maybe <XElement>(unpacked.Value) : Maybe <XElement> .Empty); } } catch (FileNotFoundException) { etag = null; return(Maybe <XElement> .Empty); } catch (DirectoryNotFoundException) { etag = null; return(Maybe <XElement> .Empty); } }
public Maybe <T> UpsertBlobOrSkip <T>( string containerName, string blobName, Func <Maybe <T> > insert, Func <T, Maybe <T> > update, IDataSerializer serializer = null) { var path = Path.Combine(_root, containerName, blobName); var folder = Path.GetDirectoryName(path); if (folder != null && !Directory.Exists(folder)) { Directory.CreateDirectory(folder); } var optimisticPolicy = _policies.OptimisticConcurrency(); int retryCount = 0; while (true) { try { using (var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) using (var epStream = new MetadataPrefixStream(file)) { var input = Maybe <T> .Empty; if (epStream.Length != 0) { var deserialized = (serializer ?? _defaultSerializer).TryDeserializeAs <T>(epStream); if (deserialized.IsSuccess) { input = deserialized.Value; } } var output = input.HasValue ? update(input.Value) : insert(); if (output.HasValue) { WriteToStream(epStream, output.Value, typeof(T), serializer); return(output.Value); } if (!input.HasValue) { epStream.Close(); file.Close(); File.Delete(path); } return(Maybe <T> .Empty); } } catch (IOException exception) { TimeSpan retryInterval; if (!optimisticPolicy.ShouldRetry(retryCount++, 0, exception, out retryInterval, null)) { throw; } // Retry Thread.Sleep(retryInterval); } } }
bool PutBlob(string containerName, string blobName, object item, Type type, bool overwrite, string expectedEtag, out string etag, IDataSerializer serializer = null) { var path = Path.Combine(_root, containerName, blobName); var folder = Path.GetDirectoryName(path); if (folder != null && !Directory.Exists(folder)) { Directory.CreateDirectory(folder); } var file = new FileInfo(path); if (overwrite) { // retry in case it is currently locked by another operation var optimisticPolicy = _policies.OptimisticConcurrency(); int retryCount = 0; while (true) { try { using (var stream = file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) using (var epStream = new MetadataPrefixStream(stream)) { if (!string.IsNullOrEmpty(expectedEtag) && epStream.ReadETag() != expectedEtag) { etag = null; return(false); } etag = WriteToStream(epStream, item, type, serializer); } return(true); } catch (IOException exception) { TimeSpan retryInterval; if (!optimisticPolicy.ShouldRetry(retryCount++, 0, exception, out retryInterval, null)) { throw; } // Retry Thread.Sleep(retryInterval); } } } // no need to retry in the non-overwrite case, since being locked implies the file already exist anyway try { using (var stream = file.Open(FileMode.CreateNew, FileAccess.Write, FileShare.None)) using (var epStream = new MetadataPrefixStream(stream)) { etag = WriteToStream(epStream, item, type, serializer); } return(true); } catch (IOException) { etag = null; return(false); } }