aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Providers/DirectoryService.cs
blob: 62d424696b3a77380795d4a582360a57e93bbef9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CommonIO;

namespace MediaBrowser.Controller.Providers
{
    public class DirectoryService : IDirectoryService
    {
        private readonly ILogger _logger;
		private readonly IFileSystem _fileSystem;

        private readonly ConcurrentDictionary<string, Dictionary<string, FileSystemMetadata>> _cache =
            new ConcurrentDictionary<string, Dictionary<string, FileSystemMetadata>>(StringComparer.OrdinalIgnoreCase);

		public DirectoryService(ILogger logger, IFileSystem fileSystem)
        {
            _logger = logger;
			_fileSystem = fileSystem;
        }

        public DirectoryService(IFileSystem fileSystem)
            : this(new NullLogger(), fileSystem)
        {
        }

        public IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path)
        {
            return GetFileSystemEntries(path, false);
        }

        public Dictionary<string, FileSystemMetadata> GetFileSystemDictionary(string path)
        {
            return GetFileSystemDictionary(path, false);
        }

        private Dictionary<string, FileSystemMetadata> GetFileSystemDictionary(string path, bool clearCache)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentNullException("path");
            }

            Dictionary<string, FileSystemMetadata> entries;

            if (clearCache)
            {
                Dictionary<string, FileSystemMetadata> removed;

                _cache.TryRemove(path, out removed);
            }

            if (!_cache.TryGetValue(path, out entries))
            {
                //_logger.Debug("Getting files for " + path);

                entries = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
                
                try
                {
                    // using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
					var list = _fileSystem.GetFileSystemEntries(path)
                        .ToList();

                    // Seeing dupes on some users file system for some reason
                    foreach (var item in list)
                    {
                        entries[item.FullName] = item;
                    }
                }
                catch (DirectoryNotFoundException)
                {
                }

                //var group = entries.ToLookup(i => Path.GetDirectoryName(i.FullName)).ToList();

                _cache.TryAdd(path, entries);
            }

            return entries;
        }

        private IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool clearCache)
        {
            return GetFileSystemDictionary(path, clearCache).Values;
        }

        public IEnumerable<FileSystemMetadata> GetFiles(string path)
        {
            return GetFiles(path, false);
        }

        public IEnumerable<FileSystemMetadata> GetFiles(string path, bool clearCache)
        {
            return GetFileSystemEntries(path, clearCache).Where(i => !i.IsDirectory);
        }

        public FileSystemMetadata GetFile(string path)
        {
            var directory = Path.GetDirectoryName(path);

            if (string.IsNullOrWhiteSpace(directory))
            {
                _logger.Debug("Parent path is null for {0}", path);
                return null;
            }

            try
            {
                var dict = GetFileSystemDictionary(directory, false);

                FileSystemMetadata entry;
                dict.TryGetValue(path, out entry);

                return entry;
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error in GetFileSystemDictionary. Directory: :{0}. Original path: {1}", ex, directory, path);
                return null;
            }
        }

        public IEnumerable<FileSystemMetadata> GetDirectories(string path)
        {
            return GetFileSystemEntries(path, false).Where(i => i.IsDirectory);
        }
    }
}