public DocumentDescriptorId FindDuplicateDocumentId( DocumentDescriptorId sourceDocumentId, FileHash sourceHash, BlobId sourceBlobId ) { if (!_config.IsDeduplicationActive) return null; var original = _blobStore.GetDescriptor(sourceBlobId); var matches = _hashReader.FindDocumentByHash(sourceHash); Logger.DebugFormat("Deduplicating document {0}", sourceDocumentId); foreach (var match in matches) { if (match.DocumentDescriptorId == sourceDocumentId) continue; Logger.DebugFormat("Checking document {0}", match.DocumentDescriptorId); var candidate = this._blobStore.GetDescriptor(match.BlobId); // only within same content type! if (candidate.ContentType != original.ContentType) { Logger.DebugFormat("document {0} has different ContentType ({1}), skipping", match.DocumentDescriptorId, candidate.ContentType ); continue; } // and same length if (candidate.Length != original.Length) { Logger.DebugFormat("document {0} has different length ({1}), skipping", match.DocumentDescriptorId, candidate.Length ); continue; } // binary check using (var candidateStream = candidate.OpenRead()) using (var originalStream = original.OpenRead()) { if (StreamHelper.StreamsContentsAreEqual(candidateStream, originalStream)) { Logger.DebugFormat("{0} has same content of {1}: match found!", match.DocumentDescriptorId, sourceDocumentId ); return match.DocumentDescriptorId; } else { Logger.DebugFormat("{0} has different content of {1}, skipping", match.DocumentDescriptorId, sourceDocumentId ); } } } return null; }
public DocumentDeleted(DocumentHandle handle, DocumentDescriptorId documentDescriptorId) { if (handle == null) throw new ArgumentNullException("handle"); if (documentDescriptorId == null) throw new ArgumentNullException("documentDescriptorId"); DocumentDescriptorId = documentDescriptorId; Handle = handle; }
public DocumentReadModel(DocumentHandle handle, DocumentDescriptorId documentid, FileNameWithExtension fileName, DocumentCustomData customData) { Handle = handle; DocumentDescriptorId = documentid; FileName = fileName; CustomData = customData; }
public DocumentLinked(DocumentHandle handle, DocumentDescriptorId documentId, DocumentDescriptorId previousDocumentId, FileNameWithExtension fileName) { FileName = fileName; PreviousDocumentId = previousDocumentId; Handle = handle; DocumentId = documentId; }
public LinkDocumentToDocumentDescriptor( DocumentDescriptorId documentDescriptorId, DocumentHandleInfo handleInfo) { DocumentDescriptorId = documentDescriptorId; HandleInfo = handleInfo; }
public CreateDocumentAsCopy( DocumentHandle handle, DocumentDescriptorId descriptorId, DocumentHandleInfo handleInfo) { Handle = handle; DocumentDescriptorId = descriptorId; HandleInfo = handleInfo; }
/// <summary> /// This DocumentDescriptor has the same content of another <see cref="DocumentDescriptor"/> /// this operation mark the current document as owner of the handle of duplicated document /// descriptor /// </summary> /// <param name="otherDocumentDescriptorId"></param> /// <param name="handle"></param> /// <param name="fileName"></param> public void Deduplicate( DocumentDescriptorId otherDocumentDescriptorId, DocumentHandleInfo handleInfo) { ThrowIfDeleted(String.Format("Deduplicate with {0}", otherDocumentDescriptorId)); RaiseEvent(new DocumentDescriptorHasBeenDeduplicated( otherDocumentDescriptorId, handleInfo)); Attach(handleInfo); }
public DocumentCopied( DocumentHandle handle, DocumentDescriptorId documentDescriptorId, DocumentHandleInfo handleInfo) { if (handle == null) throw new ArgumentNullException("handle"); if (documentDescriptorId == null) throw new ArgumentNullException("documentDescriptorId"); if (handleInfo == null) throw new ArgumentNullException("handleInfo"); DocumentDescriptorId = documentDescriptorId; NewHandle = handle; HandleInfo = handleInfo; }
public void InitializeAsAttach( BlobId blobId, DocumentHandleInfo handleInfo, FileHash hash, String fileName, DocumentDescriptorId fatherDocumentDescriptorId) { ThrowIfDeleted(String.Format("Initialize as attach with blob {0} and fileName {1}", blobId, fileName)); if (HasBeenCreated) { throw new DomainException(Id, "Already initialized"); } RaiseEvent(new DocumentDescriptorInitialized(blobId, handleInfo, hash, fatherDocumentDescriptorId)); var knownFormat = DocumentFormatTranslator.GetFormatFromFileName(fileName); if (knownFormat != null) { RaiseEvent(new FormatAddedToDocumentDescriptor(knownFormat, blobId, null)); } }
public void LinkDocument(DocumentHandle handle, DocumentDescriptorId id, long projectedAt) { InnerCreateLinkToDocument(handle, id, null, projectedAt); }
public void Projected(int expectedDocId, int projectedAt, bool isPending) { var expectedDocumentId = new DocumentDescriptorId(expectedDocId); _writer.Promise(_documentHandle, 10); _writer.LinkDocument(_documentHandle, _document2, projectedAt); var h = _writer.FindOneById(_documentHandle); Assert.NotNull(h); Assert.AreEqual(10, h.CreatetAt); Assert.IsNull(h.FileName); if (h.ProjectedAt >= h.CreatetAt) { Assert.AreEqual(expectedDocumentId, h.DocumentDescriptorId); Assert.AreEqual(projectedAt, h.ProjectedAt); } Assert.AreEqual(isPending, h.IsPending()); }
public DocumentReadModel(DocumentHandle handle, DocumentDescriptorId documentid, FileNameWithExtension fileName) : this(handle, documentid, fileName, null) { }
public void CreateIfMissing(DocumentHandle handle, DocumentDescriptorId documentDescriptorId, long createdAt) { Logger.DebugFormat("CreateIfMissing on handle {0} [{1}]", handle, createdAt); Int32 iteration = 0; do { try { var result = _collection.FindOneAndUpdate( Builders<DocumentReadModel>.Filter.Eq(x => x.Handle, handle), Builders<DocumentReadModel>.Update .SetOnInsert(x => x.CustomData, null) .SetOnInsert(x => x.ProjectedAt, 0) .SetOnInsert(x => x.DocumentDescriptorId, documentDescriptorId) .SetOnInsert(x => x.CreatetAt, createdAt) .SetOnInsert(x => x.FileName, null), new FindOneAndUpdateOptions<DocumentReadModel, DocumentReadModel>() { ReturnDocument = ReturnDocument.After, IsUpsert = true }); } catch (MongoCommandException ex) { if (ex.Message.Contains("E11000") == false) throw; } } while (iteration++ < 3); }
private Boolean InnerCreateLinkToDocument(DocumentHandle handle, DocumentDescriptorId id, Boolean? deDuplication, long projectedAt) { Logger.DebugFormat("LinkDocument on handle {0} [{1}]", handle, projectedAt); var result = _collection.FindOneAndUpdate( Builders<DocumentReadModel>.Filter.And( Builders<DocumentReadModel>.Filter.Eq(x => x.Handle, handle), Builders<DocumentReadModel>.Filter.Ne(x => x.DocumentDescriptorId, id), Builders<DocumentReadModel>.Filter.Lte(x => x.CreatetAt, projectedAt) ), Builders<DocumentReadModel>.Update .Set(x => x.DocumentDescriptorId, id) .Set(x => x.ProjectedAt, projectedAt), new FindOneAndUpdateOptions<DocumentReadModel, DocumentReadModel>() { ReturnDocument = ReturnDocument.After } ); if (Logger.IsDebugEnabled) { Logger.DebugFormat("LinkDocument on handle {0} [{1}] : {2}", handle, projectedAt, result != null); } return result != null; }
protected void SetupDocumentHandle(DocumentHandleInfo handleInfo, DocumentDescriptorId documentId) { _handleWriter .FindOneById(handleInfo.Handle) .Returns(info => new DocumentReadModel(handleInfo.Handle, documentId, handleInfo.FileName)); }
private void CreateDocument( DocumentDescriptorId documentDescriptorId, BlobId blobId, DocumentHandle handle, DocumentHandle fatherHandle, DocumentDescriptorId fatherDocumentDescriptorId, FileNameWithExtension fileName, DocumentCustomData customData ) { var descriptor = _blobStore.GetDescriptor(blobId); ICommand createDocument; var handleInfo = new DocumentHandleInfo(handle, fileName, customData); if (fatherHandle == null) { if (Logger.IsDebugEnabled) Logger.DebugFormat("Initialize DocumentDescriptor {0} ", documentDescriptorId); createDocument = new InitializeDocumentDescriptor(documentDescriptorId, blobId, handleInfo, descriptor.Hash, fileName); } else { if (Logger.IsDebugEnabled) Logger.DebugFormat("Initialize DocumentDescriptor as attach {0} ", documentDescriptorId); createDocument = new InitializeDocumentDescriptorAsAttach( documentDescriptorId, blobId, handleInfo, fatherHandle, fatherDocumentDescriptorId, descriptor.Hash, fileName); } CommandBus.Send(createDocument, "api"); }
public Match(DocumentDescriptorId documentDescriptorId, BlobId blobId) { DocumentDescriptorId = documentDescriptorId; BlobId = blobId; }
/// <summary> /// /// </summary> /// <param name="tenantId"></param> /// <param name="handle"></param> /// <param name="fatherHandle">Different from null only when you want to upload /// a document that is an attachment of another document</param> /// <param name="fatherHandleDescriptorId">Descriptor id that contains reference /// to <paramref name="fatherHandle"/></param> /// <returns></returns> private async Task<HttpResponseMessage> InnerUploadDocument( TenantId tenantId, DocumentHandle handle, DocumentHandle fatherHandle, DocumentDescriptorId fatherHandleDescriptorId) { var documentId = _identityGenerator.New<DocumentDescriptorId>(); Logger.DebugFormat("Incoming file {0}, assigned {1}", handle, documentId); var errorMessage = await UploadFromHttpContent(Request.Content); Logger.DebugFormat("File {0} processed with message {1}", _blobId, errorMessage ?? "OK"); if (errorMessage != null) { return Request.CreateErrorResponse( HttpStatusCode.BadRequest, errorMessage ); } CreateDocument(documentId, _blobId, handle, fatherHandle, fatherHandleDescriptorId, _fileName, _customData); Logger.DebugFormat("File {0} uploaded as {1}", _blobId, documentId); var storedFile = _blobStore.GetDescriptor(_blobId); return Request.CreateResponse( HttpStatusCode.OK, new UploadedDocumentResponse { Handle = handle, Hash = storedFile.Hash, HashType = "md5", Uri = Url.Content("/" + tenantId + "/documents/" + handle) } ); }
public void DocumentDeDuplicated( DocumentHandle handle, DocumentHandle primaryHandle, DocumentDescriptorId id, long projectedAt) { var linkChanged = InnerCreateLinkToDocument(handle, id, true, projectedAt); }
public void Link(DocumentDescriptorId documentId) { this.LinkedDocument = documentId; }
/// <summary> /// when a document descriptor is deleted there is no need to continue /// scheduling jobs, so all jobs should be deleted. /// </summary> /// <param name="documentDescriptorId"></param> internal void DeletedJobForDescriptor(DocumentDescriptorId documentDescriptorId) { _collection.DeleteMany( Builders<QueuedJob>.Filter.Eq(j => j.DocumentDescriptorId, documentDescriptorId)); }