Beispiel #1
0
        internal async Task <char?> Mount(char driveLetter, bool readOnly, CancellationToken cs, bool interactiveAuth = true)
        {
            if (Interlocked.CompareExchange(ref mounted, 1, 0) != 0)
            {
                return(null);
            }

            var mountedEvent = new TaskCompletionSource <char>();

            mountTask = Task.Factory.StartNew(
                async() =>
            {
                try
                {
                    lock (mountLock)
                    {
                        if (mountedLetter != null)
                        {
                            return;
                        }

                        mountedLetter = driveLetter;
                    }
                    AmazonDrive amazon = await Authenticate(cs, interactiveAuth);
                    if (amazon == null)
                    {
                        Log.Error("Authentication failed");
                        mountedEvent.SetException(new InvalidOperationException("Authentication failed"));
                        return;
                    }

                    provider                     = new FSProvider(amazon);
                    provider.CachePath           = Environment.ExpandEnvironmentVariables(Gui.Properties.Settings.Default.CacheFolder);
                    provider.SmallFilesCacheSize = Gui.Properties.Settings.Default.SmallFilesCacheLimit * (1 << 20);
                    provider.SmallFileSizeLimit  = Gui.Properties.Settings.Default.SmallFileSizeLimit * (1 << 20);
                    provider.OnStatisticsUpdated = ProviderStatisticsUpdated;
                    cloudDrive                   = new VirtualDriveWrapper(provider);
                    cloudDrive.Mounted           = () =>
                    {
                        mountedEvent.SetResult((char)mountedLetter);
                    };

                    OnMountChanged?.Invoke();
                    try
                    {
                        cloudDrive.Mount(mountedLetter + ":\\", readOnly);
                        mountedLetter = null;
                    }
                    catch (InvalidOperationException)
                    {
                        Log.Warn($"Drive letter {mountedLetter} is already used");
                        Exception lastException = null;
                        foreach (char letter in VirtualDriveWrapper.GetFreeDriveLettes())
                        {
                            try
                            {
                                mountedLetter = letter;
                                cloudDrive.Mount(mountedLetter + ":\\", readOnly);
                                break;
                            }
                            catch (InvalidOperationException ex)
                            {
                                lastException = ex;
                                Log.Warn($"Drive letter {letter} is already used");
                            }
                        }
                        if (mountedLetter != null)
                        {
                            var message = "Could not find free letter";
                            if (lastException != null && lastException.InnerException != null)
                            {
                                message = lastException.InnerException.Message;
                            }

                            mountedEvent.SetException(new InvalidOperationException(message));
                        }
                    }
                }
                catch (Exception ex)
                {
                    mountedEvent.SetException(ex);
                }
                finally
                {
                    mountedLetter = null;
                    mounted       = 0;
                    OnMountChanged?.Invoke();
                }
            }, TaskCreationOptions.LongRunning).Unwrap();
            return(await mountedEvent.Task);
        }
Beispiel #2
0
        private async Task <char> Mount(bool interactiveAuth = true)
        {
            try
            {
                Instance.OnAuthUpdated = this;
                var authenticated = await Authenticate(Instance, MountCancellation.Token, interactiveAuth);

                if (!authenticated)
                {
                    Log.ErrorTrace("Authentication failed");
                    throw new InvalidOperationException("Authentication failed");
                }

                var origProv = new FSProvider(instance, ProviderStatisticsUpdated)
                {
                    VolumeName          = CloudInfo.Name,
                    CachePath           = Environment.ExpandEnvironmentVariables(Properties.Settings.Default.CacheFolder),
                    SmallFilesCacheSize = Properties.Settings.Default.SmallFilesCacheLimit * (1 << 20),
                    SmallFileSizeLimit  = Properties.Settings.Default.SmallFileSizeLimit * (1 << 20)
                };

                var rfProv = new RootFolderFSProvider(origProv);
                await rfProv.SetRootFolder(CloudInfo.RootFolder);

                Provider = rfProv;

                var cloudDrive = new VirtualDriveWrapper(Provider);

                var mountedEvent = new TaskCompletionSource <char>();

                cloudDrive.Mounted = letter =>
                {
                    mountedEvent.SetResult(letter);
                };

                NotifyMount();

                var task = Task.Factory.StartNew(
                    () =>
                {
                    try
                    {
                        cloudDrive.Mount(CloudInfo.DriveLetter, CloudInfo.ReadOnly);
                        unmountingEvent.Set();
                    }
                    catch (InvalidOperationException)
                    {
                        Log.Warn($"Drive letter {CloudInfo.DriveLetter} is already used");
                        Exception lastException = null;
                        var wasMounted          = false;
                        foreach (var letter in VirtualDriveWrapper.GetFreeDriveLettes())
                        {
                            try
                            {
                                cloudDrive.Mount(letter, CloudInfo.ReadOnly);
                                unmountingEvent.Set();
                                Instance.Dispose();
                                instance   = null;
                                wasMounted = true;
                                break;
                            }
                            catch (InvalidOperationException ex)
                            {
                                lastException = ex;
                                Log.Warn($"Drive letter {letter} is already used");
                            }
                        }

                        if (!wasMounted)
                        {
                            var message = "Could not find free letter";
                            if (lastException?.InnerException != null)
                            {
                                message = lastException.InnerException.Message;
                            }

                            mountedEvent.SetException(new InvalidOperationException(message));
                        }
                    }
                    catch (Exception ex)
                    {
                        mountedEvent.SetException(ex);
                    }
                },
                    TaskCreationOptions.LongRunning);
                return(await mountedEvent.Task);
            }
            finally
            {
                NotifyMount();
            }
        }