aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2015-02-05 00:29:37 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2015-02-05 00:29:37 -0500
commit7d415fc2fd8c76ba25c2bdb40347d1e0d17ad99f (patch)
tree448ecc653015896c5237f54b82072ce77956bf20 /MediaBrowser.Server.Implementations
parent1f1852f3cbe2a7899aea0d306a77d2eedb0434fc (diff)
some initial work on cloud sync
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json1
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj1
-rw-r--r--MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs25
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MediaSync.cs174
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs26
5 files changed, 225 insertions, 2 deletions
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index a3a65f538..aaf05d1ff 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -614,7 +614,6 @@
"PleaseUpdateManually": "Please shutdown the server and update manually.",
"NewServerVersionAvailable": "A new version of Media Browser Server is available!",
"ServerUpToDate": "Media Browser Server is up to date",
- "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
"LabelComponentsUpdated": "The following components have been installed or updated:",
"MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
"LabelDownMixAudioScale": "Audio boost when downmixing:",
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index f63b37c09..0247856b2 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -306,6 +306,7 @@
<Compile Include="Sorting\VideoBitRateComparer.cs" />
<Compile Include="Sync\AppSyncProvider.cs" />
<Compile Include="Sync\CloudSyncProvider.cs" />
+ <Compile Include="Sync\MediaSync.cs" />
<Compile Include="Sync\SyncRegistrationInfo.cs" />
<Compile Include="Sync\SyncConfig.cs" />
<Compile Include="Sync\SyncJobProcessor.cs" />
diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
index da3ecdfa6..c48f62820 100644
--- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
@@ -2,12 +2,15 @@
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Sync;
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Sync
{
- public class CloudSyncProvider : ISyncProvider
+ public class CloudSyncProvider : IServerSyncProvider
{
private ICloudSyncProvider[] _providers = {};
@@ -35,5 +38,25 @@ namespace MediaBrowser.Server.Implementations.Sync
{
get { return "Cloud Sync"; }
}
+
+ public Task<List<string>> GetServerItemIds(string serverId, SyncTarget target, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task DeleteItem(string serverId, string itemId, SyncTarget target, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task TransferItemFile(string serverId, string itemId, string path, SyncTarget target, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task TransferRelatedFile(string serverId, string itemId, string path, ItemFileType type, SyncTarget target, CancellationToken cancellationToken)
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
new file mode 100644
index 000000000..62bc6871b
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
@@ -0,0 +1,174 @@
+using MediaBrowser.Common.Progress;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Sync;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+ public class MediaSync
+ {
+ private readonly ISyncManager _syncManager;
+ private readonly IServerApplicationHost _appHost;
+ private readonly ILogger _logger;
+
+ public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost)
+ {
+ _logger = logger;
+ _syncManager = syncManager;
+ _appHost = appHost;
+ }
+
+ public async Task Sync(IServerSyncProvider provider,
+ SyncTarget target,
+ IProgress<double> progress,
+ CancellationToken cancellationToken)
+ {
+ var serverId = _appHost.SystemId;
+
+ await SyncData(provider, serverId, target, cancellationToken).ConfigureAwait(false);
+ progress.Report(2);
+
+ // Do the data sync twice so the server knows what was removed from the device
+ await SyncData(provider, serverId, target, cancellationToken).ConfigureAwait(false);
+ progress.Report(3);
+
+ var innerProgress = new ActionableProgress<double>();
+ innerProgress.RegisterAction(pct =>
+ {
+ var totalProgress = pct * .97;
+ totalProgress += 1;
+ progress.Report(totalProgress);
+ });
+ await GetNewMedia(provider, target, serverId, innerProgress, cancellationToken);
+ progress.Report(100);
+ }
+
+ private async Task SyncData(IServerSyncProvider provider,
+ string serverId,
+ SyncTarget target,
+ CancellationToken cancellationToken)
+ {
+ var localIds = await provider.GetServerItemIds(serverId, target, cancellationToken).ConfigureAwait(false);
+
+ var result = await _syncManager.SyncData(new SyncDataRequest
+ {
+ TargetId = target.Id,
+ LocalItemIds = localIds
+
+ }).ConfigureAwait(false);
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ foreach (var itemIdToRemove in result.ItemIdsToRemove)
+ {
+ try
+ {
+ await RemoveItem(provider, serverId, itemIdToRemove, target, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error deleting item from sync target. Id: {0}", ex, itemIdToRemove);
+ }
+ }
+ }
+
+ private async Task GetNewMedia(IServerSyncProvider provider,
+ SyncTarget target,
+ string serverId,
+ IProgress<double> progress,
+ CancellationToken cancellationToken)
+ {
+ var jobItems = _syncManager.GetReadySyncItems(target.Id);
+
+ var numComplete = 0;
+ double startingPercent = 0;
+ double percentPerItem = 1;
+ if (jobItems.Count > 0)
+ {
+ percentPerItem /= jobItems.Count;
+ }
+
+ foreach (var jobItem in jobItems)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var currentPercent = startingPercent;
+ var innerProgress = new ActionableProgress<double>();
+ innerProgress.RegisterAction(pct =>
+ {
+ var totalProgress = pct * percentPerItem;
+ totalProgress += currentPercent;
+ progress.Report(totalProgress);
+ });
+
+ await GetItem(provider, target, serverId, jobItem, innerProgress, cancellationToken).ConfigureAwait(false);
+
+ numComplete++;
+ startingPercent = numComplete;
+ startingPercent /= jobItems.Count;
+ startingPercent *= 100;
+ progress.Report(startingPercent);
+ }
+ }
+
+ private async Task GetItem(IServerSyncProvider provider,
+ SyncTarget target,
+ string serverId,
+ SyncedItem jobItem,
+ IProgress<double> progress,
+ CancellationToken cancellationToken)
+ {
+ var libraryItem = jobItem.Item;
+ var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId);
+
+ var fileTransferProgress = new ActionableProgress<double>();
+ fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92));
+
+ await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id);
+
+ var transferSuccess = false;
+ Exception transferException = null;
+
+ try
+ {
+ await provider.TransferItemFile(serverId, libraryItem.Id, internalSyncJobItem.OutputPath, target, cancellationToken)
+ .ConfigureAwait(false);
+
+ progress.Report(92);
+
+ transferSuccess = true;
+
+ progress.Report(99);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error transferring sync job file", ex);
+ transferException = ex;
+ }
+
+ if (transferSuccess)
+ {
+ await _syncManager.ReportSyncJobItemTransferred(jobItem.SyncJobItemId).ConfigureAwait(false);
+ }
+ else
+ {
+ await _syncManager.ReportSyncJobItemTransferFailed(jobItem.SyncJobItemId).ConfigureAwait(false);
+
+ throw transferException;
+ }
+ }
+
+ private Task RemoveItem(IServerSyncProvider provider,
+ string serverId,
+ string itemId,
+ SyncTarget target,
+ CancellationToken cancellationToken)
+ {
+ return provider.DeleteItem(serverId, itemId, target, cancellationToken);
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index eecbd78d1..0114d734a 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -870,6 +870,32 @@ namespace MediaBrowser.Server.Implementations.Sync
await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
}
+ public async Task ReportSyncJobItemTransferBeginning(string id)
+ {
+ var jobItem = _repo.GetJobItem(id);
+
+ jobItem.Status = SyncJobItemStatus.Transferring;
+
+ await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
+
+ var processor = GetSyncJobProcessor();
+
+ await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
+ }
+
+ public async Task ReportSyncJobItemTransferFailed(string id)
+ {
+ var jobItem = _repo.GetJobItem(id);
+
+ jobItem.Status = SyncJobItemStatus.ReadyToTransfer;
+
+ await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
+
+ var processor = GetSyncJobProcessor();
+
+ await processor.UpdateJobStatus(jobItem.JobId).ConfigureAwait(false);
+ }
+
public QueryResult<string> GetLibraryItemIds(SyncJobItemQuery query)
{
return _repo.GetLibraryItemIds(query);