Skip to content

Commit 8621ed8

Browse files
committed
fix: concurrency conflict in HeaderCache.Count
1 parent a52e321 commit 8621ed8

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

src/Neo/Ledger/HeaderCache.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,26 @@ public Header this[uint index]
5555
/// <summary>
5656
/// Gets the number of elements in the cache.
5757
/// </summary>
58-
public int Count => headers.Count;
58+
public int Count
59+
{
60+
get
61+
{
62+
readerWriterLock.EnterReadLock();
63+
try
64+
{
65+
return headers.Count;
66+
}
67+
finally
68+
{
69+
readerWriterLock.ExitReadLock();
70+
}
71+
}
72+
}
5973

6074
/// <summary>
6175
/// Indicates whether the cache is full.
6276
/// </summary>
63-
public bool Full => headers.Count >= 10000;
77+
public bool Full => Count >= 10000;
6478

6579
/// <summary>
6680
/// Gets the last <see cref="Header"/> in the cache. Or <see langword="null"/> if the cache is empty.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright (C) 2015-2024 The Neo Project.
2+
//
3+
// UT_HeaderCache.cs file belongs to the neo project and is free
4+
// software distributed under the MIT software license, see the
5+
// accompanying file LICENSE in the main directory of the
6+
// repository or http://www.opensource.org/licenses/mit-license.php
7+
// for more details.
8+
//
9+
// Redistribution and use in source and binary forms with or without
10+
// modifications are permitted.
11+
12+
using FluentAssertions;
13+
using Microsoft.VisualStudio.TestTools.UnitTesting;
14+
using Neo.Ledger;
15+
using Neo.Network.P2P.Payloads;
16+
using System;
17+
18+
19+
namespace Neo.UnitTests.Ledger
20+
{
21+
[TestClass]
22+
public class UT_HeaderCache
23+
{
24+
25+
[TestMethod]
26+
public void TestHeaderCache()
27+
{
28+
var cache = new HeaderCache();
29+
var header = new Header();
30+
header.Index = 1;
31+
cache.Add(header);
32+
33+
var got = cache[1];
34+
got.Should().NotBeNull();
35+
got.Index.Should().Be(1);
36+
37+
var count = cache.Count;
38+
count.Should().Be(1);
39+
40+
var full = cache.Full;
41+
full.Should().BeFalse();
42+
43+
var last = cache.Last;
44+
last.Should().NotBeNull();
45+
last.Index.Should().Be(1);
46+
47+
got = cache[2];
48+
got.Should().BeNull();
49+
50+
// enumerate
51+
var enumerator = cache.GetEnumerator();
52+
enumerator.MoveNext().Should().BeTrue();
53+
enumerator.Current.Index.Should().Be(1);
54+
enumerator.MoveNext().Should().BeFalse();
55+
56+
var removed = cache.TryRemoveFirst(out header);
57+
removed.Should().BeTrue();
58+
59+
count = cache.Count;
60+
count.Should().Be(0);
61+
62+
full = cache.Full;
63+
full.Should().BeFalse();
64+
65+
last = cache.Last;
66+
last.Should().BeNull();
67+
68+
got = cache[1];
69+
got.Should().BeNull();
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)