Skip to content

Commit

Permalink
Fixes deadlock in BTree split..
Browse files Browse the repository at this point in the history
  • Loading branch information
koculu committed Aug 30, 2022
1 parent a6fb79f commit 8416d2d
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/Playground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
CompressionMethod.Zstd,
CompressionMethod.Gzip
};
test2.Count = test1.Count = 100_000_000;
test2.Count = test1.Count = 5_000_000;
test2.WALMode = test1.WALMode = WriteAheadLogMode.None;

b.NewSection("int-int insert");
Expand All @@ -72,7 +72,7 @@
test2.AddDatabaseFileUsage(stats);
}

/*b.NewSection("int-int iterate");
b.NewSection("int-int iterate");
foreach (var method in methods)
{
test1.CompressionMethod = method;
Expand All @@ -84,7 +84,7 @@
{
test2.CompressionMethod = method;
b.Run(test2.Iterate);
}*/
}

File.WriteAllText(@"..\..\data\benchmark.json", b.ToJSON());
}
5 changes: 5 additions & 0 deletions src/ZoneTree/Collections/BTree/BTree.Node.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ public void WriteLock()
Locker.WriteLock();
}

public bool TryEnterWriteLock(int millisecondsTimeout)
{
return Locker.TryEnterWriteLock(millisecondsTimeout);
}

public void WriteUnlock()
{
Locker.WriteUnlock();
Expand Down
49 changes: 47 additions & 2 deletions src/ZoneTree/Collections/BTree/BTree.Write.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,59 @@ void SplitChild(Node parent, int parentInsertPosition, Node child)
pre.WriteLock();
}

// HANDLE DEADLOCK
// childLeaf => LOCKED BY US
// PRE => LOCKED BY US
// NEXT => LOCKED BY ANOTHER SPLIT!!!
// DEADLOCK !!!...
// SOLUTION:
// TRY TO LOCK NEXT WITH TIMEOUT
// IF CAN NOT LOCK IN TIME UNLOCK PRE
// THEN SLEEP SOME
// THEN RELOCK PRE
// AND TRY TO LOCK NEXT ONCE AGAIN IN A LOOP.
var lockTimeout = 500;
var next = childLeaf.Next;
next?.WriteLock();
var isNextLocked = true;
while(true)
{
if (next != null)
isNextLocked = next.TryEnterWriteLock(lockTimeout);
if (isNextLocked)
break;
pre?.WriteUnlock();
Thread.Sleep(100);
pre?.WriteLock();
while (childLeaf.Previous != pre)
{
pre.WriteUnlock();
pre = childLeaf.Previous;
pre.WriteLock();
}
}

// prevent neighbour split at the same time.
while (childLeaf.Next != next)
{
next.WriteUnlock();
next = childLeaf.Next;
next.WriteLock();
isNextLocked = true;
while (true)
{
if (next != null)
isNextLocked = next.TryEnterWriteLock(lockTimeout);
if (isNextLocked)
break;
pre?.WriteUnlock();
Thread.Sleep(100);
pre?.WriteLock();
while (childLeaf.Previous != pre)
{
pre.WriteUnlock();
pre = childLeaf.Previous;
pre.WriteLock();
}
}
}

left.Previous = pre;
Expand Down
2 changes: 2 additions & 0 deletions src/ZoneTree/Collections/BTree/ILocker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace Tenray.ZoneTree.Collections.BTree;

public interface ILocker
{
bool TryEnterWriteLock(int millisecondsTimeout);

void WriteLock();

void WriteUnlock();
Expand Down
5 changes: 5 additions & 0 deletions src/ZoneTree/Collections/BTree/Lock/MonitorLock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ public void ReadUnlock()
{
Monitor.Exit(this);
}

public bool TryEnterWriteLock(int millisecondsTimeout)
{
return Monitor.TryEnter(this, millisecondsTimeout);
}
}
5 changes: 5 additions & 0 deletions src/ZoneTree/Collections/BTree/Lock/NoLock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public void ReadLock()
public void ReadUnlock()
{
}

public bool TryEnterWriteLock(int millisecondsTimeout)
{
return true;
}
}
5 changes: 5 additions & 0 deletions src/ZoneTree/Collections/BTree/Lock/ReaderWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public void ReadUnlock()
{
Locker.ExitReadLock();
}

public bool TryEnterWriteLock(int millisecondsTimeout)
{
return Locker.TryEnterWriteLock(millisecondsTimeout);
}
}
4 changes: 2 additions & 2 deletions src/ZoneTree/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<Authors>Ahmed Yasin Koculu</Authors>
<PackageId>ZoneTree</PackageId>
<Title>ZoneTree</Title>
<ProductVersion>1.4.6.0</ProductVersion>
<Version>1.4.6.0</Version>
<ProductVersion>1.4.7.0</ProductVersion>
<Version>1.4.7.0</Version>
<Authors>Ahmed Yasin Koculu</Authors>
<AssemblyTitle>ZoneTree</AssemblyTitle>
<Description>ZoneTree is a persistent, high-performance, transactional, ACID-compliant ordered key-value database for NET. It can operate in memory or on local/cloud storage.</Description>
Expand Down

0 comments on commit 8416d2d

Please sign in to comment.