Skip to content

Commit 739f816

Browse files
committed
Split IOContext into separate implementations
1 parent ddef617 commit 739f816

19 files changed

+201
-85
lines changed

lucene/core/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ FlushedSegment flush(DocumentsWriter.FlushNotifications flushNotifications) thro
415415
segmentInfo,
416416
fieldInfos.finish(),
417417
pendingUpdates,
418-
new IOContext(new FlushInfo(numDocsInRAM, lastCommittedBytesUsed)));
418+
IOContext.flush(new FlushInfo(numDocsInRAM, lastCommittedBytesUsed)));
419419
final double startMBUsed = lastCommittedBytesUsed / 1024. / 1024.;
420420

421421
// Apply delete-by-docID now (delete-byDocID only
@@ -599,7 +599,7 @@ void sealFlushedSegment(
599599
IndexWriter.setDiagnostics(newSegment.info, IndexWriter.SOURCE_FLUSH);
600600

601601
IOContext context =
602-
new IOContext(new FlushInfo(newSegment.info.maxDoc(), newSegment.sizeInBytes()));
602+
IOContext.flush(new FlushInfo(newSegment.info.maxDoc(), newSegment.sizeInBytes()));
603603

604604
boolean success = false;
605605
try {

lucene/core/src/java/org/apache/lucene/index/IndexWriter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3058,7 +3058,7 @@ public long addIndexes(Directory... dirs) throws IOException {
30583058
}
30593059

30603060
IOContext context =
3061-
new IOContext(new FlushInfo(info.info.maxDoc(), info.sizeInBytes()));
3061+
IOContext.flush(new FlushInfo(info.info.maxDoc(), info.sizeInBytes()));
30623062

30633063
FieldInfos fis = readFieldInfos(info);
30643064
for (FieldInfo fi : fis) {
@@ -3400,7 +3400,7 @@ public void addIndexesReaderMerge(MergePolicy.OneMerge merge) throws IOException
34003400
testReserveDocs(numDocs);
34013401

34023402
final IOContext context =
3403-
new IOContext(
3403+
IOContext.merge(
34043404
new MergeInfo(Math.toIntExact(numDocs), -1, false, UNBOUNDED_MAX_MERGE_SEGMENTS));
34053405

34063406
TrackingDirectoryWrapper trackingDir = new TrackingDirectoryWrapper(mergeDirectory);
@@ -3950,7 +3950,7 @@ public void setMergeInfo(SegmentCommitInfo info) {
39503950
boolean closeReaders = true;
39513951
try {
39523952
for (MergePolicy.OneMerge merge : pointInTimeMerges.merges) {
3953-
IOContext context = new IOContext(merge.getStoreMergeInfo());
3953+
IOContext context = IOContext.merge(merge.getStoreMergeInfo());
39543954
merge.initMergeReaders(
39553955
sci -> {
39563956
final ReadersAndUpdates rld = getPooledInstance(sci, true);
@@ -5139,7 +5139,7 @@ private int mergeMiddle(MergePolicy.OneMerge merge, MergePolicy mergePolicy) thr
51395139
merge.checkAborted();
51405140

51415141
Directory mergeDirectory = mergeScheduler.wrapForMerge(merge, directory);
5142-
IOContext context = new IOContext(merge.getStoreMergeInfo());
5142+
IOContext context = IOContext.merge(merge.getStoreMergeInfo());
51435143

51445144
final TrackingDirectoryWrapper dirWrapper = new TrackingDirectoryWrapper(mergeDirectory);
51455145

lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ private synchronized void handleDVUpdates(
321321
}
322322
final long nextDocValuesGen = info.getNextDocValuesGen();
323323
final String segmentSuffix = Long.toString(nextDocValuesGen, Character.MAX_RADIX);
324-
final IOContext updatesContext = new IOContext(new FlushInfo(info.info.maxDoc(), bytes));
324+
final IOContext updatesContext = IOContext.flush(new FlushInfo(info.info.maxDoc(), bytes));
325325
final FieldInfo fieldInfo = infos.fieldInfo(field);
326326
assert fieldInfo != null;
327327
fieldInfo.setDocValuesGen(nextDocValuesGen);
@@ -536,7 +536,7 @@ private synchronized Set<String> writeFieldInfosGen(
536536
// HEADER + FOOTER: 40
537537
// 90 bytes per-field (over estimating long name and attributes map)
538538
final long estInfosSize = 40 + 90L * fieldInfos.size();
539-
final IOContext infosContext = new IOContext(new FlushInfo(info.info.maxDoc(), estInfosSize));
539+
final IOContext infosContext = IOContext.flush(new FlushInfo(info.info.maxDoc(), estInfosSize));
540540
// separately also track which files were created for this gen
541541
final TrackingDirectoryWrapper trackingDir = new TrackingDirectoryWrapper(dir);
542542
infosFormat.write(trackingDir, info.info, segmentSuffix, fieldInfos, infosContext);

lucene/core/src/java/org/apache/lucene/index/SortingTermVectorsConsumer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void flush(
8686
@Override
8787
void initTermVectorsWriter() throws IOException {
8888
if (writer == null) {
89-
IOContext context = new IOContext(new FlushInfo(lastDocID, bytesUsed.get()));
89+
IOContext context = IOContext.flush(new FlushInfo(lastDocID, bytesUsed.get()));
9090
tmpDirectory = new TrackingTmpOutputDirectoryWrapper(directory);
9191
writer = TEMP_TERM_VECTORS_FORMAT.vectorsWriter(tmpDirectory, info, context);
9292
lastDocID = 0;

lucene/core/src/java/org/apache/lucene/index/TermVectorsConsumer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void fill(int docID) throws IOException {
102102

103103
void initTermVectorsWriter() throws IOException {
104104
if (writer == null) {
105-
IOContext context = new IOContext(new FlushInfo(lastDocID, bytesUsed.get()));
105+
IOContext context = IOContext.flush(new FlushInfo(lastDocID, bytesUsed.get()));
106106
writer = codec.termVectorsFormat().vectorsWriter(directory, info, context);
107107
lastDocID = 0;
108108
accountable = writer;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.lucene.store;
18+
19+
import java.util.Arrays;
20+
import java.util.Objects;
21+
22+
record DefaultIOContext(ReadAdvice readAdvice) implements IOContext {
23+
24+
public DefaultIOContext {
25+
Objects.requireNonNull(readAdvice);
26+
}
27+
28+
@Override
29+
public Context context() {
30+
return Context.DEFAULT;
31+
}
32+
33+
@Override
34+
public MergeInfo mergeInfo() {
35+
return null;
36+
}
37+
38+
@Override
39+
public FlushInfo flushInfo() {
40+
return null;
41+
}
42+
43+
private static final DefaultIOContext[] READADVICE_TO_IOCONTEXT =
44+
Arrays.stream(ReadAdvice.values())
45+
.map(DefaultIOContext::new)
46+
.toArray(DefaultIOContext[]::new);
47+
48+
@Override
49+
public DefaultIOContext withReadAdvice(ReadAdvice advice) {
50+
return READADVICE_TO_IOCONTEXT[advice.ordinal()];
51+
}
52+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.lucene.store;
18+
19+
import java.util.Objects;
20+
21+
record FlushIOContext(FlushInfo flushInfo) implements IOContext {
22+
public FlushIOContext {
23+
Objects.requireNonNull(flushInfo);
24+
}
25+
26+
@Override
27+
public Context context() {
28+
return Context.FLUSH;
29+
}
30+
31+
@Override
32+
public MergeInfo mergeInfo() {
33+
return null;
34+
}
35+
36+
@Override
37+
public ReadAdvice readAdvice() {
38+
return ReadAdvice.SEQUENTIAL;
39+
}
40+
41+
@Override
42+
public IOContext withReadAdvice(ReadAdvice advice) {
43+
return this;
44+
}
45+
}

lucene/core/src/java/org/apache/lucene/store/IOContext.java

Lines changed: 22 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,18 @@
1616
*/
1717
package org.apache.lucene.store;
1818

19-
import java.util.Arrays;
20-
import java.util.Objects;
2119
import org.apache.lucene.util.Constants;
2220

2321
/**
2422
* IOContext holds additional details on the merge/search context. An IOContext object can never be
2523
* passed as a {@code null} parameter to either {@link
2624
* org.apache.lucene.store.Directory#openInput(String, IOContext)} or {@link
2725
* org.apache.lucene.store.Directory#createOutput(String, IOContext)}
28-
*
29-
* @param context An object of a enumerator Context type
30-
* @param mergeInfo must be given when {@code context == MERGE}
31-
* @param flushInfo must be given when {@code context == FLUSH}
32-
* @param readAdvice Advice regarding the read access pattern
3326
*/
34-
public record IOContext(
35-
Context context, MergeInfo mergeInfo, FlushInfo flushInfo, ReadAdvice readAdvice) {
27+
public interface IOContext {
3628

3729
/** Context is an enumerator which specifies the context in which the Directory is being used. */
38-
public enum Context {
30+
enum Context {
3931
/** Context for reads and writes that are associated with a merge. */
4032
MERGE,
4133
/** Context for writes that are associated with a segment flush. */
@@ -51,64 +43,44 @@ public enum Context {
5143
* <p>It will use {@link ReadAdvice#RANDOM} by default, unless set by system property {@code
5244
* org.apache.lucene.store.defaultReadAdvice}.
5345
*/
54-
public static final IOContext DEFAULT = new IOContext(Constants.DEFAULT_READADVICE);
46+
IOContext DEFAULT = new DefaultIOContext(Constants.DEFAULT_READADVICE);
5547

5648
/**
5749
* A default context for reads with {@link ReadAdvice#SEQUENTIAL}.
5850
*
5951
* <p>This context should only be used when the read operations will be performed in the same
6052
* thread as the thread that opens the underlying storage.
6153
*/
62-
public static final IOContext READONCE = new IOContext(ReadAdvice.SEQUENTIAL);
54+
IOContext READONCE = new DefaultIOContext(ReadAdvice.SEQUENTIAL);
6355

64-
@SuppressWarnings("incomplete-switch")
65-
public IOContext {
66-
Objects.requireNonNull(context, "context must not be null");
67-
Objects.requireNonNull(readAdvice, "readAdvice must not be null");
68-
switch (context) {
69-
case MERGE ->
70-
Objects.requireNonNull(mergeInfo, "mergeInfo must not be null if context is MERGE");
71-
case FLUSH ->
72-
Objects.requireNonNull(flushInfo, "flushInfo must not be null if context is FLUSH");
73-
}
74-
if ((context == Context.FLUSH || context == Context.MERGE)
75-
&& readAdvice != ReadAdvice.SEQUENTIAL) {
76-
throw new IllegalArgumentException(
77-
"The FLUSH and MERGE contexts must use the SEQUENTIAL read access advice");
78-
}
56+
/** Returns an {@link IOContext} for merging with the specified {@link MergeInfo} */
57+
static IOContext merge(MergeInfo mergeInfo) {
58+
return new MergeIOContext(mergeInfo);
7959
}
8060

81-
/** Creates a default {@link IOContext} for reading/writing with the given {@link ReadAdvice} */
82-
private IOContext(ReadAdvice accessAdvice) {
83-
this(Context.DEFAULT, null, null, accessAdvice);
61+
/** Returns an {@link IOContext} for flushing with the specified {@link FlushInfo} */
62+
static IOContext flush(FlushInfo flushInfo) {
63+
return new FlushIOContext(flushInfo);
8464
}
8565

86-
/** Creates an {@link IOContext} for flushing. */
87-
public IOContext(FlushInfo flushInfo) {
88-
this(Context.FLUSH, null, flushInfo, ReadAdvice.SEQUENTIAL);
89-
}
66+
/** The {@link Context} this context is for */
67+
Context context();
9068

91-
/** Creates an {@link IOContext} for merging. */
92-
public IOContext(MergeInfo mergeInfo) {
93-
// Merges read input segments sequentially.
94-
this(Context.MERGE, mergeInfo, null, ReadAdvice.SEQUENTIAL);
95-
}
69+
/** Merge info, if {@link #context()} is {@link Context#MERGE} */
70+
MergeInfo mergeInfo();
9671

97-
private static final IOContext[] READADVICE_TO_IOCONTEXT =
98-
Arrays.stream(ReadAdvice.values()).map(IOContext::new).toArray(IOContext[]::new);
72+
/** Flush info, if {@link #context()} is {@link Context#FLUSH} */
73+
FlushInfo flushInfo();
74+
75+
/** Advice on the expected read access pattern */
76+
ReadAdvice readAdvice();
9977

10078
/**
101-
* Return an updated {@link IOContext} that has the provided {@link ReadAdvice} if the {@link
102-
* Context} is a {@link Context#DEFAULT} context, otherwise return this existing instance. This
79+
* Return an updated {@link IOContext} that has the provided {@link ReadAdvice}, if the provided
80+
* advice is compatible with the current context, otherwise return this existing instance. This
10381
* helps preserve a {@link ReadAdvice#SEQUENTIAL} advice for merging, which is always the right
10482
* choice, while allowing {@link IndexInput}s open for searching to use arbitrary {@link
10583
* ReadAdvice}s.
10684
*/
107-
public IOContext withReadAdvice(ReadAdvice advice) {
108-
if (context == Context.DEFAULT) {
109-
return READADVICE_TO_IOCONTEXT[advice.ordinal()];
110-
} else {
111-
return this;
112-
}
113-
}
85+
IOContext withReadAdvice(ReadAdvice advice);
11486
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.lucene.store;
18+
19+
import java.util.Objects;
20+
21+
record MergeIOContext(MergeInfo mergeInfo) implements IOContext {
22+
23+
public MergeIOContext {
24+
Objects.requireNonNull(mergeInfo);
25+
}
26+
27+
@Override
28+
public Context context() {
29+
return Context.MERGE;
30+
}
31+
32+
@Override
33+
public FlushInfo flushInfo() {
34+
return null;
35+
}
36+
37+
@Override
38+
public ReadAdvice readAdvice() {
39+
return ReadAdvice.SEQUENTIAL;
40+
}
41+
42+
@Override
43+
public IOContext withReadAdvice(ReadAdvice advice) {
44+
return this;
45+
}
46+
}

lucene/core/src/test/org/apache/lucene/index/TestDoc.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ private SegmentCommitInfo merge(
210210
String merged,
211211
boolean useCompoundFile)
212212
throws Exception {
213-
IOContext context = newIOContext(random(), new IOContext(new MergeInfo(-1, -1, false, -1)));
213+
IOContext context = newIOContext(random(), IOContext.merge(new MergeInfo(-1, -1, false, -1)));
214214
SegmentReader r1 = new SegmentReader(si1, Version.LATEST.major, context);
215215
SegmentReader r2 = new SegmentReader(si2, Version.LATEST.major, context);
216216

0 commit comments

Comments
 (0)