PageRenderTime 64ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Raven.Database/Server/RavenFS/Synchronization/SynchronizationStrategy.cs

https://github.com/nwendel/ravendb
C# | 118 lines | 93 code | 21 blank | 4 comment | 33 complexity | e314a788fe508454723fa8a566a6771e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Specialized;
  4. using System.Linq;
  5. using Raven.Database.Server.RavenFS.Infrastructure;
  6. using Raven.Database.Server.RavenFS.Storage;
  7. using Raven.Database.Server.RavenFS.Storage.Esent;
  8. using Raven.Database.Server.RavenFS.Synchronization.Rdc.Wrapper;
  9. using Raven.Database.Server.RavenFS.Util;
  10. using Raven.Json.Linq;
  11. using Raven.Abstractions.FileSystem;
  12. using Raven.Abstractions.Data;
  13. namespace Raven.Database.Server.RavenFS.Synchronization
  14. {
  15. public class SynchronizationStrategy
  16. {
  17. private readonly SigGenerator sigGenerator;
  18. private readonly ITransactionalStorage storage;
  19. public SynchronizationStrategy(ITransactionalStorage storage, SigGenerator sigGenerator)
  20. {
  21. this.storage = storage;
  22. this.sigGenerator = sigGenerator;
  23. }
  24. public bool Filter(FileHeader file, Guid destinationId, IEnumerable<FileHeader> candidatesToSynchronization)
  25. {
  26. // prevent synchronization back to source
  27. if (file.Metadata.Value<Guid>(SynchronizationConstants.RavenSynchronizationSource) == destinationId)
  28. return false;
  29. if (file.Name.EndsWith(RavenFileNameHelper.DownloadingFileSuffix))
  30. return false;
  31. if (file.Name.EndsWith(RavenFileNameHelper.DeletingFileSuffix))
  32. return false;
  33. if (file.IsFileBeingUploadedOrUploadHasBeenBroken())
  34. return false;
  35. if (ExistsRenameTombstone(file.Name, candidatesToSynchronization))
  36. return false;
  37. return true;
  38. }
  39. private static bool ExistsRenameTombstone(string name, IEnumerable<FileHeader> candidatesToSynchronization)
  40. {
  41. return
  42. candidatesToSynchronization.Any(
  43. x =>
  44. x.Metadata[SynchronizationConstants.RavenDeleteMarker] != null &&
  45. x.Metadata.Value<string>(SynchronizationConstants.RavenRenameFile) == name);
  46. }
  47. public SynchronizationWorkItem DetermineWork(string file, RavenJObject localMetadata, RavenJObject destinationMetadata, string localServerUrl, out NoSyncReason reason)
  48. {
  49. reason = NoSyncReason.Unknown;
  50. if (localMetadata == null)
  51. {
  52. reason = NoSyncReason.SourceFileNotExist;
  53. return null;
  54. }
  55. if (destinationMetadata != null && destinationMetadata[SynchronizationConstants.RavenSynchronizationConflict] != null && destinationMetadata[SynchronizationConstants.RavenSynchronizationConflictResolution] == null)
  56. {
  57. reason = NoSyncReason.DestinationFileConflicted;
  58. return null;
  59. }
  60. if (localMetadata[SynchronizationConstants.RavenSynchronizationConflict] != null)
  61. {
  62. reason = NoSyncReason.SourceFileConflicted;
  63. return null;
  64. }
  65. if (localMetadata[SynchronizationConstants.RavenDeleteMarker] != null)
  66. {
  67. if (localMetadata.ContainsKey(SynchronizationConstants.RavenRenameFile))
  68. {
  69. var rename = localMetadata.Value<string>(SynchronizationConstants.RavenRenameFile);
  70. if (destinationMetadata != null)
  71. return new RenameWorkItem(file, rename, localServerUrl, storage);
  72. return new ContentUpdateWorkItem(rename, localServerUrl, storage, sigGenerator);
  73. // we have a rename tombstone but file does not exists on destination
  74. }
  75. return new DeleteWorkItem(file, localServerUrl, storage);
  76. }
  77. if (destinationMetadata != null && Historian.IsDirectChildOfCurrent(localMetadata, destinationMetadata))
  78. {
  79. reason = NoSyncReason.ContainedInDestinationHistory;
  80. return null;
  81. }
  82. // file exists on dest and has the same content
  83. if (destinationMetadata != null && localMetadata.Value<string>("Content-MD5") == destinationMetadata.Value<string>("Content-MD5"))
  84. {
  85. // check metadata to detect if any synchronization is needed
  86. if (localMetadata.Keys.Except(new[] { Constants.MetadataEtagField, Constants.LastModified })
  87. .Any(key => !destinationMetadata.ContainsKey(key) || localMetadata[key] != destinationMetadata[key]))
  88. {
  89. return new MetadataUpdateWorkItem(file, localServerUrl, destinationMetadata, storage);
  90. }
  91. reason = NoSyncReason.SameContentAndMetadata;
  92. return null; // the same content and metadata - no need to synchronize
  93. }
  94. return new ContentUpdateWorkItem(file, localServerUrl, storage, sigGenerator);
  95. }
  96. }
  97. }