示例#1
0
            public void WriteDocument(DocumentItem item, SmugglerProgressBase.CountsWithLastEtagAndAttachments progress)
            {
                if (item.Attachments != null)
                {
                    throw new NotSupportedException();
                }

                var document = item.Document;

                using (document)
                {
                    if (_options.OperateOnTypes.HasFlag(DatabaseItemType.Attachments))
                    {
                        WriteUniqueAttachmentStreams(document, progress);
                    }

                    if (First == false)
                    {
                        Writer.WriteComma();
                    }
                    First = false;

                    Writer.WriteDocument(_context, document, metadataOnly: false, _filterMetadataProperty);
                }
            }
示例#2
0
            private void WriteUniqueAttachmentStreams(Document document, SmugglerProgressBase.CountsWithLastEtagAndAttachments progress)
            {
                if ((document.Flags & DocumentFlags.HasAttachments) != DocumentFlags.HasAttachments ||
                    document.Data.TryGet(Constants.Documents.Metadata.Key, out BlittableJsonReaderObject metadata) == false ||
                    metadata.TryGet(Constants.Documents.Metadata.Attachments, out BlittableJsonReaderArray attachments) == false)
                {
                    return;
                }

                if (_attachmentStreamsAlreadyExported == null)
                {
                    _attachmentStreamsAlreadyExported = new HashSet <string>();
                }

                foreach (BlittableJsonReaderObject attachment in attachments)
                {
                    if (attachment.TryGet(nameof(AttachmentName.Hash), out LazyStringValue hash) == false)
                    {
                        progress.Attachments.ErroredCount++;

                        throw new ArgumentException($"Hash field is mandatory in attachment's metadata: {attachment}");
                    }

                    progress.Attachments.ReadCount++;

                    if (_attachmentStreamsAlreadyExported.Add(hash))
                    {
                        using (var stream = _source.GetAttachmentStream(hash, out string tag))
                        {
                            if (stream == null)
                            {
                                progress.Attachments.ErroredCount++;
                                throw new ArgumentException($"Document {document.Id} seems to have a attachment hash: {hash}, but no correlating hash was found in the storage.");
                            }
                            WriteAttachmentStream(hash, stream, tag);
                        }
                    }
                }
            }
示例#3
0
        public async Task Attachments()
        {
            var destination = new DatabaseDestination(Database);
            var options     = new DatabaseSmugglerOptionsServerSide
            {
                OperateOnTypes       = DatabaseItemType.Attachments,
                SkipRevisionCreation = true
            };

            destination.Initialize(options, null, buildVersion: default);

            using (var documentActions = destination.Documents())
                using (var buffered = new BufferedStream(RequestBodyStream()))
                                                                            #pragma warning disable CS0618 // Type or member is obsolete
                    using (var reader = new BsonReader(buffered))
#pragma warning restore CS0618                                                                             // Type or member is obsolete
                    {
                        var result = LegacyAttachmentUtils.GetObject(reader);

                        const string idProperty       = "@id";
                        const string etagProperty     = "@etag";
                        const string metadataProperty = "@metadata";
                        const string dataProperty     = "data";

                        string lastAttachmentEtag = null;
                        var    progress           = new SmugglerProgressBase.CountsWithLastEtagAndAttachments();
                        foreach (var attachmentObject in result.Values)
                        {
                            if (!(attachmentObject is Dictionary <string, object> attachmentDictionary))
                            {
                                throw new InvalidDataException("attachmentObject isn't a Dictionary<string, object>");
                            }

                            if (attachmentDictionary.TryGetValue(idProperty, out var attachmentKeyObject) == false)
                            {
                                throw new InvalidDataException($"{idProperty} doesn't exist");
                            }

                            if (!(attachmentKeyObject is string attachmentKey))
                            {
                                throw new InvalidDataException($"{idProperty} isn't of type string");
                            }

                            if (attachmentDictionary.TryGetValue(etagProperty, out var lastAttachmentEtagObject) == false)
                            {
                                throw new InvalidDataException($"{etagProperty} doesn't exist");
                            }

                            if (!(lastAttachmentEtagObject is byte[] lastAttachmentEtagByteArray))
                            {
                                throw new InvalidDataException($"{etagProperty} isn't of type byte[]");
                            }

                            lastAttachmentEtag = LegacyAttachmentUtils.ByteArrayToEtagString(lastAttachmentEtagByteArray);

                            if (attachmentDictionary.TryGetValue(metadataProperty, out object metadataObject) == false)
                            {
                                throw new InvalidDataException($"{metadataProperty} doesn't exist");
                            }

                            if (!(metadataObject is Dictionary <string, object> metadata))
                            {
                                throw new InvalidDataException($"{idProperty} isn't of type string");
                            }

                            if (metadata.TryGetValue("Raven-Delete-Marker", out var deletedObject) && deletedObject is bool deletedObjectAsBool && deletedObjectAsBool)
                            {
                                var id = StreamSource.GetLegacyAttachmentId(attachmentKey);
                                documentActions.DeleteDocument(id);
                                continue;
                            }

                            var djv = new DynamicJsonValue();
                            foreach (var keyValue in metadata)
                            {
                                var key = keyValue.Key;
                                if (key.Equals("Raven-Replication-Source") ||
                                    key.Equals("Raven-Replication-Version") ||
                                    key.Equals("Raven-Replication-History"))
                                {
                                    continue;
                                }

                                djv[key] = keyValue.Value;
                            }

                            var contextToUse      = documentActions.GetContextForNewDocument();
                            var metadataBlittable = contextToUse.ReadObject(djv, "metadata");

                            if (attachmentDictionary.TryGetValue(dataProperty, out object dataObject) == false)
                            {
                                throw new InvalidDataException($"{dataProperty} doesn't exist");
                            }

                            if (!(dataObject is byte[] data))
                            {
                                throw new InvalidDataException($"{dataProperty} isn't of type byte[]");
                            }

                            using (var dataStream = new MemoryStream(data))
                            {
                                var attachment = new DocumentItem.AttachmentStream
                                {
                                    Stream = documentActions.GetTempStream()
                                };

                                var attachmentDetails = StreamSource.GenerateLegacyAttachmentDetails(contextToUse, dataStream, attachmentKey, metadataBlittable, ref attachment);

                                var documentItem = new DocumentItem
                                {
                                    Document = new Document
                                    {
                                        Data         = StreamSource.WriteDummyDocumentForAttachment(contextToUse, attachmentDetails),
                                        Id           = attachmentDetails.Id,
                                        ChangeVector = string.Empty,
                                        Flags        = DocumentFlags.HasAttachments,
                                        LastModified = Database.Time.GetUtcNow()
                                    },
                                    Attachments = new List <DocumentItem.AttachmentStream>
                                    {
                                        attachment
                                    }
                                };

                                documentActions.WriteDocument(documentItem, progress);
                            }
                        }

                        using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                        {
                            var replicationSource = GetSourceReplicationInformation(context, GetRemoteServerInstanceId(), out var documentId);
                            replicationSource.LastAttachmentEtag = lastAttachmentEtag;
                            replicationSource.Source             = GetFromServer();
                            replicationSource.LastModified       = DateTime.UtcNow;

                            await SaveSourceReplicationInformation(replicationSource, context, documentId);
                        }
                    }
        }