예제 #1
0
        public static LegacyAttachmentDetails GenerateLegacyAttachmentDetails(
            DocumentsOperationContext context,
            Stream decodedStream,
            string key,
            BlittableJsonReaderObject metadata,
            ref DocumentItem.AttachmentStream attachment)
        {
            var stream = attachment.Stream;
            var hash   = AsyncHelpers.RunSync(() => AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, decodedStream, stream, CancellationToken.None));

            attachment.Stream.Flush();
            var lazyHash = context.GetLazyString(hash);

            attachment.Base64HashDispose = Slice.External(context.Allocator, lazyHash, out attachment.Base64Hash);
            var tag     = $"{DummyDocumentPrefix}{key}{RecordSeparator}d{RecordSeparator}{key}{RecordSeparator}{hash}{RecordSeparator}";
            var lazyTag = context.GetLazyString(tag);

            attachment.TagDispose = Slice.External(context.Allocator, lazyTag, out attachment.Tag);
            var id     = GetLegacyAttachmentId(key);
            var lazyId = context.GetLazyString(id);

            attachment.Data = context.ReadObject(metadata, id);
            return(new LegacyAttachmentDetails
            {
                Id = lazyId,
                Hash = hash,
                Key = key,
                Size = attachment.Stream.Length,
                Tag = tag,
                Metadata = attachment.Data
            });
        }
예제 #2
0
        private async Task <BatchHandler.MergedBatchCommand.AttachmentStream> WriteAttachment(long size, Stream stream)
        {
            var attachmentStream = new BatchHandler.MergedBatchCommand.AttachmentStream();

            if (size <= 32 * 1024)
            {
                attachmentStream.Stream = new MemoryStream();
            }
            else
            {
                StreamsTempFile attachmentStreamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("bulk");
                attachmentStream.Stream = attachmentStreamsTempFile.StartNewStream();

                if (_streamsTempFiles == null)
                {
                    _streamsTempFiles = new List <StreamsTempFile>();
                }

                _streamsTempFiles.Add(attachmentStreamsTempFile);
            }

            using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                using (ctx.OpenWriteTransaction())
                {
                    attachmentStream.Hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(ctx, stream, attachmentStream.Stream, Database.DatabaseShutdown);

                    await attachmentStream.Stream.FlushAsync();
                }

            return(attachmentStream);
        }
예제 #3
0
        public async Task InsertDocument(BlittableJsonReaderObject document, string id, Dictionary <string, byte[]> attachments)
        {
            _commands.Add(new BatchRequestParser.CommandData
            {
                Type     = CommandType.PUT,
                Document = document,
                Id       = id
            });

            foreach (var attachment in attachments)
            {
                var memoryStream = new MemoryStream(attachment.Value);
                var stream       = _command.AttachmentStreamsTempFile.StartNewStream();

                _toDispose.Add(memoryStream);
                _toDispose.Add(stream);

                var attachmentStream = new BatchHandler.MergedBatchCommand.AttachmentStream
                {
                    Stream = stream,
                    Hash   = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(_context, memoryStream, stream, _context.DocumentDatabase.DatabaseShutdown) //TODO: do we need it?
                };

                await stream.FlushAsync();

                _attachmentStreams.Add(attachmentStream);

                _commands.Add(new BatchRequestParser.CommandData
                {
                    Type        = CommandType.AttachmentPUT,
                    Id          = id,
                    ContentType = "",
                    Name        = attachment.Key
                });
            }

            if (_commands.Count >= _batchSize)
            {
                await FlushCommands();
            }
        }
예제 #4
0
        private async Task ParseMultipart(DocumentsOperationContext context, MergedBatchCommand command)
        {
            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(HttpContext.Request.ContentType),
                MultipartRequestHelper.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, RequestBodyStream());

            for (var i = 0; i < int.MaxValue; i++)
            {
                var section = await reader.ReadNextSectionAsync().ConfigureAwait(false);

                if (section == null)
                {
                    break;
                }

                var bodyStream = GetBodyStream(section);
                if (i == 0)
                {
                    command.ParsedCommands = await BatchRequestParser.BuildCommandsAsync(context, bodyStream, Database, ServerStore);

                    continue;
                }

                if (command.AttachmentStreams == null)
                {
                    command.AttachmentStreams         = new Queue <MergedBatchCommand.AttachmentStream>();
                    command.AttachmentStreamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("batch");
                }

                var attachmentStream = new MergedBatchCommand.AttachmentStream
                {
                    Stream = command.AttachmentStreamsTempFile.StartNewStream()
                };
                attachmentStream.Hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, bodyStream, attachmentStream.Stream, Database.DatabaseShutdown);

                attachmentStream.Stream.Flush();
                command.AttachmentStreams.Enqueue(attachmentStream);
            }
        }
예제 #5
0
        public async Task Put()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                var id          = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");
                var name        = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name");
                var contentType = GetStringQueryString("contentType", false) ?? "";

                AttachmentDetails result;
                using (var streamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("put"))
                    using (var stream = streamsTempFile.StartNewStream())
                    {
                        Stream requestBodyStream = RequestBodyStream();
                        string hash;
                        try
                        {
                            hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, requestBodyStream, stream, Database.DatabaseShutdown);
                        }
                        catch (Exception)
                        {
                            try
                            {
                                // if we failed to read the entire request body stream, we might leave
                                // data in the pipe still, this will cause us to read and discard the
                                // rest of the attachment stream and return the actual error to the caller
                                requestBodyStream.CopyTo(Stream.Null);
                            }
                            catch (Exception)
                            {
                                // we tried, but we can't clean the request, so let's just kill
                                // the connection
                                HttpContext.Abort();
                            }
                            throw;
                        }

                        var changeVector = context.GetLazyString(GetStringFromHeaders("If-Match"));

                        var cmd = new MergedPutAttachmentCommand
                        {
                            Database             = Database,
                            ExpectedChangeVector = changeVector,
                            DocumentId           = id,
                            Name        = name,
                            Stream      = stream,
                            Hash        = hash,
                            ContentType = contentType
                        };
                        stream.Flush();
                        await Database.TxMerger.Enqueue(cmd);

                        cmd.ExceptionDispatchInfo?.Throw();
                        result = cmd.Result;
                    }

                HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName(nameof(AttachmentDetails.ChangeVector));
                    writer.WriteString(result.ChangeVector);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Name));
                    writer.WriteString(result.Name);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.DocumentId));
                    writer.WriteString(result.DocumentId);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.ContentType));
                    writer.WriteString(result.ContentType);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Hash));
                    writer.WriteString(result.Hash);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Size));
                    writer.WriteInteger(result.Size);

                    writer.WriteEndObject();
                }
            }
        }
예제 #6
0
        public async Task Put()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
            {
                var id          = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");
                var name        = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name");
                var contentType = GetStringQueryString("contentType", false) ?? "";

                AttachmentDetails result;
                using (var streamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("put"))
                    using (var stream = streamsTempFile.StartNewStream())
                    {
                        var hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, RequestBodyStream(), stream, Database.DatabaseShutdown);

                        var changeVector = context.GetLazyString(GetStringQueryString("If-Match", false));

                        var cmd = new MergedPutAttachmentCommand
                        {
                            Database             = Database,
                            ExpectedChangeVector = changeVector,
                            DocumentId           = id,
                            Name        = name,
                            Stream      = stream,
                            Hash        = hash,
                            ContentType = contentType
                        };
                        await Database.TxMerger.Enqueue(cmd);

                        cmd.ExceptionDispatchInfo?.Throw();
                        result = cmd.Result;
                    }

                HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName(nameof(AttachmentDetails.ChangeVector));
                    writer.WriteString(result.ChangeVector);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Name));
                    writer.WriteString(result.Name);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.DocumentId));
                    writer.WriteString(result.DocumentId);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.ContentType));
                    writer.WriteString(result.ContentType);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Hash));
                    writer.WriteString(result.Hash);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(AttachmentDetails.Size));
                    writer.WriteInteger(result.Size);

                    writer.WriteEndObject();
                }
            }
        }