PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/Raven.Database/Bundles/Replication/Responders/DocumentReplicationResponder.cs

https://github.com/nwendel/ravendb
C# | 144 lines | 128 code | 9 blank | 7 comment | 11 complexity | aba7386e1d73dbd969c4f5edecfd9644 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, CC-BY-SA-3.0
  1. //-----------------------------------------------------------------------
  2. // <copyright file="DocumentReplicationResponder.cs" company="Hibernating Rhinos LTD">
  3. // Copyright (c) Hibernating Rhinos LTD. All rights reserved.
  4. // </copyright>
  5. //-----------------------------------------------------------------------
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel.Composition;
  9. using System.Linq;
  10. using System.Security.Cryptography;
  11. using System.Text;
  12. using Raven.Abstractions.Logging;
  13. using Raven.Abstractions.Util.Encryptors;
  14. using Raven.Bundles.Replication.Tasks;
  15. using Raven.Database.Server;
  16. using Raven.Imports.Newtonsoft.Json.Linq;
  17. using Raven.Abstractions.Data;
  18. using Raven.Abstractions.Extensions;
  19. using Raven.Abstractions.Logging;
  20. using Raven.Bundles.Replication.Data;
  21. using Raven.Bundles.Replication.Plugins;
  22. using Raven.Bundles.Replication.Tasks;
  23. using Raven.Database.Extensions;
  24. using Raven.Database.Server;
  25. using Raven.Database.Server.Abstractions;
  26. using Raven.Database.Storage;
  27. using Raven.Json.Linq;
  28. using System;
  29. using System.Collections.Generic;
  30. using System.ComponentModel.Composition;
  31. using System.Linq;
  32. namespace Raven.Bundles.Replication.Responders
  33. {
  34. [ExportMetadata("Bundle", "Replication")]
  35. [InheritedExport(typeof(AbstractRequestResponder))]
  36. public class DocumentReplicationResponder : AbstractRequestResponder
  37. {
  38. private readonly ILog log = LogManager.GetCurrentClassLogger();
  39. private ReplicationTask replicationTask;
  40. public ReplicationTask ReplicationTask
  41. {
  42. get { return replicationTask ?? (replicationTask = Database.StartupTasks.OfType<ReplicationTask>().FirstOrDefault()); }
  43. }
  44. [ImportMany]
  45. public IEnumerable<AbstractDocumentReplicationConflictResolver> ReplicationConflictResolvers { get; set; }
  46. public override void Respond(IHttpContext context)
  47. {
  48. var src = context.Request.QueryString["from"];
  49. if (string.IsNullOrEmpty(src))
  50. {
  51. context.SetStatusToBadRequest();
  52. return;
  53. }
  54. while (src.EndsWith("/"))
  55. src = src.Substring(0, src.Length - 1);// remove last /, because that has special meaning for Raven
  56. if (string.IsNullOrEmpty(src))
  57. {
  58. context.SetStatusToBadRequest();
  59. return;
  60. }
  61. var array = context.ReadJsonArray();
  62. if (ReplicationTask != null)
  63. ReplicationTask.HandleHeartbeat(src);
  64. using (Database.DisableAllTriggersForCurrentThread())
  65. {
  66. Database.TransactionalStorage.Batch(actions =>
  67. {
  68. string lastEtag = Etag.Empty.ToString();
  69. foreach (RavenJObject document in array)
  70. {
  71. var metadata = document.Value<RavenJObject>("@metadata");
  72. if (metadata[Constants.RavenReplicationSource] == null)
  73. {
  74. // not sure why, old document from when the user didn't have replication
  75. // that we suddenly decided to replicate, choose the source for that
  76. metadata[Constants.RavenReplicationSource] = RavenJToken.FromObject(src);
  77. }
  78. lastEtag = metadata.Value<string>("@etag");
  79. var id = metadata.Value<string>("@id");
  80. document.Remove("@metadata");
  81. ReplicateDocument(actions, id, metadata, document, src);
  82. }
  83. var replicationDocKey = Constants.RavenReplicationSourcesBasePath + "/" + src;
  84. var replicationDocument = Database.Get(replicationDocKey, null);
  85. var lastAttachmentId = Etag.Empty;
  86. if (replicationDocument != null)
  87. {
  88. lastAttachmentId =
  89. replicationDocument.DataAsJson.JsonDeserialization<SourceReplicationInformation>().
  90. LastAttachmentEtag;
  91. }
  92. Guid serverInstanceId;
  93. if (Guid.TryParse(context.Request.QueryString["dbid"], out serverInstanceId) == false)
  94. serverInstanceId = Database.TransactionalStorage.Id;
  95. Database.Put(replicationDocKey, null,
  96. RavenJObject.FromObject(new SourceReplicationInformation
  97. {
  98. Source = src,
  99. LastDocumentEtag = Etag.Parse(lastEtag),
  100. LastAttachmentEtag = lastAttachmentId,
  101. ServerInstanceId = serverInstanceId
  102. }),
  103. new RavenJObject(), null);
  104. });
  105. }
  106. }
  107. private void ReplicateDocument(IStorageActionsAccessor actions, string id, RavenJObject metadata, RavenJObject document, string src)
  108. {
  109. try
  110. {
  111. new DocumentReplicationBehavior
  112. {
  113. Actions = actions,
  114. Database = Database,
  115. ReplicationConflictResolvers = ReplicationConflictResolvers,
  116. Src = src
  117. }.Replicate(id, metadata, document);
  118. }
  119. catch (Exception ex)
  120. {
  121. log.ErrorException(
  122. string.Format("Exception occurred during the replication of the document {0} from the server {1}", id, src), ex);
  123. throw;
  124. }
  125. }
  126. public override string UrlPattern
  127. {
  128. get { return "^/replication/replicateDocs$"; }
  129. }
  130. public override string[] SupportedVerbs
  131. {
  132. get { return new[] { "POST" }; }
  133. }
  134. }
  135. }