예제 #1
0
        public async Task <IActionResult> Get(string identifier)
        {
            if (!ArchiveId.Accepts(identifier))
            {
                return(BadRequest());
            }

            var archiveId = new ArchiveId(identifier);
            var blobName  = new BlobName(archiveId.ToString());

            if (!await _client.BlobExistsAsync(blobName, HttpContext.RequestAborted))
            {
                return(NotFound());
            }

            var blob = await _client.GetBlobAsync(blobName, HttpContext.RequestAborted);

            var filename = blob.Metadata
                           .Single(pair => pair.Key == new MetadataKey("filename"));

            return(new FileCallbackResult(
                       new MediaTypeHeaderValue("application/zip"),
                       async(stream, actionContext) =>
            {
                using (var blobStream = await blob.OpenAsync(actionContext.HttpContext.RequestAborted))
                {
                    await blobStream.CopyToAsync(stream, actionContext.HttpContext.RequestAborted);
                }
            })
            {
                FileDownloadName = filename.Value
            });
        }
예제 #2
0
 /// <summary>
 /// Gets the hash code
 /// </summary>
 /// <returns>Hash code</returns>
 public override int GetHashCode()
 {
     unchecked // Overflow is fine, just wrap
     {
         var hashCode = 41;
         // Suitable nullity checks etc, of course :)
         if (BlobName != null)
         {
             hashCode = hashCode * 59 + BlobName.GetHashCode();
         }
         if (ContainerName != null)
         {
             hashCode = hashCode * 59 + ContainerName.GetHashCode();
         }
         if (CorrelationId != null)
         {
             hashCode = hashCode * 59 + CorrelationId.GetHashCode();
         }
         if (HostName != null)
         {
             hashCode = hashCode * 59 + HostName.GetHashCode();
         }
         if (SasToken != null)
         {
             hashCode = hashCode * 59 + SasToken.GetHashCode();
         }
         return(hashCode);
     }
 }
예제 #3
0
        public async Task CreateBlobAsync(
            BlobName name,
            Metadata metadata,
            ContentType contentType,
            Stream content,
            CancellationToken cancellationToken = default)
        {
            var file = new FileInfo(Path.Combine(_directory.FullName, FileName.From(name)));

            if (file.Exists)
            {
                throw new BlobAlreadyExistsException(name);
            }

            using (var fileStream = file.OpenWrite())
            {
                using (var writer = new BinaryWriter(fileStream, Encoding.UTF8, true))
                {
                    writer.Write(contentType.ToString()); // content type
                    writer.Write(metadata.Count);         // count of metadatum
                    foreach (var metadatum in metadata)
                    {
                        writer.Write(metadatum.Key.ToString());      // key
                        writer.Write(metadatum.Value?.Length ?? -1); // length of value - null is indicated using -1
                        if (metadatum.Value != null)
                        {
                            writer.Write(metadatum.Value); // non null value
                        }
                    }
                }
                content.CopyTo(fileStream);
                await fileStream.FlushAsync(cancellationToken);
            }
        }
예제 #4
0
        public async Task CreateBlobAsync(BlobName name, Metadata metadata, ContentType contentType, Stream content,
                                          CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                await Task.FromCanceled(cancellationToken);
            }

            async Task <byte[]> Copy(Stream input, CancellationToken ct)
            {
                using (var output = new MemoryStream())
                {
                    await input.CopyToAsync(output, 1024, ct);

                    return(output.ToArray());
                }
            }

            var buffer = await Copy(content, cancellationToken);

            if (!_storage.TryAdd(name, new BlobObject(name, metadata, contentType,
                                                      ct =>
            {
                if (_storage.ContainsKey(name))
                {
                    return(Task.FromResult <Stream>(new ForwardOnlyStream(new MemoryStream(buffer, false))));
                }

                throw new BlobNotFoundException(name);
            })))
            {
                throw new BlobAlreadyExistsException(name);
            }
        }
예제 #5
0
        public async Task DeleteBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            var nameParameter = CreateSqlParameter(
                "@Name",
                SqlDbType.NVarChar,
                BlobName.MaxLength,
                name.ToString());

            using (var connection = new SqlConnection(_builder.ConnectionString))
            {
                await connection.OpenAsync(cancellationToken);

                using (var transaction = connection.BeginTransaction(IsolationLevel.Snapshot))
                {
                    using (var command = new SqlCommand(_text.DeleteBlob(), connection, transaction)
                    {
                        CommandType = CommandType.Text,
                        Parameters = { nameParameter }
                    })
                    {
                        await command.ExecuteNonQueryAsync(cancellationToken);
                    }

                    transaction.Commit();
                }
            }
        }
예제 #6
0
        public async Task CreateBlobAsync(
            BlobName name,
            Metadata metadata,
            ContentType contentType,
            Stream content,
            CancellationToken cancellationToken = default)
        {
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }

            var nameParameter = CreateSqlParameter(
                "@Name",
                SqlDbType.NVarChar,
                BlobName.MaxLength,
                name.ToString());
            var metadataParameter = CreateSqlParameter(
                "@Metadata",
                SqlDbType.NVarChar,
                -1,
                MetadataToString(metadata));
            var contentTypeParameter = CreateSqlParameter(
                "@ContentType",
                SqlDbType.NVarChar,
                ContentType.MaxLength,
                contentType.ToString());
            var contentParameter = CreateSqlParameter(
                "@Content",
                SqlDbType.VarBinary,
                -1,
                content);

            using (var connection = new SqlConnection(_builder.ConnectionString))
            {
                await connection.OpenAsync(cancellationToken);

                using (var transaction = connection.BeginTransaction(IsolationLevel.Snapshot))
                {
                    using (var command = new SqlCommand(_text.CreateBlob(), connection, transaction)
                    {
                        CommandType = CommandType.Text,
                        Parameters = { nameParameter, metadataParameter, contentTypeParameter, contentParameter }
                    })
                    {
                        try
                        {
                            await command.ExecuteNonQueryAsync(cancellationToken);
                        }
                        catch (SqlException exception) when(exception.Number == 2627)
                        {
                            throw new BlobAlreadyExistsException(name, exception);
                        }
                    }

                    transaction.Commit();
                }
            }
        }
예제 #7
0
 public async Task DeleteBlobAsync(BlobName name, CancellationToken cancellationToken = default)
 {
     await _client.DeleteObjectAsync(new DeleteObjectRequest
     {
         BucketName = _bucket,
         Key        = name.ToString()
     }, cancellationToken);
 }
예제 #8
0
 public Task <Result <TState> > ReadModifyWriteAsync <TState>(
     OperationContext context,
     BlobName fileName,
     Func <TState, TState> transform)
     where TState : new()
 {
     return(ReadModifyWriteAsync <TState, Unit>(context, fileName, current => (transform(current), Unit.Void)).SelectAsync(r => r.Value.NextState));
 }
예제 #9
0
        public Task <bool> BlobExistsAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <bool>(cancellationToken));
            }

            return(Task.FromResult(_storage.ContainsKey(name)));
        }
예제 #10
0
        public Task <bool> BlobExistsAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <bool>(cancellationToken));
            }
            var file = new FileInfo(Path.Combine(_directory.FullName, FileName.From(name)));

            return(Task.FromResult(file.Exists));
        }
예제 #11
0
        public Task DeleteBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            var file = new FileInfo(Path.Combine(_directory.FullName, FileName.From(name)));

            if (file.Exists)
            {
                file.Delete();
            }
            return(Task.CompletedTask);
        }
예제 #12
0
        public Task DeleteBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled(cancellationToken));
            }

            _storage.TryRemove(name, out _);
            return(Task.CompletedTask);
        }
예제 #13
0
        public string GetFileName()
        {
            string[] parts = BlobName.Split(':');
            if (parts.Length != 2)
            {
                throw new ApplicationException("Invalid BlobName:" + BlobName);
            }

            return(parts[1]);
        }
예제 #14
0
        public Task <BlobObject> GetBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <BlobObject>(cancellationToken));
            }

            var file = new FileInfo(Path.Combine(_directory.FullName, FileName.From(name)));

            if (!file.Exists)
            {
                return(Task.FromResult <BlobObject>(null));
            }

            using (var fileStream = file.OpenRead())
                using (var reader = new BinaryReader(fileStream, Encoding.UTF8))
                {
                    var metadata       = Metadata.None;
                    var contentType    = ContentType.Parse(reader.ReadString());
                    var metadatumCount = reader.ReadInt32();
                    for (var index = 0; index < metadatumCount; index++)
                    {
                        var key         = new MetadataKey(reader.ReadString());
                        var valueLength = reader.ReadInt32();
                        var value       = valueLength != -1 ? reader.ReadString() : null;
                        metadata = metadata.Add(new KeyValuePair <MetadataKey, string>(key, value));
                    }

                    return(Task.FromResult(new BlobObject(name, metadata, contentType, contentCancellationToken =>
                    {
                        if (!File.Exists(file.FullName))
                        {
                            throw new BlobNotFoundException(name);
                        }

                        var contentFileStream = file.OpenRead();
                        using (var contentReader = new BinaryReader(contentFileStream, Encoding.UTF8, true))
                        {
                            // skip over the metadata
                            contentReader.ReadString();
                            var contentMetadatumCount = contentReader.ReadInt32();
                            for (var index = 0; index < contentMetadatumCount; index++)
                            {
                                contentReader.ReadString();
                                var valueLength = contentReader.ReadInt32();
                                if (valueLength != -1)
                                {
                                    contentReader.ReadString();
                                }
                            }
                        }
                        return Task.FromResult <Stream>(new ForwardOnlyStream(contentFileStream));
                    })));
                }
        }
예제 #15
0
        public Task <BlobObject> GetBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <BlobObject>(cancellationToken));
            }

            return(_storage.TryGetValue(name, out var result)
                ? Task.FromResult(result)
                : Task.FromResult <BlobObject>(null));
        }
예제 #16
0
        public static string From(BlobName name)
        {
            var value   = name.ToString().ToCharArray();
            var builder = new StringBuilder(value.Length);

            for (var index = 0; index < value.Length; index++)
            {
                switch (value[index])
                {
                case '!':
                    builder.Append(Convert.ToByte('!').ToString("x"));
                    break;

                case '/':
                    builder.Append(Convert.ToByte('/').ToString("x"));
                    break;

                case '-':
                    builder.Append(Convert.ToByte('-').ToString("x"));
                    break;

                case '_':
                    builder.Append(Convert.ToByte('_').ToString("x"));
                    break;

                case '.':
                    builder.Append(Convert.ToByte('.').ToString("x"));
                    break;

                case '*':
                    builder.Append(Convert.ToByte('*').ToString("x"));
                    break;

                case '\'':
                    builder.Append(Convert.ToByte('\'').ToString("x"));
                    break;

                case '(':
                    builder.Append(Convert.ToByte('(').ToString("x"));
                    break;

                case ')':
                    builder.Append(Convert.ToByte(')').ToString("x"));
                    break;

                default:
                    builder.Append(value[index]);
                    break;
                }
            }
            return(builder.ToString());
        }
예제 #17
0
 public override int GetHashCode() =>
 BlobName.GetHashCode() ^
 CacheControl.GetHashCode() ^
 BlobContainerName.GetHashCode() ^
 ContentDisposition.GetHashCode() ^
 ContentEncoding.GetHashCode() ^
 ContentLanguage.GetHashCode() ^
 ContentType.GetHashCode() ^
 ExpiryTime.GetHashCode() ^
 Identifier.GetHashCode() ^
 IPRange.GetHashCode() ^
 Permissions.GetHashCode() ^
 Protocol.GetHashCode() ^
 StartTime.GetHashCode() ^
 Version.GetHashCode();
예제 #18
0
        private static async Task EnrichWithArchiveInformation(string archiveId,
                                                               RoadNetworkChangesArchiveInfo archiveInfo, IBlobClient client, CancellationToken ct)
        {
            var blobName = new BlobName(archiveId);

            if (await client.BlobExistsAsync(blobName, ct))
            {
                var blob = await client.GetBlobAsync(blobName, ct);

                archiveInfo.Available = true;
                archiveInfo.Filename  = blob.Metadata.Single(pair => pair.Key == new MetadataKey("filename")).Value;
            }
            else
            {
                archiveInfo.Available = false;
                archiveInfo.Filename  = "";
            }
        }
예제 #19
0
        public async Task <bool> BlobExistsAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            try
            {
                await _client.GetObjectAsync(new GetObjectRequest
                {
                    BucketName = _bucket,
                    Key        = name.ToString(),
                    ByteRange  = NoData
                }, cancellationToken);

                return(true);
            }
            catch (AmazonS3Exception exception) when(
                exception.ErrorType == ErrorType.Sender &&
                string.Equals(exception.ErrorCode, "NoSuchKey", StringComparison.OrdinalIgnoreCase))
            {
                return(false);
            }
        }
예제 #20
0
        public async Task <BlobObject> GetBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            try
            {
                var response = await _client.GetObjectAsync(new GetObjectRequest
                {
                    BucketName = _bucket,
                    Key        = name.ToString(),
                    ByteRange  = NoData
                }, cancellationToken);

                return(new BlobObject(
                           name,
                           ConvertMetadataFromMetadataCollection(response),
                           ContentType.Parse(response.Headers.ContentType),
                           async contentCancellationToken =>
                {
                    try
                    {
                        var contentResponse = await _client.GetObjectAsync(new GetObjectRequest
                        {
                            BucketName = _bucket,
                            Key = name.ToString()
                        }, contentCancellationToken);
                        return new ForwardOnlyStream(contentResponse.ResponseStream);
                    }
                    catch (AmazonS3Exception exception) when(
                        exception.ErrorType == ErrorType.Sender &&
                        string.Equals(exception.ErrorCode, "NoSuchKey", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new BlobNotFoundException(name, exception);
                    }
                }));
            }
            catch (AmazonS3Exception exception) when(
                exception.ErrorType == ErrorType.Sender &&
                string.Equals(exception.ErrorCode, "NoSuchKey", StringComparison.OrdinalIgnoreCase))
            {
                return(null);
            }
        }
        protected override void Write(LogEventInfo logEvent)
        {
            _client = _client ?? CloudStorageAccount.Parse(ConnectionString.Render(logEvent)).CreateCloudBlobClient();

            if (_client == null)
            {
                return;
            }

            var containerName = Container.Render(logEvent);
            var blobName      = BlobName.Render(logEvent);

            if (_container == null || _container.Name != containerName)
            {
                _container = _client.GetContainerReference(containerName);
                _container.CreateIfNotExistsAsync().Wait();
                _blob = null;
            }

            if (_blob == null || _blob.Name != blobName || _forceCheck)
            {
                _blob = _container.GetAppendBlobReference(blobName);

                if (!_blob.ExistsAsync().Result)
                {
                    try
                    {
                        _blob.Properties.ContentType = "text/plain";
                        _blob.CreateOrReplaceAsync().Wait();
                        _blob.SetPropertiesAsync().Wait();
                    }
                    catch (StorageException ex) when(ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.Conflict)
                    {
                        // to be expected
                    }
                }
            }

            _blob.AppendTextAsync(Layout.Render(logEvent) + "\r\n").Wait();
        }
예제 #22
0
        public async Task <(Messages.RoadNetworkSnapshot snapshot, int version)> ReadSnapshot(CancellationToken cancellationToken)
        {
            if (!await _client.BlobExistsAsync(SnapshotHead, cancellationToken))
            {
                return(null, ExpectedVersion.NoStream);
            }

            var snapshotHeadBlob = await _client.GetBlobAsync(SnapshotHead, cancellationToken);

            using (var headStream = await snapshotHeadBlob.OpenAsync(cancellationToken))
            {
                var snapshotHead =
                    await MessagePackSerializer.DeserializeAsync <Messages.RoadNetworkSnapshotHead>(
                        headStream,
                        cancellationToken : cancellationToken
                        );

                var snapshotBlobName = new BlobName(snapshotHead.SnapshotBlobName);
                if (!await _client.BlobExistsAsync(snapshotBlobName, cancellationToken))
                {
                    return(null, ExpectedVersion.NoStream);
                }

                var snapshotBlob = await _client.GetBlobAsync(snapshotBlobName, cancellationToken);

                if (!snapshotBlob.Metadata.TryGetAtVersion(out var version))
                {
                    return(null, ExpectedVersion.NoStream);
                }

                using (var snapshotStream = await snapshotBlob.OpenAsync(cancellationToken))
                {
                    var snapshot = await MessagePackSerializer.DeserializeAsync <Messages.RoadNetworkSnapshot>(
                        snapshotStream,
                        cancellationToken : cancellationToken);

                    return(snapshot, version);
                }
            }
        }
예제 #23
0
        public async Task <bool> BlobExistsAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            var nameParameter = CreateSqlParameter(
                "@Name",
                SqlDbType.NVarChar,
                BlobName.MaxLength,
                name.ToString());

            using (var connection = new SqlConnection(_builder.ConnectionString))
            {
                await connection.OpenAsync(cancellationToken);

                using (var command = new SqlCommand(_text.BlobExists(), connection)
                {
                    CommandType = CommandType.Text,
                    Parameters = { nameParameter }
                })
                {
                    return(0 != (int)await command.ExecuteScalarAsync(cancellationToken));
                }
            }
        }
예제 #24
0
        public async Task CreateBlobAsync(BlobName name, Metadata metadata, ContentType contentType, Stream content,
                                          CancellationToken cancellationToken = default)
        {
            // S3 does not have real concurrency control, this is simply a best effort approach
            if (await BlobExistsAsync(name, cancellationToken))
            {
                throw new BlobAlreadyExistsException(name);
            }

            var request = new PutObjectRequest
            {
                BucketName              = _bucket,
                Key                     = name.ToString(),
                ContentType             = contentType.ToString(),
                InputStream             = content,
                AutoResetStreamPosition = false,
                AutoCloseStream         = false
            };

            CopyMetadataToMetadataCollection(metadata, request.Metadata);
            await _client.PutObjectAsync(request, cancellationToken);
        }
예제 #25
0
        /// <summary>
        /// Returns true if BlobStorageInfo instances are equal
        /// </summary>
        /// <param name="other">Instance of BlobStorageInfo to be compared</param>
        /// <returns>Boolean</returns>
        public bool Equals(BlobStorageInfo other)
        {
            if (ReferenceEquals(null, other))
            {
                return(false);
            }
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            return
                ((
                     BlobName == other.BlobName ||
                     BlobName != null &&
                     BlobName.Equals(other.BlobName)
                     ) &&
                 (
                     ContainerName == other.ContainerName ||
                     ContainerName != null &&
                     ContainerName.Equals(other.ContainerName)
                 ) &&
                 (
                     CorrelationId == other.CorrelationId ||
                     CorrelationId != null &&
                     CorrelationId.Equals(other.CorrelationId)
                 ) &&
                 (
                     HostName == other.HostName ||
                     HostName != null &&
                     HostName.Equals(other.HostName)
                 ) &&
                 (
                     SasToken == other.SasToken ||
                     SasToken != null &&
                     SasToken.Equals(other.SasToken)
                 ));
        }
예제 #26
0
 /// <summary>Shorthand constructor.</summary>
 public BlobCounter(IBlobStorageProvider provider, BlobName <decimal> fullName)
     : this(provider, fullName.ContainerName, fullName.ToString())
 {
 }
예제 #27
0
 /// <summary>Shorthand constructor.</summary>
 public BlobCounter(IBlobStorageProvider provider, BlobName<decimal> fullName)
     : this(provider, fullName.ContainerName, fullName.ToString())
 {
 }
예제 #28
0
        public async Task <BlobObject> GetBlobAsync(BlobName name, CancellationToken cancellationToken = default)
        {
            var nameParameter = CreateSqlParameter(
                "@Name",
                SqlDbType.NVarChar,
                BlobName.MaxLength,
                name.ToString());

            using (var connection = new SqlConnection(_builder.ConnectionString))
            {
                await connection.OpenAsync(cancellationToken);

                using (var command = new SqlCommand(_text.GetBlob(), connection)
                {
                    CommandType = CommandType.Text,
                    Parameters = { nameParameter }
                })
                {
                    using (var reader = await command.ExecuteReaderAsync(ReaderBehavior, cancellationToken))
                    {
                        if (!reader.IsClosed && reader.Read())
                        {
                            return(new BlobObject(
                                       name,
                                       MetadataFromString(reader.GetString(0)),
                                       ContentType.Parse(reader.GetString(1)),
                                       async contentCancellationToken =>
                            {
                                var contentConnection = new SqlConnection(_builder.ConnectionString);
                                await contentConnection.OpenAsync(contentCancellationToken);
                                var contentCommand = new SqlCommand(_text.GetBlobContent(), contentConnection)
                                {
                                    CommandType = CommandType.Text,
                                    Parameters =
                                    {
                                        CreateSqlParameter(
                                            "@Name",
                                            SqlDbType.NVarChar,
                                            BlobName.MaxLength,
                                            name.ToString()
                                            )
                                    }
                                };
                                var contentReader =
                                    await contentCommand.ExecuteReaderAsync(ReaderBehavior,
                                                                            contentCancellationToken);
                                if (!contentReader.IsClosed && contentReader.Read())
                                {
                                    return new ForwardOnlyStream(
                                        new DisposableStream(
                                            contentReader.GetStream(0),
                                            contentReader,
                                            contentCommand,
                                            contentConnection)
                                        );
                                }

                                throw new BlobNotFoundException(name);
                            }));
                        }

                        return(null);
                    }
                }
            }
        }
예제 #29
0
        public NewBlobDialog()
        {
            InitializeComponent();

            BlobName.Focus();
        }