109
109
import org .opensearch .core .xcontent .XContentParser ;
110
110
import org .opensearch .index .mapper .MapperService ;
111
111
import org .opensearch .index .remote .RemoteStorePathStrategy ;
112
+ import org .opensearch .index .remote .RemoteStorePathStrategy .BasePathInput ;
112
113
import org .opensearch .index .snapshots .IndexShardRestoreFailedException ;
113
114
import org .opensearch .index .snapshots .IndexShardSnapshotStatus ;
114
115
import org .opensearch .index .snapshots .blobstore .BlobStoreIndexShardSnapshot ;
158
159
import java .util .List ;
159
160
import java .util .Locale ;
160
161
import java .util .Map ;
162
+ import java .util .Objects ;
161
163
import java .util .Optional ;
162
164
import java .util .Set ;
163
165
import java .util .concurrent .BlockingQueue ;
175
177
import java .util .stream .LongStream ;
176
178
import java .util .stream .Stream ;
177
179
180
+ import static org .opensearch .index .remote .RemoteStoreEnums .PathHashAlgorithm .FNV_1A_COMPOSITE_1 ;
181
+ import static org .opensearch .index .remote .RemoteStoreEnums .PathType .HASHED_PREFIX ;
178
182
import static org .opensearch .index .snapshots .blobstore .BlobStoreIndexShardSnapshot .FileInfo .canonicalName ;
179
183
import static org .opensearch .repositories .blobstore .ChecksumBlobStoreFormat .SNAPSHOT_ONLY_FORMAT_PARAMS ;
180
184
@@ -303,6 +307,16 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
303
307
Setting .Property .NodeScope
304
308
);
305
309
310
+ /**
311
+ * Setting to enable prefix mode verification. In this mode, a hashed string is prepended at the prefix of the base
312
+ * path during repository verification.
313
+ */
314
+ public static final Setting <Boolean > PREFIX_MODE_VERIFICATION_SETTING = Setting .boolSetting (
315
+ "prefix_mode_verification" ,
316
+ false ,
317
+ Setting .Property .NodeScope
318
+ );
319
+
306
320
protected volatile boolean supportURLRepo ;
307
321
308
322
private volatile int maxShardBlobDeleteBatch ;
@@ -370,6 +384,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
370
384
371
385
private final boolean isSystemRepository ;
372
386
387
+ private final boolean prefixModeVerification ;
388
+
373
389
private final Object lock = new Object ();
374
390
375
391
private final SetOnce <BlobContainer > blobContainer = new SetOnce <>();
@@ -430,6 +446,7 @@ protected BlobStoreRepository(
430
446
readRepositoryMetadata (repositoryMetadata );
431
447
432
448
isSystemRepository = SYSTEM_REPOSITORY_SETTING .get (metadata .settings ());
449
+ prefixModeVerification = PREFIX_MODE_VERIFICATION_SETTING .get (metadata .settings ());
433
450
this .namedXContentRegistry = namedXContentRegistry ;
434
451
this .threadPool = clusterService .getClusterApplierService ().threadPool ();
435
452
this .clusterService = clusterService ;
@@ -772,6 +789,10 @@ protected BlobStore getBlobStore() {
772
789
return blobStore .get ();
773
790
}
774
791
792
+ boolean getPrefixModeVerification () {
793
+ return prefixModeVerification ;
794
+ }
795
+
775
796
/**
776
797
* maintains single lazy instance of {@link BlobContainer}
777
798
*/
@@ -2004,7 +2025,7 @@ public String startVerification() {
2004
2025
} else {
2005
2026
String seed = UUIDs .randomBase64UUID ();
2006
2027
byte [] testBytes = Strings .toUTF8Bytes (seed );
2007
- BlobContainer testContainer = blobStore (). blobContainer ( basePath (). add ( testBlobPrefix ( seed )) );
2028
+ BlobContainer testContainer = testContainer ( seed );
2008
2029
BytesArray bytes = new BytesArray (testBytes );
2009
2030
if (isSystemRepository == false ) {
2010
2031
try (InputStream stream = bytes .streamInput ()) {
@@ -2022,12 +2043,26 @@ public String startVerification() {
2022
2043
}
2023
2044
}
2024
2045
2046
+ /**
2047
+ * Returns the blobContainer depending on the seed and {@code prefixModeVerification}.
2048
+ */
2049
+ private BlobContainer testContainer (String seed ) {
2050
+ BlobPath testBlobPath ;
2051
+ if (prefixModeVerification == true ) {
2052
+ BasePathInput pathInput = BasePathInput .builder ().basePath (basePath ()).indexUUID (seed ).build ();
2053
+ testBlobPath = HASHED_PREFIX .path (pathInput , FNV_1A_COMPOSITE_1 );
2054
+ } else {
2055
+ testBlobPath = basePath ();
2056
+ }
2057
+ assert Objects .nonNull (testBlobPath );
2058
+ return blobStore ().blobContainer (testBlobPath .add (testBlobPrefix (seed )));
2059
+ }
2060
+
2025
2061
@ Override
2026
2062
public void endVerification (String seed ) {
2027
2063
if (isReadOnly () == false ) {
2028
2064
try {
2029
- final String testPrefix = testBlobPrefix (seed );
2030
- blobStore ().blobContainer (basePath ().add (testPrefix )).delete ();
2065
+ testContainer (seed ).delete ();
2031
2066
} catch (Exception exp ) {
2032
2067
throw new RepositoryVerificationException (metadata .name (), "cannot delete test data at " + basePath (), exp );
2033
2068
}
@@ -3404,7 +3439,7 @@ public void verify(String seed, DiscoveryNode localNode) {
3404
3439
);
3405
3440
}
3406
3441
} else {
3407
- BlobContainer testBlobContainer = blobStore (). blobContainer ( basePath (). add ( testBlobPrefix ( seed )) );
3442
+ BlobContainer testBlobContainer = testContainer ( seed );
3408
3443
try {
3409
3444
BytesArray bytes = new BytesArray (seed );
3410
3445
try (InputStream stream = bytes .streamInput ()) {
0 commit comments