forked from ravendb/ravendb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RavenDB-17054 We need to get the write lock when accessing compressio…
…n.buffers during ZeroCompressionBuffer() call. In RavenDB we call it on our own if a database is encrypted from the tx merger and an index instance so we need to ensure it won't be called concurrently.
- Loading branch information
1 parent
9e4c8f8
commit ed5815d
Showing
2 changed files
with
102 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System; | ||
using System.Threading; | ||
using FastTests.Voron; | ||
using Sparrow.Server; | ||
using Voron; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
|
||
namespace SlowTests.Voron.Issues | ||
{ | ||
public class RavenDB_17054 : StorageTest | ||
{ | ||
public RavenDB_17054(ITestOutputHelper output) : base(output) | ||
{ | ||
} | ||
|
||
protected override void Configure(StorageEnvironmentOptions options) | ||
{ | ||
options.Encryption.MasterKey = Sodium.GenerateRandomBuffer((int)Sodium.crypto_aead_xchacha20poly1305_ietf_keybytes()); | ||
options.MaxScratchBufferSize = 65536 - 1; // to make ShouldReduceSizeOfCompressionPager() return true | ||
options.Encryption.RegisterForJournalCompressionHandler(); | ||
} | ||
|
||
[Fact] | ||
public void WeNeedToTakeWriteLockWhenZeroCompressionBufferIsCalled() | ||
{ | ||
var testingActionWasCalled = false; | ||
|
||
Exception startTransactionException = null; | ||
|
||
var zeroCompressionBufferThread = new Thread(() => | ||
{ | ||
try | ||
{ | ||
using (var tx = Env.WriteTransaction()) | ||
{ | ||
Env.Journal.ZeroCompressionBuffer(tx.LowLevelTransaction); // this can be called by an index e.g. when forceMemoryCleanup is true | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
startTransactionException = e; | ||
} | ||
}); | ||
|
||
Env.Journal.ForTestingPurposesOnly().OnReduceSizeOfCompressionBufferIfNeeded_RightAfterDisposingCompressionPager += () => | ||
{ | ||
testingActionWasCalled = true; | ||
zeroCompressionBufferThread.Start(); | ||
Thread.Sleep(1000); // give the thread more time to ensure that ZeroCompressionBuffer will wait for _writeLock | ||
}; | ||
|
||
// in RavenDB we call TryReduceSizeOfCompressionBufferIfNeeded when a database is idle, then we call IndexStore?.RunIdleOperations(mode) | ||
// although an index can still run ZeroCompressionBuffer concurrently e.g. when forceMemoryCleanup is true | ||
Env.Journal.TryReduceSizeOfCompressionBufferIfNeeded(); | ||
|
||
Assert.True(testingActionWasCalled); | ||
|
||
Assert.True(zeroCompressionBufferThread.Join(TimeSpan.FromSeconds(30)), "zeroCompressionBufferThread.Join(TimeSpan.FromSeconds(30))"); | ||
|
||
Assert.Null(startTransactionException); | ||
} | ||
} | ||
} |