Skip to content

Commit e0e58dc

Browse files
navneet1vPradeep L
authored andcommitted
Update MMapDirectory to use ADVISE_BY_CONTEXT rather than default (opensearch-project#21031)
Signed-off-by: Navneet Verma <navneev@amazon.com>
1 parent 0aa8646 commit e0e58dc

3 files changed

Lines changed: 64 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
3939
- Move pull-based ingestion classes from experimental to publicAPI ([#20704](https://github.com/opensearch-project/OpenSearch/pull/20704))
4040
- Lazy init stored field reader in SourceLookup ([#20827](https://github.com/opensearch-project/OpenSearch/pull/20827))
4141
* Improved error message when trying to open an index originally created with Elasticsearch on OpenSearch ([#20512](https://github.com/opensearch-project/OpenSearch/pull/20512))
42+
- Updated MMapDirectory to use ReadAdviseByContext rather than default readadvise of Lucene([#21031](https://github.com/opensearch-project/OpenSearch/pull/21031))
4243

4344
### Fixed
4445
- Relax index template pattern overlap check to use minimum-string heuristic, allowing distinguishable multi-wildcard patterns at the same priority ([#20702](https://github.com/opensearch-project/OpenSearch/pull/20702))

server/src/main/java/org/opensearch/index/store/FsDirectoryFactory.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,17 @@ public Directory newFSDirectory(Path location, LockFactory lockFactory, IndexSet
100100
final FSDirectory primaryDirectory = FSDirectory.open(location, lockFactory);
101101
final Set<String> nioExtensions = new HashSet<>(indexSettings.getValue(IndexModule.INDEX_STORE_HYBRID_NIO_EXTENSIONS));
102102
if (primaryDirectory instanceof MMapDirectory mMapDirectory) {
103+
// Setting the read advise by context: REF: https://github.com/opensearch-project/OpenSearch/issues/21012
104+
mMapDirectory.setReadAdvice(MMapDirectory.ADVISE_BY_CONTEXT);
103105
return new HybridDirectory(lockFactory, setPreload(mMapDirectory, preLoadExtensions), nioExtensions);
104106
} else {
105107
return primaryDirectory;
106108
}
107109
case MMAPFS:
108-
return setPreload(new MMapDirectory(location, lockFactory), preLoadExtensions);
110+
final MMapDirectory mMapDirectory = new MMapDirectory(location, lockFactory);
111+
// Setting the read advise by context: REF: https://github.com/opensearch-project/OpenSearch/issues/21012
112+
mMapDirectory.setReadAdvice(MMapDirectory.ADVISE_BY_CONTEXT);
113+
return setPreload(mMapDirectory, preLoadExtensions);
109114
// simplefs was removed in Lucene 9; support for enum is maintained for bwc
110115
case SIMPLEFS:
111116
case NIOFS:

server/src/test/java/org/opensearch/index/store/FsDirectoryFactoryTests.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@
3131

3232
package org.opensearch.index.store;
3333

34+
import org.apache.lucene.store.DataAccessHint;
3435
import org.apache.lucene.store.Directory;
3536
import org.apache.lucene.store.IOContext;
3637
import org.apache.lucene.store.MMapDirectory;
38+
import org.apache.lucene.store.MergeInfo;
3739
import org.apache.lucene.store.NIOFSDirectory;
3840
import org.apache.lucene.store.NoLockFactory;
41+
import org.apache.lucene.store.ReadAdvice;
3942
import org.apache.lucene.util.Constants;
4043
import org.opensearch.Version;
4144
import org.opensearch.cluster.metadata.IndexMetadata;
45+
import org.opensearch.common.SuppressForbidden;
4246
import org.opensearch.common.settings.Settings;
4347
import org.opensearch.core.index.Index;
4448
import org.opensearch.core.index.shard.ShardId;
@@ -49,11 +53,14 @@
4953
import org.opensearch.test.OpenSearchTestCase;
5054

5155
import java.io.IOException;
56+
import java.lang.reflect.Field;
5257
import java.nio.file.Files;
5358
import java.nio.file.Path;
5459
import java.util.Arrays;
5560
import java.util.Locale;
61+
import java.util.Optional;
5662
import java.util.Set;
63+
import java.util.function.BiFunction;
5764
import java.util.function.BiPredicate;
5865

5966
import static org.opensearch.test.store.MockFSDirectoryFactory.FILE_SYSTEM_BASED_STORE_TYPES;
@@ -173,6 +180,7 @@ private void doTestStoreDirectory(Path tempDir, String typeSettingValue, IndexMo
173180
switch (type) {
174181
case HYBRIDFS:
175182
assertTrue(FsDirectoryFactory.isHybridFs(directory));
183+
mMapDirectoryHasReadAdviceByContext(((FsDirectoryFactory.HybridDirectory) directory).getDelegate());
176184
break;
177185
// simplefs was removed in Lucene 9; support for enum is maintained for bwc
178186
case SIMPLEFS:
@@ -181,6 +189,7 @@ private void doTestStoreDirectory(Path tempDir, String typeSettingValue, IndexMo
181189
break;
182190
case MMAPFS:
183191
assertTrue(type + " " + directory.toString(), directory instanceof MMapDirectory);
192+
mMapDirectoryHasReadAdviceByContext((MMapDirectory) directory);
184193
break;
185194
case FS:
186195
if (Constants.JRE_IS_64BIT) {
@@ -194,4 +203,52 @@ private void doTestStoreDirectory(Path tempDir, String typeSettingValue, IndexMo
194203
}
195204
}
196205
}
206+
207+
@SuppressForbidden(reason = "Need to check the readAdvise as there is no getter on read advise")
208+
private void mMapDirectoryHasReadAdviceByContext(MMapDirectory mapDirectory) {
209+
try {
210+
@SuppressWarnings("unchecked")
211+
BiFunction<String, IOContext, Optional<ReadAdvice>> readAdvice = (BiFunction<
212+
String,
213+
IOContext,
214+
Optional<ReadAdvice>>) getReadAdviceField(mapDirectory);
215+
216+
// Verify the function behaves identically to ADVISE_BY_CONTEXT
217+
// ADVISE_BY_CONTEXT returns the ReadAdvice from the IOContext
218+
assertEquals(
219+
"Advise By context is not set",
220+
MMapDirectory.ADVISE_BY_CONTEXT.apply("test.dvd", IOContext.DEFAULT),
221+
readAdvice.apply("test.dvd", IOContext.DEFAULT)
222+
);
223+
assertEquals(
224+
"Advise By context is not set",
225+
MMapDirectory.ADVISE_BY_CONTEXT.apply("test.tim", IOContext.READONCE),
226+
readAdvice.apply("test.tim", IOContext.READONCE)
227+
);
228+
MergeInfo mergeInfo = new MergeInfo(100, 100L, false, 1);
229+
assertEquals(
230+
"Advise By context is not set",
231+
MMapDirectory.ADVISE_BY_CONTEXT.apply("test.vec", IOContext.merge(mergeInfo)),
232+
readAdvice.apply("test.vec", IOContext.merge(mergeInfo).withHints())
233+
);
234+
235+
assertEquals(
236+
"Advise By context is not set",
237+
MMapDirectory.ADVISE_BY_CONTEXT.apply("test.vec", IOContext.DEFAULT.withHints(DataAccessHint.RANDOM)),
238+
readAdvice.apply("test.vec", IOContext.DEFAULT.withHints(DataAccessHint.RANDOM))
239+
);
240+
241+
} catch (Exception e) {
242+
throw new RuntimeException("Failed to verify read advice is set to ADVISE_BY_CONTEXT: ", e);
243+
}
244+
245+
}
246+
247+
@SuppressForbidden(reason = "need reflection to access private readAdvice field for testing")
248+
private Object getReadAdviceField(MMapDirectory mMapDirectory) throws Exception {
249+
Field readAdviceField = MMapDirectory.class.getDeclaredField("readAdvice");
250+
readAdviceField.setAccessible(true);
251+
return readAdviceField.get(mMapDirectory);
252+
}
253+
197254
}

0 commit comments

Comments
 (0)