Inheritance: ISignatureRepository
		public override async Task<SynchronizationReport> PerformAsync(string destination)
		{
			AssertLocalFileExistsAndIsNotConflicted(FileMetadata);

			var destinationRavenFileSystemClient = new RavenFileSystemClient(destination);

			var destinationMetadata = await destinationRavenFileSystemClient.GetMetadataForAsync(FileName);

			if (destinationMetadata == null)
			{
				// if file doesn't exist on destination server - upload it there
				return await UploadToAsync(destination);
			}

			var destinationServerRdcStats = await destinationRavenFileSystemClient.Synchronization.GetRdcStatsAsync();
			if (!IsRemoteRdcCompatible(destinationServerRdcStats))
				throw new SynchronizationException("Incompatible RDC version detected on destination server");

			var conflict = CheckConflictWithDestination(FileMetadata, destinationMetadata, ServerInfo.Url);

			if (conflict != null)
				return await ApplyConflictOnDestinationAsync(conflict, destination, ServerInfo.Url, log);

			using (var localSignatureRepository = new StorageSignatureRepository(Storage, FileName))
			using (var remoteSignatureCache = new VolatileSignatureRepository(FileName))
			{
				var localRdcManager = new LocalRdcManager(localSignatureRepository, Storage, sigGenerator);
				var destinationRdcManager = new RemoteRdcManager(destinationRavenFileSystemClient, localSignatureRepository,
				                                                 remoteSignatureCache);

				log.Debug("Starting to retrieve signatures of a local file '{0}'.", FileName);

				Cts.Token.ThrowIfCancellationRequested();

				// first we need to create a local file signatures before we synchronize with remote ones
				var localSignatureManifest = await localRdcManager.GetSignatureManifestAsync(FileDataInfo);

				log.Debug("Number of a local file '{0}' signatures was {1}.", FileName, localSignatureManifest.Signatures.Count);

				if (localSignatureManifest.Signatures.Count > 0)
				{
					var destinationSignatureManifest = await destinationRdcManager.SynchronizeSignaturesAsync(FileDataInfo, Cts.Token);

					if (destinationSignatureManifest.Signatures.Count > 0)
					{
						return
							await
							SynchronizeTo(destination, localSignatureRepository, remoteSignatureCache, localSignatureManifest,
							              destinationSignatureManifest);
					}
				}

				return await UploadToAsync(destination);
			}
		}
		public void Should_be_the_same_signatures()
		{
			const int size = 1024*1024*5;
			var randomStream = new RandomStream(size);
			var buffer = new byte[size];
			randomStream.Read(buffer, 0, size);
			var stream = new MemoryStream(buffer);

			var firstSigContentHashes = new List<string>();

			using (var signatureRepository = new VolatileSignatureRepository("test"))
			using (var rested = new SigGenerator())
			{
				var result = rested.GenerateSignatures(stream, "test", signatureRepository);

				foreach (var signatureInfo in result)
				{
					using (var content = signatureRepository.GetContentForReading(signatureInfo.Name))
					{
						firstSigContentHashes.Add(content.GetMD5Hash());
					}
				}
			}

			stream.Position = 0;

			var secondSigContentHashes = new List<string>();

			using (var signatureRepository = new VolatileSignatureRepository("test"))
			using (var rested = new SigGenerator())
			{
				var result = rested.GenerateSignatures(stream, "test", signatureRepository);

				foreach (var signatureInfo in result)
				{
					using (var content = signatureRepository.GetContentForReading(signatureInfo.Name))
					{
						secondSigContentHashes.Add(content.GetMD5Hash());
					}
				}
			}

			Assert.Equal(firstSigContentHashes.Count, secondSigContentHashes.Count);

			for (var i = 0; i < firstSigContentHashes.Count; i++)
			{
				Assert.Equal(firstSigContentHashes[i], secondSigContentHashes[i]);
			}
		}
		public void Generate_check()
		{
			using (var signatureRepository = new VolatileSignatureRepository("test"))
			using (var rested = new SigGenerator())
			{
				var result = rested.GenerateSignatures(_stream, "test", signatureRepository);
				Assert.Equal(2, result.Count);
				using (var content = signatureRepository.GetContentForReading(result[0].Name))
				{
					Assert.Equal("91b64180c75ef27213398979cc20bfb7", content.GetMD5Hash());
				}
				using (var content = signatureRepository.GetContentForReading(result[1].Name))
				{
					Assert.Equal("9fe9d408aed35769e25ece3a56f2d12f", content.GetMD5Hash());
				}
			}
		}