Skip to content
3 changes: 2 additions & 1 deletion LiteDB/Client/Shared/SharedEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using LiteDB.Client.Shared;
using LiteDB.Vector;
#if NETFRAMEWORK
using System.Security.AccessControl;
Expand All @@ -22,7 +23,7 @@ public SharedEngine(EngineSettings settings)
{
_settings = settings;

var name = Path.GetFullPath(settings.Filename).ToLower().Sha1();
var name = SharedMutexNameFactory.Create(settings.Filename, settings.SharedMutexNameStrategy);

try
{
Expand Down
43 changes: 43 additions & 0 deletions LiteDB/Client/Shared/SharedMutexNameFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using LiteDB.Engine;

namespace LiteDB.Client.Shared;

internal static class SharedMutexNameFactory
{
internal static string Create(string fileName, SharedMutexNameStrategy strategy)
{
return strategy switch
{
SharedMutexNameStrategy.UriEscape or SharedMutexNameStrategy.Default => CreateUsingUriEncoding(fileName),
SharedMutexNameStrategy.Sha1Hash => CreateUsingSha1(fileName),
_ => throw new ArgumentOutOfRangeException(nameof(strategy), strategy, null)
};
}

private static string CreateUsingUriEncoding(string fileName)
{
var normalized = Path.GetFullPath(fileName).ToLowerInvariant();
return Uri.EscapeDataString(normalized);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mutex names exceed Windows limit for long database paths

Switching the default mutex name generation to CreateUsingUriEncoding encodes the entire absolute path rather than hashing it. On Windows a named mutex cannot exceed 260 characters, but an escaped full path grows by two extra characters for every directory separator and other reserved characters. Valid database files whose paths are already near MAX_PATH now cause new Mutex(false, …) to throw ArgumentException, whereas the previous SHA1 hash was always 40 characters. This makes some databases unusable when their path length is only moderately long.

Useful? React with 👍 / 👎.

}

internal static string CreateUsingSha1(string value)
{
var normalized = Path.GetFullPath(value).ToLower();
var data = Encoding.UTF8.GetBytes(normalized);

using var sha = SHA1.Create();
var hashData = sha.ComputeHash(data);
var hash = new StringBuilder();

foreach (var b in hashData)
{
hash.Append(b.ToString("X2"));
}

return hash.ToString();
}
}
5 changes: 5 additions & 0 deletions LiteDB/Engine/EngineSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ public class EngineSettings
/// Is used to transform a <see cref="BsonValue"/> from the database on read. This can be used to upgrade data from older versions.
/// </summary>
public Func<string, BsonValue, BsonValue> ReadTransform { get; set; }

/// <summary>
/// Determines how the mutex name is generated.
/// </summary>
public SharedMutexNameStrategy SharedMutexNameStrategy { get; set; }

/// <summary>
/// Create new IStreamFactory for datafile
Expand Down
9 changes: 9 additions & 0 deletions LiteDB/Engine/SharedMutexNameStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

namespace LiteDB.Engine;

public enum SharedMutexNameStrategy
{
Default,
UriEscape,
Sha1Hash
}
18 changes: 0 additions & 18 deletions LiteDB/Utils/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,6 @@ public static bool IsWord(this string str)
return true;
}

public static string Sha1(this string value)
{
var data = Encoding.UTF8.GetBytes(value);

using (var sha = SHA1.Create())
{
var hashData = sha.ComputeHash(data);
var hash = new StringBuilder();

foreach (var b in hashData)
{
hash.Append(b.ToString("X2"));
}

return hash.ToString();
}
}

/// <summary>
/// Implement SqlLike in C# string - based on
/// https://stackoverflow.com/a/8583383/3286260
Expand Down
Loading