Skip to content

Commit 6d55a3f

Browse files
committed
v2.5.5083.0
1 parent ca45391 commit 6d55a3f

File tree

78 files changed

+3231
-1725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+3231
-1725
lines changed

ITHit.FileSystem.Samples.Common/ClientLockFailedException.cs renamed to ITHit.FileSystem.Samples.Common.Windows/ClientLockFailedException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.IO;
44
using System.Text;
55

6-
namespace ITHit.FileSystem.Samples.Common
6+
namespace ITHit.FileSystem.Samples.Common.Windows
77
{
88
/// <summary>
99
/// Thrown when a file can not be locked. For example when a lock-token file is blocked

ITHit.FileSystem.Samples.Common/CustomData.cs renamed to ITHit.FileSystem.Samples.Common.Windows/CustomData.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.Text;
77
using System.Threading.Tasks;
88

9-
namespace ITHit.FileSystem.Samples.Common
9+
namespace ITHit.FileSystem.Samples.Common.Windows
1010
{
1111
/// <summary>
1212
/// Custom data stored with a file or folder placeholder, such original file/folder path. Max 4KB.
@@ -114,11 +114,12 @@ public static bool IsMoved(this PlaceholderItem placeholder)
114114
/// <summary>
115115
/// Returns true if the item was created and must be synched to remote storage.
116116
/// </summary>
117+
/// <param name="virtualDrive">Vitrual drive.</param>
117118
/// <returns>
118119
/// True if the item was created in the user file system and does not exists
119120
/// in the remote storage. False otherwise.
120121
/// </returns>
121-
public static bool IsNew(this PlaceholderItem placeholder)
122+
public static bool IsNew(this PlaceholderItem placeholder, VirtualDriveBase virtualDrive)
122123
{
123124
// ETag absence signals that the item is new.
124125
// However, ETag file may not exists during move operation,
@@ -128,7 +129,7 @@ public static bool IsNew(this PlaceholderItem placeholder)
128129

129130
string originalPath = placeholder.GetOriginalPath();
130131

131-
bool eTagFileExists = File.Exists(ETag.GetETagFilePath(placeholder.Path));
132+
bool eTagFileExists = File.Exists(virtualDrive.GetETagManager(placeholder.Path).ETagFilePath);
132133

133134
return !eTagFileExists && string.IsNullOrEmpty(originalPath);
134135
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace ITHit.FileSystem.Samples.Common.Windows
8+
{
9+
/// <summary>
10+
/// Provides method for reading and writing ETags.
11+
/// </summary>
12+
public class ETagManager
13+
{
14+
private readonly string userFileSystemPath;
15+
private readonly string userFileSystemRootPath;
16+
private readonly string serverDataFolderPath;
17+
private readonly ILogger logger;
18+
internal readonly string ETagFilePath;
19+
20+
private const string eTagExt = ".etag";
21+
22+
/// <summary>
23+
/// Creates instance of this class.
24+
/// </summary>
25+
/// <param name="userFileSystemRootPath">User file system root path.</param>
26+
/// <param name="serverDataFolderPath">Folder where ETags are stored.</param>
27+
/// <param name="logger">Logger.</param>
28+
internal ETagManager(string userFileSystemPath, string serverDataFolderPath, string userFileSystemRootPath, ILogger logger)
29+
{
30+
this.userFileSystemPath = userFileSystemPath;
31+
this.userFileSystemRootPath = userFileSystemRootPath;
32+
this.serverDataFolderPath = serverDataFolderPath;
33+
this.logger = logger;
34+
this.ETagFilePath = $"{GetEtagFilePath(userFileSystemPath)}{eTagExt}";
35+
}
36+
37+
/// <summary>
38+
/// Creates or updates ETag associated with the file.
39+
/// </summary>
40+
/// <param name="eTag">ETag.</param>
41+
/// <returns></returns>
42+
public async Task SetETagAsync(string eTag)
43+
{
44+
// Delete ETag file if null or empty string value is passed.
45+
if (string.IsNullOrEmpty(eTag) && File.Exists(ETagFilePath))
46+
{
47+
DeleteETag();
48+
}
49+
50+
Directory.CreateDirectory(Path.GetDirectoryName(ETagFilePath));
51+
await File.WriteAllTextAsync(ETagFilePath, eTag);
52+
}
53+
54+
/// <summary>
55+
/// Gets ETag associated with a file.
56+
/// </summary>
57+
/// <returns>ETag.</returns>
58+
public async Task<string> GetETagAsync()
59+
{
60+
if (!File.Exists(ETagFilePath))
61+
{
62+
return null;
63+
}
64+
return await File.ReadAllTextAsync(ETagFilePath);
65+
}
66+
67+
/// <summary>
68+
/// Moves ETag to a new location.
69+
/// </summary>
70+
/// <param name="userFileSystemNewPath">Path of the file in the user file system to move this Etag to.</param>
71+
internal async Task MoveToAsync(string userFileSystemNewPath)
72+
{
73+
// Move ETag file.
74+
string eTagTargetPath = GetEtagFilePath(userFileSystemNewPath);
75+
string eTagFileTargetPath = $"{eTagTargetPath}{eTagExt}";
76+
77+
// Ensure the target directory exisit, in case we are moving into empty folder or which is offline.
78+
new FileInfo(eTagFileTargetPath).Directory.Create();
79+
File.Move(ETagFilePath, eTagFileTargetPath);
80+
81+
// If this is a folder, move all eTags in this folder.
82+
string eTagSourceFolderPath = GetEtagFilePath(userFileSystemPath);
83+
if (Directory.Exists(eTagSourceFolderPath))
84+
{
85+
Directory.Move(eTagSourceFolderPath, eTagTargetPath);
86+
}
87+
}
88+
89+
/// <summary>
90+
/// Deletes ETag associated with a file.
91+
/// </summary>
92+
internal void DeleteETag()
93+
{
94+
File.Delete(ETagFilePath);
95+
96+
// If this is a folder, delete all eTags in this folder.
97+
string eTagFolderPath = GetEtagFilePath(userFileSystemPath);
98+
if (Directory.Exists(eTagFolderPath))
99+
{
100+
Directory.Delete(eTagFolderPath, true);
101+
}
102+
}
103+
104+
/// <summary>
105+
/// Returns true if the remote storage ETag and user file system ETags are equal. False - otherwise.
106+
/// </summary>
107+
/// <param name="remoteStorageItem">Remote storage item info.</param>
108+
/// <remarks>
109+
/// ETag is updated on the server during every document update and is sent to client with a file.
110+
/// During user file system to remote storage update it is sent back to the remote storage together with a modified content.
111+
/// This ensures the changes in the remote storage are not overwritten if the document on the server is modified.
112+
/// </remarks>
113+
public async Task<bool> ETagEqualsAsync(FileSystemItemMetadata remoteStorageItem)
114+
{
115+
string remoteStorageETag = remoteStorageItem.ETag;
116+
string userFileSystemETag = await GetETagAsync();
117+
118+
if (string.IsNullOrEmpty(remoteStorageETag) && string.IsNullOrEmpty(userFileSystemETag))
119+
{
120+
// We assume the remote storage is not using ETags or no ETag is ssociated with this file/folder.
121+
return true;
122+
}
123+
124+
return remoteStorageETag == userFileSystemETag;
125+
}
126+
127+
/// <summary>
128+
/// Gets ETag file path (without extension).
129+
/// </summary>
130+
/// <param name="userFileSystemPath">Path of the file in user file system to get ETag path for.</param>
131+
private string GetEtagFilePath(string userFileSystemPath)
132+
{
133+
// Get path relative to the virtual root.
134+
string relativePath = userFileSystemPath.TrimEnd(Path.DirectorySeparatorChar).Substring(
135+
userFileSystemRootPath.TrimEnd(Path.DirectorySeparatorChar).Length);
136+
137+
return $"{serverDataFolderPath.TrimEnd(Path.DirectorySeparatorChar)}{relativePath}";
138+
}
139+
}
140+
}

ITHit.FileSystem.Samples.Common/FsPath.cs renamed to ITHit.FileSystem.Samples.Common.Windows/FsPath.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using Windows.Storage;
77
using FileAttributes = System.IO.FileAttributes;
88

9-
namespace ITHit.FileSystem.Samples.Common
9+
namespace ITHit.FileSystem.Samples.Common.Windows
1010
{
1111
/// <summary>
1212
/// Provides file system operations. Helps determining file and folder existence and creating file and folder items.
@@ -47,6 +47,11 @@ public static bool Exists(string path)
4747
return File.Exists(path) || Directory.Exists(path);
4848
}
4949

50+
public static FileSystemItemTypeEnum GetItemType(string path)
51+
{
52+
return FsPath.IsFile(path) ? FileSystemItemTypeEnum.File : FileSystemItemTypeEnum.Folder;
53+
}
54+
5055
/// <summary>
5156
/// Returns true if the path point to a recycle bin folder.
5257
/// </summary>
@@ -124,7 +129,7 @@ private static bool IsMsOfficeTemp(string path)
124129
return (Path.GetFileName(path).StartsWith('~') && Path.GetExtension(path).Equals(".tmp", StringComparison.InvariantCultureIgnoreCase)) // Word temp files
125130
|| (Path.GetFileName(path).StartsWith("ppt") && Path.GetExtension(path).Equals(".tmp", StringComparison.InvariantCultureIgnoreCase)) // PowerPoint temp files
126131
|| (string.IsNullOrEmpty(Path.GetExtension(path)) && (Path.GetFileName(path).Length == 8) && File.Exists(path)) // Excel temp files
127-
|| ((Path.GetFileNameWithoutExtension(path).Length == 8) && Path.GetExtension(path).Equals(".tmp", StringComparison.InvariantCultureIgnoreCase)); // Excel temp files
132+
|| ( ((Path.GetFileNameWithoutExtension(path).Length == 8) || (Path.GetFileNameWithoutExtension(path).Length == 7)) && Path.GetExtension(path).Equals(".tmp", StringComparison.InvariantCultureIgnoreCase)); // Excel temp files
128133
}
129134

130135
/// <summary>
@@ -246,6 +251,16 @@ public static string Size(string path)
246251
return null;
247252
}
248253

254+
return FormatBytes(length);
255+
}
256+
257+
/// <summary>
258+
/// Formats bytes to string.
259+
/// </summary>
260+
/// <param name="length">Bytes to format.</param>
261+
/// <returns>Human readable bytes string.</returns>
262+
public static string FormatBytes(long length)
263+
{
249264
string[] suf = { "b ", "KB", "MB", "GB", "TB", "PB", "EB" };
250265
if (length == 0)
251266
{
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>netstandard2.1</TargetFramework>
4+
<Description>Contains functionality common for all Windows Virtual Drive samples.</Description>
5+
<Authors>IT Hit LTD.</Authors>
6+
<Product>IT Hit User File System</Product>
7+
<Copyright>IT Hit LTD.</Copyright>
8+
</PropertyGroup>
9+
<ItemGroup>
10+
<PackageReference Include="log4net" Version="2.0.12" />
11+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
12+
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />
13+
</ItemGroup>
14+
<ItemGroup>
15+
<ProjectReference Include="..\..\ITHit.FileSystem\ITHit.FileSystem.Windows\ITHit.FileSystem.Windows.csproj" />
16+
<ProjectReference Include="..\ITHit.FileSystem.Samples.Common\ITHit.FileSystem.Samples.Common.csproj" />
17+
</ItemGroup>
18+
</Project>

0 commit comments

Comments
 (0)