internal static StateSyncEntry ToEntry(Guid id, Guid parentId) { var entry = new StateSyncEntry(); entry.Id = CloudFolderFileSystem.ToId(id); entry.ParentId = CloudFolderFileSystem.ToId(parentId); return(entry); }
static void Main() { Console.WriteLine("ShellBoost Samples - Cloud Folder Sync - " + (IntPtr.Size == 4 ? "32" : "64") + "-bit - Copyright (C) 2017-" + DateTime.Now.Year + " Aelyo Softworks. All rights reserved."); Console.WriteLine("ShellBoost Runtime Version " + typeof(ShellContext).Assembly.GetInformationalVersion()); Console.WriteLine(); WebApi.Logger = new FileLogger(); var id = WebApi.ServerInfo.Id; // this will connect to server, if it fails here, check connections, server, etc. WebApi.Logger.Log(TraceLevel.Info, "Server root url: " + WebApi.RootUrl); WebApi.Logger.Log(TraceLevel.Info, "Server id: " + WebApi.ServerInfo.Id); WebApi.Logger.Log(TraceLevel.Info, "Server time diff: " + WebApi.ServerInfo.TimeDifference); if (WebApi.ServerInfo.TimeDifference.TotalMinutes > 1) { WebApi.Logger.Log(TraceLevel.Error, "Server time diff is a bit high!"); } // determine a folder path var folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Name); // we want events from the server (SignalR) var options = new MultiPointSynchronizerOptions(); options.Logger = WebApi.Logger; WebApi.Logger.Log(TraceLevel.Info, "Local folder path: " + folderPath); options.BackupState = true; // we want to backup the state (state is by default an sqlite database) var reg = new OnDemandLocalFileSystemRegistration { ProviderDisplayName = DisplayName }; Console.WriteLine(); Console.WriteLine("Press a key:"); Console.WriteLine(); Console.WriteLine(" '1' Register the target folder as a Cloud Storage Provider and enter synchronization loop."); Console.WriteLine(" '2' Unregister the target folder as a Cloud Storage Provider. Only necessary when you've stopped all your tests."); Console.WriteLine(); Console.WriteLine("Any other key will exit."); Console.WriteLine(); var key = Console.ReadKey(true); switch (key.KeyChar) { case '1': // register to the Windows file system as a storage provider OnDemandLocalFileSystem.EnsureRegistered(folderPath, reg); // register to the Windows Shell (explorer treeview) as a storage provider ShellRegistration.RegisterCloudStorageProvider(folderPath, DisplayName, id); // create the synchronizer // note: by default, SQLite state database will be created at %localappdata%\ShellBoost.Core.Synchronization\<ShellBoost Project Id> directory using (var mp = new MultiPointSynchronizer(Name + "." + id.ToString(), options: options)) { // this our file system implementation var fs = new CloudFolderFileSystem(options.Logger); // this is Windows 10+ files on-demand local file system (ShellBoost provided) var local = new OnDemandLocalFileSystem(folderPath, new OnDemandLocalFileSystemOptions { UpdateAllEntriesStatesAtInitialization = false }); // add sync endpoints mp.AddEndPoint("Local", local); // we prefer to put each temporary (upload) file in the target folder // instead of using a temp folder like with the Google Drive sample mp.AddEndPoint(Name, fs, new EndPointSynchronizerOptions { UploadsWaitForParents = true }); // start sync loop mp.Start(); Console.WriteLine("Sync loop started. Press ESC to stop."); do { key = Console.ReadKey(true); if (key.Key == ConsoleKey.Escape) { break; } // console output can be pretty big... press C to clear if (key.Key == ConsoleKey.C) { Console.Clear(); } }while (true); mp.Stop(); } break; case '2': // remove ourselves from the explorer treeview ShellRegistration.UnregisterCloudStorageProvider(id); // unregister to the Windows file system as a storage provider OnDemandLocalFileSystem.Unregister(folderPath, reg); Console.WriteLine(" Cloud Storage Provider has been unregistered."); break; } }
public CloudFolderEvents(CloudFolderFileSystem fileSystem) { if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } _fileSystem = fileSystem; // build SignalR connection _connection = new HubConnectionBuilder() .WithUrl(WebApi.RootUrl + "events") .WithAutomaticReconnect() .Build(); _connection.Closed += async(error) => { _fileSystem.Logger?.Log(TraceLevel.Warning, "Server events closed. Error: " + error?.Message + " Restart: " + _started); // restart? if (_started) { await Task.Delay(new Random().Next(0, 5) * 1000).ConfigureAwait(false); await _connection.StartAsync().ConfigureAwait(false); } }; // must match server's IFileSystemEvents method signature // Change(Guid id, Guid itemId, Guid parentId, WatcherChangeTypes types, DateTime creationTimeUtc, string oldName); _connection.On <Guid, Guid, Guid, WatcherChangeTypes, DateTime, string>("Change", (id, itemId, parentId, type, dt, oldName) => { _fileSystem.Logger?.Log(TraceLevel.Verbose, "id: " + id + " itemid: " + itemId + " parentId: " + parentId + " type: " + type + " oldName:" + oldName); StateSyncEntry entry; switch (type) { case WatcherChangeTypes.Deleted: entry = ToEntry(itemId, parentId); _fileSystem.OnEvent(new SyncFileSystemEventArgs(SyncFileSystemEventType.Deleted, dt, entry)); break; case WatcherChangeTypes.Created: entry = ToEntry(itemId, parentId); _fileSystem.OnEvent(new SyncFileSystemEventArgs(SyncFileSystemEventType.Created, dt, entry)); break; case WatcherChangeTypes.Changed: entry = ToEntry(itemId, parentId); _fileSystem.OnEvent(new SyncFileSystemEventArgs(SyncFileSystemEventType.Changed, dt, entry)); break; case WatcherChangeTypes.Renamed: entry = ToEntry(itemId, parentId); var oldEntry = ToEntry(itemId, parentId); oldEntry.FileName = oldName; _fileSystem.OnEvent(new SyncFileSystemEventArgs(SyncFileSystemEventType.Moved, dt, entry, oldEntry)); break; } SetLastEventTime(dt); }); }