Skip to content

Commit 56ace91

Browse files
committed
BREAKING: Lucene.Net.Store.DataOutput: Added abstract overload of WriteBytes(ReadOnlySpan<byte>) and made the WriteBytes(byte[], int, int) overload virtual.
1 parent 63f52bb commit 56ace91

19 files changed

Lines changed: 209 additions & 63 deletions

src/Lucene.Net.TestFramework/Store/MockDirectoryWrapper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,9 +1444,10 @@ public BufferedIndexOutputWrapper(int bufferSize, IndexOutput io)
14441444

14451445
public override long Length => io.Length;
14461446

1447-
protected internal override void FlushBuffer(byte[] b, int offset, int len)
1447+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
1448+
protected internal override void FlushBuffer(ReadOnlySpan<byte> bytes)
14481449
{
1449-
io.WriteBytes(b, offset, len);
1450+
io.WriteBytes(bytes);
14501451
}
14511452

14521453
[Obsolete("(4.1) this method will be removed in Lucene 5.0")]

src/Lucene.Net.TestFramework/Store/MockIndexOutputWrapper.cs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.IO;
55
using System.Threading;
6+
#nullable enable
67

78
namespace Lucene.Net.Store
89
{
@@ -56,7 +57,7 @@ private void CheckCrashed()
5657
}
5758
}
5859

59-
private void CheckDiskFull(byte[] b, int offset, DataInput @in, long len)
60+
private void CheckDiskFull(byte[]? b, int offset, DataInput? @in, long len)
6061
{
6162
long freeSpace = dir.maxSize == 0 ? 0 : dir.maxSize - dir.GetSizeInBytes();
6263
long realUsage = 0;
@@ -103,6 +104,48 @@ private void CheckDiskFull(byte[] b, int offset, DataInput @in, long len)
103104
}
104105
}
105106

107+
// LUCENENET specific overload
108+
private void CheckDiskFull(ReadOnlySpan<byte> source)
109+
{
110+
long len = source.Length;
111+
long freeSpace = dir.maxSize == 0 ? 0 : dir.maxSize - dir.GetSizeInBytes();
112+
long realUsage = 0;
113+
114+
// Enforce disk full:
115+
if (dir.maxSize != 0 && freeSpace <= len)
116+
{
117+
// Compute the real disk free. this will greatly slow
118+
// down our test but makes it more accurate:
119+
realUsage = dir.GetRecomputedActualSizeInBytes();
120+
freeSpace = dir.maxSize - realUsage;
121+
}
122+
123+
if (dir.maxSize != 0 && freeSpace <= len)
124+
{
125+
if (freeSpace > 0)
126+
{
127+
realUsage += freeSpace;
128+
@delegate.WriteBytes(source.Slice(/*offset*/ 0, (int)freeSpace));
129+
}
130+
if (realUsage > dir.maxUsedSize)
131+
{
132+
dir.maxUsedSize = realUsage;
133+
}
134+
string message = "fake disk full at " + dir.GetRecomputedActualSizeInBytes() + " bytes when writing " + name + " (file length=" + @delegate.Length;
135+
if (freeSpace > 0)
136+
{
137+
message += "; wrote " + freeSpace + " of " + len + " bytes";
138+
}
139+
message += ")";
140+
if (LuceneTestCase.Verbose)
141+
{
142+
Console.WriteLine(Thread.CurrentThread.Name + ": MDW: now throw fake disk full");
143+
StackTraceHelper.PrintCurrentStackTrace(Console.Out);
144+
}
145+
throw new IOException(message);
146+
}
147+
}
148+
106149
protected override void Dispose(bool disposing)
107150
{
108151
if (disposing)
@@ -141,6 +184,9 @@ public override void WriteByte(byte b)
141184
WriteBytes(singleByte, 0, 1);
142185
}
143186

187+
// LUCENENET: For performance reasons, it is better to keep this duplication, for now.
188+
// At least until we have migrated many of the callers to call the ReadOnlySpan<char> overload
189+
// directly.
144190
public override void WriteBytes(byte[] b, int offset, int len)
145191
{
146192
CheckCrashed();
@@ -169,6 +215,39 @@ public override void WriteBytes(byte[] b, int offset, int len)
169215
}
170216
}
171217

218+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
219+
public override void WriteBytes(ReadOnlySpan<byte> source)
220+
{
221+
int len = source.Length;
222+
CheckCrashed();
223+
CheckDiskFull(source);
224+
225+
if (dir.randomState.Next(200) == 0)
226+
{
227+
int half = len / 2;
228+
//@delegate.WriteBytes(b, offset, half);
229+
@delegate.WriteBytes(source.Slice(/*offset*/ 0, half));
230+
Thread.Yield();
231+
//@delegate.WriteBytes(b, offset + half, len - half);
232+
@delegate.WriteBytes(source.Slice(/*offset +*/ half, len - half));
233+
}
234+
else
235+
{
236+
//@delegate.WriteBytes(b, offset, len);
237+
@delegate.WriteBytes(source);
238+
}
239+
240+
dir.MaybeThrowDeterministicException();
241+
242+
if (first)
243+
{
244+
// Maybe throw random exception; only do this on first
245+
// write to a new file:
246+
first = false;
247+
dir.MaybeThrowIOException(name);
248+
}
249+
}
250+
172251
public override long Position => @delegate.Position; // LUCENENET specific: Renamed from getFilePointer() to match FileStream
173252

174253
[Obsolete("(4.1) this method will be removed in Lucene 5.0")]

src/Lucene.Net.TestFramework/Util/ThrottledIndexOutput.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,15 @@ public override void WriteByte(byte b)
107107
WriteBytes(bytes, 0, 1);
108108
}
109109

110-
public override void WriteBytes(byte[] b, int offset, int length)
110+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
111+
public override void WriteBytes(ReadOnlySpan<byte> source)
111112
{
113+
int length = source.Length;
112114
long before = J2N.Time.NanoTime();
113115
// TODO: sometimes, write only half the bytes, then
114116
// sleep, then 2nd half, then sleep, so we sometimes
115117
// interrupt having only written not all bytes
116-
@delegate.WriteBytes(b, offset, length);
118+
@delegate.WriteBytes(source);
117119
timeElapsed += J2N.Time.NanoTime() - before;
118120
pendingBytes += length;
119121
Sleep(GetDelay(false));

src/Lucene.Net.Tests.Facet/SlowRAMDirectory.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,15 +220,17 @@ public override void WriteByte(byte b)
220220
io.WriteByte(b);
221221
}
222222

223-
public override void WriteBytes(byte[] b, int offset, int length)
223+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
224+
public override void WriteBytes(ReadOnlySpan<byte> source)
224225
{
226+
int length = source.Length;
225227
if (numWrote >= IO_SLEEP_THRESHOLD)
226228
{
227229
outerInstance.DoSleep(rand, length);
228230
numWrote = 0;
229231
}
230232
numWrote += length;
231-
io.WriteBytes(b, offset, length);
233+
io.WriteBytes(source);
232234
}
233235

234236
[Obsolete]

src/Lucene.Net/Index/ByteSliceWriter.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using Lucene.Net.Diagnostics;
2-
using System.Diagnostics;
2+
using System;
33

44
namespace Lucene.Net.Index
55
{
@@ -69,8 +69,11 @@ public override void WriteByte(byte b)
6969
if (Debugging.AssertsEnabled) Debugging.Assert(upto != slice.Length);
7070
}
7171

72-
public override void WriteBytes(byte[] b, int offset, int len)
72+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
73+
public override void WriteBytes(ReadOnlySpan<byte> source)
7374
{
75+
int offset = 0;
76+
int len = source.Length;
7477
int offsetEnd = offset + len;
7578
while (offset < offsetEnd)
7679
{
@@ -82,7 +85,7 @@ public override void WriteBytes(byte[] b, int offset, int len)
8285
offset0 = pool.ByteOffset;
8386
}
8487

85-
slice[upto++] = (byte)b[offset++];
88+
slice[upto++] = source[offset++];
8689
if (Debugging.AssertsEnabled) Debugging.Assert(upto != slice.Length);
8790
}
8891
}

src/Lucene.Net/Store/BufferedChecksum.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Lucene.Net.Support;
2+
using System;
23

34
namespace Lucene.Net.Store
45
{
@@ -72,29 +73,30 @@ public virtual void Update(int b)
7273
}
7374

7475
// LUCENENET specific overload for updating a whole byte[] array
75-
public virtual void Update(byte[] b)
76-
{
77-
Update(b, 0, b.Length);
78-
}
79-
80-
public virtual void Update(byte[] b, int off, int len)
76+
public virtual void Update(ReadOnlySpan<byte> bytes)
8177
{
78+
int len = bytes.Length;
8279
if (len >= buffer.Length)
8380
{
8481
Flush();
85-
@in.Update(b, off, len);
82+
@in.Update(bytes);
8683
}
8784
else
8885
{
8986
if (upto + len > buffer.Length)
9087
{
9188
Flush();
9289
}
93-
Arrays.Copy(b, off, buffer, upto, len);
90+
Arrays.Copy(bytes, /*off*/ 0, buffer, upto, len);
9491
upto += len;
9592
}
9693
}
9794

95+
public virtual void Update(byte[] b, int off, int len)
96+
{
97+
Update(b.AsSpan(off, len));
98+
}
99+
98100
public virtual long Value
99101
{
100102
get

src/Lucene.Net/Store/BufferedIndexOutput.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,20 @@ public override void WriteByte(byte b)
7878

7979
public override void WriteBytes(byte[] b, int offset, int length)
8080
{
81+
WriteBytes(b.AsSpan(offset, length));
82+
}
83+
84+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
85+
public override void WriteBytes(ReadOnlySpan<byte> source)
86+
{
87+
int length = source.Length;
8188
if (buffer is null) buffer = new byte[bufferSize]; // LUCENENET: Lazy-load the buffer, so we don't force all subclasses to allocate it
8289
int bytesLeft = bufferSize - bufferPosition;
8390
// is there enough space in the buffer?
8491
if (bytesLeft >= length)
8592
{
8693
// we add the data to the end of the buffer
87-
Arrays.Copy(b, offset, buffer, bufferPosition, length);
94+
Arrays.Copy(source, /*offset*/ 0, buffer, bufferPosition, length);
8895
bufferPosition += length;
8996
// if the buffer is full, flush it
9097
if (bufferSize - bufferPosition == 0)
@@ -103,8 +110,8 @@ public override void WriteBytes(byte[] b, int offset, int length)
103110
Flush();
104111
}
105112
// and write data at once
106-
crc.Update(b, offset, length);
107-
FlushBuffer(b, offset, length);
113+
crc.Update(source);
114+
FlushBuffer(source);
108115
bufferStart += length;
109116
}
110117
else
@@ -115,7 +122,7 @@ public override void WriteBytes(byte[] b, int offset, int length)
115122
while (pos < length)
116123
{
117124
pieceLength = (length - pos < bytesLeft) ? length - pos : bytesLeft;
118-
Arrays.Copy(b, pos + offset, buffer, bufferPosition, pieceLength);
125+
Arrays.Copy(source, pos /*+ offset*/, buffer, bufferPosition, pieceLength);
119126
pos += pieceLength;
120127
bufferPosition += pieceLength;
121128
// if the buffer is full, flush it
@@ -156,7 +163,17 @@ private void FlushBuffer(byte[] b, int len)
156163
/// <param name="b"> the bytes to write </param>
157164
/// <param name="offset"> the offset in the byte array </param>
158165
/// <param name="len"> the number of bytes to write </param>
159-
protected internal abstract void FlushBuffer(byte[] b, int offset, int len);
166+
protected internal virtual void FlushBuffer(byte[] b, int offset, int len)
167+
{
168+
FlushBuffer(b.AsSpan(offset, len));
169+
}
170+
171+
/// <summary>
172+
/// Expert: implements buffer write. Writes bytes at the current position in
173+
/// the output.
174+
/// </summary>
175+
/// <param name="source">The bytes to write.</param>
176+
protected internal abstract void FlushBuffer(ReadOnlySpan<byte> source);
160177

161178
/// <inheritdoc/>
162179
protected override void Dispose(bool disposing)

src/Lucene.Net/Store/ByteArrayDataOutput.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,12 @@ public override void WriteByte(byte b)
103103
bytes[pos++] = b;
104104
}
105105

106-
public override void WriteBytes(byte[] b, int offset, int length)
106+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
107+
public override void WriteBytes(ReadOnlySpan<byte> source)
107108
{
109+
int length = source.Length;
108110
if (Debugging.AssertsEnabled) Debugging.Assert(pos + length <= limit);
109-
Arrays.Copy(b, offset, bytes, pos, length);
111+
Arrays.Copy(source, /*offset*/ 0, bytes, pos, length);
110112
pos += length;
111113
}
112114
}

src/Lucene.Net/Store/CompoundFileWriter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,13 @@ public override void WriteByte(byte b)
420420
@delegate.WriteByte(b);
421421
}
422422

423-
public override void WriteBytes(byte[] b, int offset, int length)
423+
// LUCENENET: Use ReadOnlySpan<byte> instead of byte[] for better compatibility.
424+
public override void WriteBytes(ReadOnlySpan<byte> source)
424425
{
426+
int length = source.Length;
425427
if (Debugging.AssertsEnabled) Debugging.Assert(!closed);
426428
writtenBytes += length;
427-
@delegate.WriteBytes(b, offset, length);
429+
@delegate.WriteBytes(source);
428430
}
429431

430432
public override long Checksum => @delegate.Checksum;

src/Lucene.Net/Store/DataOutput.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
using Lucene.Net.Diagnostics;
2+
using Lucene.Net.Support.Buffers;
3+
using Lucene.Net.Util;
4+
using System;
5+
using System.Buffers;
26
using System.Collections.Generic;
7+
using System.Diagnostics;
38
using System.IO;
49

510
namespace Lucene.Net.Store
@@ -21,9 +26,6 @@ namespace Lucene.Net.Store
2126
* limitations under the License.
2227
*/
2328

24-
using BytesRef = Lucene.Net.Util.BytesRef;
25-
using UnicodeUtil = Lucene.Net.Util.UnicodeUtil;
26-
2729
/// <summary>
2830
/// Abstract base class for performing write operations of Lucene's low-level
2931
/// data types.
@@ -60,7 +62,16 @@ public virtual void WriteBytes(byte[] b, int length)
6062
/// <param name="offset"> the offset in the byte array </param>
6163
/// <param name="length"> the number of bytes to write </param>
6264
/// <seealso cref="DataInput.ReadBytes(byte[], int, int)"/>
63-
public abstract void WriteBytes(byte[] b, int offset, int length);
65+
public virtual void WriteBytes(byte[] b, int offset, int length)
66+
{
67+
WriteBytes(b.AsSpan(offset, length));
68+
}
69+
70+
/// <summary>
71+
/// Writes a sequence of bytes. </summary>
72+
/// <param name="source"> the bytes to write </param>
73+
/// <seealso cref="DataInput.ReadBytes(Span{Byte})"/>
74+
public abstract void WriteBytes(ReadOnlySpan<byte> source);
6475

6576
/// <summary>
6677
/// Writes an <see cref="int"/> as four bytes.

0 commit comments

Comments
 (0)